From 1ea65f0285d7022ce20ef84d4e35e3c94bcb3fbd Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 27 Mar 2012 22:56:02 -0700 Subject: CHUI-51 WIP notifications routig code cleanup phase 1, removal of most of llnotificationhandler --- indra/llui/llnotifications.cpp | 50 +++--- indra/llui/llnotifications.h | 21 +-- indra/llui/llnotificationtemplate.h | 10 +- indra/newview/llbrowsernotification.cpp | 5 +- indra/newview/llchiclet.cpp | 9 +- indra/newview/llfloaternotificationsconsole.cpp | 2 +- indra/newview/llfloateroutbox.cpp | 51 +----- indra/newview/llfloateroutbox.h | 2 +- indra/newview/llimhandler.cpp | 82 +++++----- indra/newview/llnearbychathandler.cpp | 8 +- indra/newview/llnearbychathandler.h | 3 +- indra/newview/llnotificationalerthandler.cpp | 99 +++++------- indra/newview/llnotificationgrouphandler.cpp | 50 +++--- indra/newview/llnotificationhandler.h | 143 ++++++----------- indra/newview/llnotificationhandlerutil.cpp | 126 ++------------- indra/newview/llnotificationhinthandler.cpp | 26 +--- indra/newview/llnotificationmanager.cpp | 90 ++--------- indra/newview/llnotificationmanager.h | 11 +- indra/newview/llnotificationofferhandler.cpp | 172 ++++++++++----------- indra/newview/llnotificationscripthandler.cpp | 89 +++++------ indra/newview/llnotificationtiphandler.cpp | 117 ++++++-------- indra/newview/llscreenchannel.h | 14 +- indra/newview/llsyswellwindow.cpp | 11 +- indra/newview/lltoastgroupnotifypanel.cpp | 2 +- indra/newview/lltoastgroupnotifypanel.h | 2 +- indra/newview/lltoastnotifypanel.cpp | 4 +- indra/newview/lltoastnotifypanel.h | 4 +- indra/newview/llviewermessage.cpp | 2 - indra/newview/llviewerwindow.cpp | 8 +- .../newview/skins/default/xui/en/notifications.xml | 22 +++ 30 files changed, 435 insertions(+), 800 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d232e27ef2..038a86d20a 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -409,7 +409,9 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mUnique(p.unique.isProvided()), mPriority(p.priority), mPersist(p.persist), - mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()) + mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), + mLogToChat(p.log_to_chat), + mLogToIM(p.log_to_im) { if (p.sound.isProvided() && LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -886,6 +888,24 @@ std::string LLNotification::getURL() const return (mTemplatep ? url : ""); } +bool LLNotification::canLogToChat() const +{ + return mTemplatep->mLogToChat; +} + +bool LLNotification::canLogToIM() const +{ + return mTemplatep->mLogToIM; +} + +bool LLNotification::hasFormElements() const +{ + return mTemplatep->mForm->getNumElements() != 0; +} + + + + // ========================================================= // LLNotificationChannel implementation // --- @@ -1051,20 +1071,6 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt return abortProcessing; } -/* static */ -LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name, - const std::string& parent, - LLNotificationFilter filter, - LLNotificationComparator comparator) -{ - // note: this is not a leak; notifications are self-registering. - // This factory helps to prevent excess deletions by making sure all smart - // pointers to notification channels come from the same source - new LLNotificationChannel(name, parent, filter, comparator); - return LLNotifications::instance().getChannel(name); -} - - LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter, @@ -1272,19 +1278,19 @@ void LLNotifications::createDefaultChannels() { // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file - LLNotificationChannel::buildChannel("Enabled", "", + new LLNotificationChannel("Enabled", "", !boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); - LLNotificationChannel::buildChannel("Expiration", "Enabled", + new LLNotificationChannel("Expiration", "Enabled", boost::bind(&LLNotifications::expirationFilter, this, _1)); - LLNotificationChannel::buildChannel("Unexpired", "Enabled", + new LLNotificationChannel("Unexpired", "Enabled", !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind - LLNotificationChannel::buildChannel("Unique", "Unexpired", + new LLNotificationChannel("Unique", "Unexpired", boost::bind(&LLNotifications::uniqueFilter, this, _1)); - LLNotificationChannel::buildChannel("Ignore", "Unique", + new LLNotificationChannel("Ignore", "Unique", filterIgnoredNotifications); - LLNotificationChannel::buildChannel("VisibilityRules", "Ignore", + new LLNotificationChannel("VisibilityRules", "Ignore", boost::bind(&LLNotifications::isVisibleByRules, this, _1)); - LLNotificationChannel::buildChannel("Visible", "VisibilityRules", + new LLNotificationChannel("Visible", "VisibilityRules", &LLNotificationFilters::includeEverything); // create special persistent notification channel diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 462d69be2e..f83365a97d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -513,7 +513,10 @@ public: std::string getURL() const; S32 getURLOption() const; S32 getURLOpenExternally() const; - + bool canLogToChat() const; + bool canLogToIM() const; + bool hasFormElements() const; + const LLNotificationFormPtr getForm(); const LLDate getExpiration() const @@ -791,13 +794,6 @@ typedef boost::shared_ptr LLNotificationChannelPtr; // of a queue with notifications being added to different nonequivalent copies. So we // make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. // -// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to -// do something like: -// LLNotificationChannel::buildChannel("name", "parent"...); -// This returns an LLNotificationChannelPtr, which you can store, or -// you can then retrieve the channel by using the registry: -// LLNotifications::instance().getChannel("name")... -// class LLNotificationChannel : boost::noncopyable, public LLNotificationChannelBase @@ -822,20 +818,13 @@ public: std::string summarize(); - // factory method for constructing these channels; since they're self-registering, - // we want to make sure that you can't use new to make them - static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter=LLNotificationFilters::includeEverything, - LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); - -protected: // Notification Channels have a filter, which determines which notifications // will be added to this channel. // Channel filters cannot change. // Channels have a protected constructor so you can't make smart pointers that don't // come from our internal reference; call NotificationChannel::build(args) LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator); + LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); private: std::string mName; diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index fb50c9c123..1df7205b23 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -170,7 +170,9 @@ struct LLNotificationTemplate struct Params : public LLInitParam::Block { Mandatory name; - Optional persist; + Optional persist, + log_to_im, + log_to_chat; Optional functor, icon, label, @@ -190,6 +192,8 @@ struct LLNotificationTemplate Params() : name("name"), persist("persist", false), + log_to_im("log_to_im", false), + log_to_chat("log_to_chat", false), functor("functor"), icon("icon"), label("label"), @@ -291,6 +295,10 @@ struct LLNotificationTemplate LLUUID mSoundEffect; // List of tags that rules can match against. std::list mTags; + + // inject these notifications into chat/IM streams + bool mLogToChat; + bool mLogToIM; }; #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 6e77d1e336..9e608d2c8b 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,11 +35,8 @@ using namespace LLNotificationsUI; -bool LLBrowserNotification::processNotification(const LLSD& notify) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) { - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - if (!notification) return false; - LLUUID media_id = notification->getPayload()["media_id"].asUUID(); LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id); if (media_instance) diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index aabab0ccb9..9f19f8dd1c 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -339,9 +339,9 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) , mUreadSystemNotifications(0) { // connect counter handlers to the signals - connectCounterUpdatersToSignal("notify"); - connectCounterUpdatersToSignal("groupnotify"); - connectCounterUpdatersToSignal("offer"); + connectCounterUpdatersToSignal("Notify"); + connectCounterUpdatersToSignal("Group Notify"); + connectCounterUpdatersToSignal("Offer"); // ensure that notification well window exists, to synchronously // handle toast add/delete events. @@ -350,8 +350,7 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) { - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast(LLNotifications::instance().getChannel(notification_type).get()); if(n_handler) { n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 2681d4b34d..90dbabebfb 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -57,7 +57,7 @@ LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChann { mChannelPtr = LLNotifications::instance().getChannel(p.name); mChannelRejectsPtr = LLNotificationChannelPtr( - LLNotificationChannel::buildChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), + new LLNotificationChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), !boost::bind(mChannelPtr->getFilter(), _1))); buildFromFile( "panel_notifications_channel.xml"); } diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 540f977305..2a2b231b53 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -44,14 +44,12 @@ #include "llviewernetwork.h" #include "llwindowshade.h" -#define USE_WINDOWSHADE_DIALOGS 0 - ///---------------------------------------------------------------------------- /// LLOutboxNotification class ///---------------------------------------------------------------------------- -bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify) { LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance("outbox"); @@ -516,52 +514,11 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) updateView(); } -void LLFloaterOutbox::showNotification(const LLSD& notify) +void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) { - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (!notification) - { - llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; - - return; - } - -#if USE_WINDOWSHADE_DIALOGS - - if (mWindowShade) - { - delete mWindowShade; - } - - LLRect floater_rect = getLocalRect(); - floater_rect.mTop -= getHeaderHeight(); - floater_rect.stretch(-5, 0); - - LLWindowShade::Params params; - params.name = "notification_shade"; - params.rect = floater_rect; - params.follows.flags = FOLLOWS_ALL; - params.modal = true; - params.can_close = false; - params.shade_color = LLColor4::white % 0.25f; - params.text_color = LLColor4::white; - - mWindowShade = LLUICtrlFactory::create(params); - - addChild(mWindowShade); - mWindowShade->show(notification); - -#else - - LLNotificationsUI::LLEventHandler * handler = - LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); - - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast(handler); + LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast(LLNotifications::instance().getChannel("AlertModal").get()); llassert(sys_handler); - sys_handler->processNotification(notify); - -#endif + sys_handler->processNotification(notification); } diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 18baccf1c9..a91d8c1139 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -64,7 +64,7 @@ public: EAcceptance* accept, std::string& tooltip_msg); - void showNotification(const LLSD& notify); + void showNotification(const LLNotificationPtr& notification); BOOL handleHover(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index cd71da7393..a92c4fa387 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -37,10 +37,9 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) +LLIMHandler::LLIMHandler() +: LLSysHandler("IM Notifications", "notifytoast") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); } @@ -59,62 +58,51 @@ void LLIMHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLSD& notify) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { - LLSD substitutions = notification->getSubstitutions(); - - // According to comments in LLIMMgr::addMessage(), if we get message - // from ourselves, the sender id is set to null. This fixes EXT-875. - LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); - if (avatar_id.isNull()) - avatar_id = gAgentID; - - LLToastIMPanel::Params im_p; - im_p.notification = notification; - im_p.avatar_id = avatar_id; - im_p.from = substitutions["FROM"].asString(); - im_p.time = substitutions["TIME"].asString(); - im_p.message = substitutions["MESSAGE"].asString(); - im_p.session_id = substitutions["SESSION_ID"].asUUID(); - - LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.session_id = im_p.session_id; - p.notification = notification; - p.panel = im_box; - p.can_be_stored = false; - p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); - - // send a signal to the counter manager; - mNewNotificationSignal(); - } - else if (notify["sigtype"].asString() == "delete") - { - mChannel->killToastByNotificationID(notification->getID()); - } + LLSD substitutions = notification->getSubstitutions(); + + // According to comments in LLIMMgr::addMessage(), if we get message + // from ourselves, the sender id is set to null. This fixes EXT-875. + LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); + if (avatar_id.isNull()) + avatar_id = gAgentID; + + LLToastIMPanel::Params im_p; + im_p.notification = notification; + im_p.avatar_id = avatar_id; + im_p.from = substitutions["FROM"].asString(); + im_p.time = substitutions["TIME"].asString(); + im_p.message = substitutions["MESSAGE"].asString(); + im_p.session_id = substitutions["SESSION_ID"].asUUID(); + + LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; + p.notification = notification; + p.panel = im_box; + p.can_be_stored = false; + p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); + + // send a signal to the counter manager; + mNewNotificationSignal(); + return false; } diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 240a7c7a35..269b42bbe9 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -445,10 +445,8 @@ void LLNearbyChatScreenChannel::arrangeToasts() //----------------------------------------------------------------------------------------------- boost::scoped_ptr LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); -LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) +LLNearbyChatHandler::LLNearbyChatHandler() { - mType = type; - // Getting a Channel for our notifications LLNearbyChatScreenChannel::Params p; p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); @@ -614,10 +612,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } -void LLNearbyChatHandler::onDeleteToast(LLToast* toast) -{ -} - //----------------------------------------------------------------------------------------------- // LLNearbyChatToast diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index b0e4f62d51..a5034ac1cb 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -37,14 +37,13 @@ namespace LLNotificationsUI{ class LLNearbyChatHandler : public LLChatHandler { public: - LLNearbyChatHandler(e_notification_type type,const LLSD& id); + LLNearbyChatHandler(); virtual ~LLNearbyChatHandler(); virtual void processChat(const LLChat& chat_msg, const LLSD &args); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); static boost::scoped_ptr sChatWatcher; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index cae7d02fed..e6239534f7 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -40,10 +40,10 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false) +LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal) +: LLSysHandler(name, notification_type), + mIsModal(is_modal) { - mType = type; - LLScreenChannelBase::Params p; p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID")); p.display_toasts_always = true; @@ -68,79 +68,58 @@ void LLAlertHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLSD& notify) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") + if (notification->canLogToIM() && notification->hasFormElements()) { - if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); - - LLUUID from_id = notification->getPayload()["from_id"]; - - // firstly create session... - LLHandlerUtil::spawnIMSession(name, from_id); - - // ...then log message to have IM Well notified about new message - LLHandlerUtil::logToIMP2P(notification); - } - - LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = dynamic_cast(alert_dialog); - p.enable_hide_btn = false; - p.can_fade = false; - p.is_modal = mIsModal; - p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - - // Show alert in middle of progress view (during teleport) (EXT-1093) - LLProgressView* progress = gViewerWindow->getProgressView(); - LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); - mChannel->updatePositionAndSize(rc); - - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); - } - else if (notify["sigtype"].asString() == "change") - { - LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); - } - else - { - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->killToastByNotificationID(notification->getID()); + const std::string name = LLHandlerUtil::getSubstitutionName(notification); + + LLUUID from_id = notification->getPayload()["from_id"]; + + // firstly create session... + LLHandlerUtil::spawnIMSession(name, from_id); + + // ...then log message to have IM Well notified about new message + LLHandlerUtil::logToIMP2P(notification); } + + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = dynamic_cast(alert_dialog); + p.enable_hide_btn = false; + p.can_fade = false; + p.is_modal = mIsModal; + p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + + // Show alert in middle of progress view (during teleport) (EXT-1093) + LLProgressView* progress = gViewerWindow->getProgressView(); + LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); + mChannel->updatePositionAndSize(rc); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); + return false; } -//-------------------------------------------------------------------------- - -void LLAlertHandler::onDeleteToast(LLToast* toast) +void LLAlertHandler::onChange( LLNotificationPtr notification ) { + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 9b7fdaef82..2ce51fa094 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -37,15 +37,14 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) +LLGroupHandler::LLGroupHandler() +: LLSysHandler("Group Notifications", "groupnotify") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -62,48 +61,37 @@ void LLGroupHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLSD& notify) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { - LLHandlerUtil::logGroupNoticeToIMGroup(notification); + LLHandlerUtil::logGroupNoticeToIMGroup(notification); + + LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); - LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); + // send a signal to the counter manager + mNewNotificationSignal(); - // send a signal to the counter manager - mNewNotificationSignal(); + LLGroupActions::refresh_notices(); - LLGroupActions::refresh_notices(); - } - else if (notify["sigtype"].asString() == "delete") - { - mChannel->killToastByNotificationID(notification->getID()); - } return false; } @@ -123,7 +111,7 @@ void LLGroupHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 23dbb6b047..ff9371f7df 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -30,7 +30,7 @@ #include "llwindow.h" -//#include "llnotificationsutil.h" +#include "llnotifications.h" #include "llchannelmanager.h" #include "llchat.h" #include "llinstantmessage.h" @@ -40,20 +40,6 @@ class LLIMFloater; namespace LLNotificationsUI { -// ENotificationType enumerates all possible types of notifications that could be met -// -typedef enum e_notification_type -{ - NT_NOTIFY, - NT_NOTIFYTIP, - NT_GROUPNOTIFY, - NT_IMCHAT, - NT_GROUPCHAT, - NT_NEARBYCHAT, - NT_ALERT, - NT_ALERTMODAL, - NT_OFFER -} ENotificationType; /** * Handler of notification events. @@ -95,7 +81,7 @@ public: boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } protected: - virtual void onDeleteToast(LLToast* toast)=0; + virtual void onDeleteToast(LLToast* toast) {} // arrange handler's channel on a screen // is necessary to unbind a moment of creation of a channel and a moment of positioning of it @@ -104,8 +90,6 @@ protected: virtual void initChannel()=0; LLScreenChannelBase* mChannel; - e_notification_type mType; - }; // LLSysHandler and LLChatHandler are more specific base classes @@ -115,13 +99,18 @@ protected: /** * Handler for system notifications. */ -class LLSysHandler : public LLEventHandler +class LLSysHandler : public LLEventHandler, public LLNotificationChannel { public: - LLSysHandler(); + LLSysHandler(const std::string& name, const std::string& notification_type); virtual ~LLSysHandler() {}; - virtual bool processNotification(const LLSD& notify)=0; + // base interface functions + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());} + + virtual bool processNotification(const LLNotificationPtr& notify)=0; protected : static void init(); @@ -149,13 +138,11 @@ public: class LLIMHandler : public LLSysHandler { public: - LLIMHandler(e_notification_type type, const LLSD& id); + LLIMHandler(); virtual ~LLIMHandler(); - // base interface functions - virtual bool processNotification(const LLSD& notify); - protected: + bool processNotification(const LLNotificationPtr& p); virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); }; @@ -167,14 +154,13 @@ protected: class LLTipHandler : public LLSysHandler { public: - LLTipHandler(e_notification_type type, const LLSD& id); + LLTipHandler(); virtual ~LLTipHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void onRejectToast(const LLUUID& id); virtual void initChannel(); }; @@ -186,11 +172,12 @@ protected: class LLScriptHandler : public LLSysHandler { public: - LLScriptHandler(e_notification_type type, const LLSD& id); + LLScriptHandler(); virtual ~LLScriptHandler(); + virtual void onDelete(LLNotificationPtr p); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -207,11 +194,11 @@ protected: class LLGroupHandler : public LLSysHandler { public: - LLGroupHandler(e_notification_type type, const LLSD& id); + LLGroupHandler(); virtual ~LLGroupHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -227,16 +214,16 @@ protected: class LLAlertHandler : public LLSysHandler { public: - LLAlertHandler(e_notification_type type, const LLSD& id); + LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal); virtual ~LLAlertHandler(); - void setAlertMode(bool is_modal) { mIsModal = is_modal; } + /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } // base interface functions - virtual bool processNotification(const LLSD& notify); + virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); bool mIsModal; @@ -249,11 +236,12 @@ protected: class LLOfferHandler : public LLSysHandler { public: - LLOfferHandler(e_notification_type type, const LLSD& id); + LLOfferHandler(); virtual ~LLOfferHandler(); // base interface functions - virtual bool processNotification(const LLSD& notify); + /*virtual*/ void onDelete(LLNotificationPtr notification); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void onDeleteToast(LLToast* toast); @@ -266,84 +254,54 @@ protected: /** * Handler for UI hints. */ -class LLHintHandler : public LLSingleton +class LLHintHandler : public LLNotificationChannel { public: - LLHintHandler(); - virtual ~LLHintHandler(); + LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "hint")) + {} + virtual ~LLHintHandler() {} - // base interface functions - virtual bool processNotification(const LLSD& notify); + /*virtual*/ void onAdd(LLNotificationPtr p); + /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onDelete(LLNotificationPtr p); }; /** * Handler for browser notifications */ -class LLBrowserNotification : public LLSingleton +class LLBrowserNotification : public LLNotificationChannel { public: - virtual bool processNotification(const LLSD& notify); + LLBrowserNotification() + : LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "browser")) + {} + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + bool processNotification(const LLNotificationPtr& p); }; /** * Handler for outbox notifications */ -class LLOutboxNotification : public LLSingleton +class LLOutboxNotification : public LLNotificationChannel { public: - virtual bool processNotification(const LLSD& notify); + LLOutboxNotification() + : LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "outbox")) + {} + /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + bool processNotification(const LLNotificationPtr& p); }; class LLHandlerUtil { public: - /** - * Checks sufficient conditions to log notification message to IM session. - */ - static bool canLogToIM(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to log notification message to nearby chat session. - */ - static bool canLogToNearbyChat(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to spawn IM session. - */ - static bool canSpawnIMSession(const LLNotificationPtr& notification); - - /** - * Checks sufficient conditions to add notification toast panel IM floater. - */ - static bool canAddNotifPanelToIM(const LLNotificationPtr& notification); - - /** - * Checks whether notification can be used multiple times or not. - */ - static bool isNotificationReusable(const LLNotificationPtr& notification); - - /** - * Checks if passed notification can create IM session and be written into it. - * - * This method uses canLogToIM() & canSpawnIMSession(). - */ - static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); - - /** - * Checks if passed notification can create toast. - */ - static bool canSpawnToast(const LLNotificationPtr& notification); - /** * Determines whether IM floater is opened. */ static bool isIMFloaterOpened(const LLNotificationPtr& notification); - /** - * Determines whether IM floater is focused. - */ - static bool isIMFloaterFocused(const LLNotificationPtr& notification); - /** * Writes notification message to IM session. */ @@ -406,13 +364,6 @@ public: */ static void decIMMesageCounter(const LLNotificationPtr& notification); -private: - - /** - * Find IM floater based on "from_id" - */ - static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); - }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1b767e80d4..dca7fda151 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -54,7 +54,8 @@ void LLSysHandler::init() sExclusiveNotificationGroups.push_back(online_offline_group); } -LLSysHandler::LLSysHandler() +LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) +: LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, notification_type)) { if(sExclusiveNotificationGroups.empty()) { @@ -110,119 +111,9 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) } } -const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), - REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), - OBJECT_GIVE_ITEM("ObjectGiveItem"), - OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"), - PAYMENT_RECEIVED("PaymentReceived"), - PAYMENT_SENT("PaymentSent"), - ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), - USER_GIVE_ITEM("UserGiveItem"), - INVENTORY_ACCEPTED("InventoryAccepted"), - INVENTORY_DECLINED("InventoryDeclined"), - OFFER_FRIENDSHIP("OfferFriendship"), - FRIENDSHIP_ACCEPTED("FriendshipAccepted"), - FRIENDSHIP_OFFERED("FriendshipOffered"), - FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"), - FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"), - FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), - SERVER_OBJECT_MESSAGE("ServerObjectMessage"), - TELEPORT_OFFERED("TeleportOffered"), - TELEPORT_OFFER_SENT("TeleportOfferSent"), - IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); +const static std::string OBJECT_GIVE_ITEM("ObjectGiveItem"); - -// static -bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) -{ - return GRANTED_MODIFY_RIGHTS == notification->getName() - || REVOKED_MODIFY_RIGHTS == notification->getName() - || PAYMENT_RECEIVED == notification->getName() - || PAYMENT_SENT == notification->getName() - || OFFER_FRIENDSHIP == notification->getName() - || FRIENDSHIP_OFFERED == notification->getName() - || FRIENDSHIP_ACCEPTED == notification->getName() - || FRIENDSHIP_ACCEPTED_BYME == notification->getName() - || FRIENDSHIP_DECLINED_BYME == notification->getName() - || SERVER_OBJECT_MESSAGE == notification->getName() - || INVENTORY_ACCEPTED == notification->getName() - || INVENTORY_DECLINED == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName() - || TELEPORT_OFFER_SENT == notification->getName() - || IM_SYSTEM_MESSAGE_TIP == notification->getName(); -} - -// static -bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) -{ - return notification->getType() == "notifytip" - && FRIEND_ONLINE != notification->getName() - && FRIEND_OFFLINE != notification->getName() - && INVENTORY_ACCEPTED != notification->getName() - && INVENTORY_DECLINED != notification->getName() - && IM_SYSTEM_MESSAGE_TIP != notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) -{ - return OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) -{ - return canLogToIM(notification) && canSpawnIMSession(notification); -} - -// static -bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) -{ - if(INVENTORY_DECLINED == notification->getName() - || INVENTORY_ACCEPTED == notification->getName()) - { - // return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) - return ! isIMFloaterOpened(notification); - } - - if(FRIENDSHIP_ACCEPTED == notification->getName()) - { - // don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 - return ! isIMFloaterFocused(notification); - } - - if(OFFER_FRIENDSHIP == notification->getName() - || USER_GIVE_ITEM == notification->getName() - || TELEPORT_OFFERED == notification->getName()) - { - // When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 - return ! isIMFloaterOpened(notification); - } - - return true; -} - -// static -LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) +static LLIMFloater* find_im_floater(const LLNotificationPtr& notification) { LLUUID from_id = notification->getPayload()["from_id"]; LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); @@ -234,7 +125,7 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = findIMFloater(notification); + LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { res = im_floater->getVisible() == TRUE; @@ -243,11 +134,11 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) return res; } -bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) +static bool is_IM_floater_focused(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = findIMFloater(notification); + LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { res = im_floater->hasFocus() == TRUE; @@ -335,7 +226,7 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only) { // don't create IM p2p session with objects, it's necessary condition to log - if (notification->getName() != OBJECT_GIVE_ITEM) + //if (notification->getName() != OBJECT_GIVE_ITEM) { LLUUID from_id = notification->getPayload()["from_id"]; @@ -505,3 +396,4 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) arg["participant_unread"] = session->mParticipantUnreadMessageCount; LLIMModel::getInstance()->mNewMsgSignal(arg); } + diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f7163cb04f..47156a3915 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,26 +33,6 @@ using namespace LLNotificationsUI; -LLHintHandler::LLHintHandler() -{ -} - -LLHintHandler::~LLHintHandler() -{ -} - -bool LLHintHandler::processNotification(const LLSD& notify) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - std::string sigtype = notify["sigtype"].asString(); - if (sigtype == "add" || sigtype == "load") - { - LLHints::show(notification); - } - else if (sigtype == "delete") - { - LLHints::hide(notification); - } - return false; -} +void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onChange(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6105eff8ea..394ae2ac21 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -41,7 +41,6 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLNotificationManager::LLNotificationManager() { - mNotifyHandlers.clear(); init(); } @@ -53,88 +52,23 @@ LLNotificationManager::~LLNotificationManager() //-------------------------------------------------------------------------- void LLNotificationManager::init() { - LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "notify")); - LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "notifytip")); - LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "groupnotify")); - LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alert")); - LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alertmodal")); - LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "notifytoast")); - LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "offer")); - LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "hint")); - LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "browser")); - LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "outbox")); - - LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); - LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); - LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); - - mNotifyHandlers["notify"] = boost::shared_ptr(new LLScriptHandler(NT_NOTIFY, LLSD())); - mNotifyHandlers["notifytip"] = boost::shared_ptr(new LLTipHandler(NT_NOTIFY, LLSD())); - mNotifyHandlers["groupnotify"] = boost::shared_ptr(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); - mNotifyHandlers["alert"] = boost::shared_ptr(new LLAlertHandler(NT_ALERT, LLSD())); - mNotifyHandlers["alertmodal"] = boost::shared_ptr(new LLAlertHandler(NT_ALERT, LLSD())); - static_cast(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); - mNotifyHandlers["notifytoast"] = boost::shared_ptr(new LLIMHandler(NT_IMCHAT, LLSD())); - - mNotifyHandlers["nearbychat"] = boost::shared_ptr(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); - mNotifyHandlers["offer"] = boost::shared_ptr(new LLOfferHandler(NT_OFFER, LLSD())); -} - -//-------------------------------------------------------------------------- -bool LLNotificationManager::onNotification(const LLSD& notify) -{ - LLSysHandler* handle = NULL; - - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (!notification) - return false; - - std::string notification_type = notification->getType(); - handle = static_cast(mNotifyHandlers[notification_type].get()); - - if(!handle) - return false; + new LLScriptHandler(); + new LLTipHandler(); + new LLGroupHandler(); + new LLAlertHandler("Alerts", "alert", false); + new LLAlertHandler("AlertModal", "alertmodal", true); + new LLOfferHandler(); + new LLHintHandler(); + new LLBrowserNotification(); + new LLOutboxNotification(); - return handle->processNotification(notify); + mChatHandler = boost::shared_ptr(new LLNearbyChatHandler()); } //-------------------------------------------------------------------------- void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args) { - // check ENotificationType argument - switch(args["type"].asInteger()) - { - case NT_NEARBYCHAT: - { - LLNearbyChatHandler* handle = dynamic_cast(mNotifyHandlers["nearbychat"].get()); - - if(handle) - handle->processChat(msg, args); - } - break; - default: //no need to handle all enum types - break; - } + if(mChatHandler) + mChatHandler->processChat(msg, args); } -//-------------------------------------------------------------------------- -LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type) -{ - std::map >::iterator it = mNotifyHandlers.find(notification_type); - - if(it != mNotifyHandlers.end()) - return (*it).second.get(); - - return NULL; -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 16e82e4cce..4d124e1379 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -56,20 +56,11 @@ public: void init(void); //TODO: combine processing and storage (*) - // this method reacts on system notifications and calls an appropriate handler - bool onNotification(const LLSD& notification); - // this method reacts on chat notifications and calls an appropriate handler void onChat(const LLChat& msg, const LLSD &args); - // get a handler for a certain type of notification - LLEventHandler* getHandlerForNotification(std::string notification_type); - - private: - //TODO (*) - std::map > mNotifyHandlers; - // cruft std::map mChatHandlers; + boost::shared_ptr mChatHandler; }; } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 68fd65be0f..8010417d43 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,17 +40,16 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +LLOfferHandler::LLOfferHandler() +: LLSysHandler("Offer", "offer") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -67,126 +66,118 @@ void LLOfferHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLSD& notify) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") - { + bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // This is an original inventory offer, so add a script floater + LLScriptFloaterManager::instance().onAddNotification(notification->getID()); + } + else + { + notification->setReusable(add_notif_to_im); - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) - { - // This is an original inventory offer, so add a script floater - LLScriptFloaterManager::instance().onAddNotification(notification->getID()); - } - else + LLUUID session_id; + if (add_notif_to_im) { - notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); + const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID session_id; - if (LLHandlerUtil::canSpawnIMSession(notification)) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); + LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID from_id = notification->getPayload()["from_id"]; + session_id = LLHandlerUtil::spawnIMSession(name, from_id); + } - session_id = LLHandlerUtil::spawnIMSession(name, from_id); - } + if (add_notif_to_im) + { + LLHandlerUtil::addNotifPanelToIM(notification); + } - bool show_toast = LLHandlerUtil::canSpawnToast(notification); - bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); - if (add_notid_to_im) + if (notification->getPayload().has("SUPPRESS_TOAST") + && notification->getPayload()["SUPPRESS_TOAST"]) + { + LLNotificationsUtil::cancel(notification); + } + else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification)) + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + // don't close notification on panel destroy since it will be used by IM floater + notify_box->setCloseNotificationOnDestroy(!add_notif_to_im); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); + // we not save offer notifications to the syswell floater that should be added to the IM floater + p.can_be_stored = !add_notif_to_im; + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); + + // if we not add notification to IM - add it to notification well + if (!add_notif_to_im) { - LLHandlerUtil::addNotifPanelToIM(notification); + // send a signal to the counter manager + mNewNotificationSignal(); } + } - if (notification->getPayload().has("SUPPRESS_TOAST") - && notification->getPayload()["SUPPRESS_TOAST"]) - { - LLNotificationsUtil::cancel(notification); - } - else if(show_toast) + if (notification->canLogToIM()) + { + // log only to file if notif panel can be embedded to IM and IM is opened + if (add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - // don't close notification on panel destroy since it will be used by IM floater - notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); - // we not save offer notifications to the syswell floater that should be added to the IM floater - p.can_be_stored = !add_notid_to_im; - - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); - - // if we not add notification to IM - add it to notification well - if (!add_notid_to_im) - { - // send a signal to the counter manager - mNewNotificationSignal(); - } + LLHandlerUtil::logToIMP2P(notification, true); } - - if (LLHandlerUtil::canLogToIM(notification)) + else { - // log only to file if notif panel can be embedded to IM and IM is opened - if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::logToIMP2P(notification, true); - } - else - { - LLHandlerUtil::logToIMP2P(notification); - } + LLHandlerUtil::logToIMP2P(notification); } } } - else if (notify["sigtype"].asString() == "delete") + + return false; +} + +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // Remove original inventory offer script floater + LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + } + else { - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + if (notification->canLogToIM() + && notification->hasFormElements() + && !LLHandlerUtil::isIMFloaterOpened(notification)) { - // Remove original inventory offer script floater - LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); - } - else - { - if (LLHandlerUtil::canAddNotifPanelToIM(notification) - && !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::decIMMesageCounter(notification); - } - mChannel->killToastByNotificationID(notification->getID()); + LLHandlerUtil::decIMMesageCounter(notification); } + mChannel->killToastByNotificationID(notification->getID()); } - - return false; } //-------------------------------------------------------------------------- void LLOfferHandler::onDeleteToast(LLToast* toast) { - if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) + if (!toast->getNotification()->canLogToIM() || !toast->getNotification()->hasFormElements()) { // send a signal to the counter manager mDelNotificationSignal(); @@ -202,11 +193,10 @@ void LLOfferHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this - // don't delete notification since it may be used by IM floater - && !LLHandlerUtil::canAddNotifPanelToIM(notification)) + if (notification + && mItems.find(notification) != mItems.end() + // don't delete notification since it may be used by IM floater + && (!notification->canLogToIM() || !notification->hasFormElements())) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index bbb4d03768..714f14963c 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -42,17 +42,16 @@ static const std::string SCRIPT_DIALOG_GROUP ("ScriptDialogGroup"); static const std::string SCRIPT_LOAD_URL ("LoadWebPage"); //-------------------------------------------------------------------------- -LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +LLScriptHandler::LLScriptHandler() +: LLSysHandler("Notifications", "notify") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); } @@ -70,69 +69,65 @@ void LLScriptHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLSD& notify) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add") + if (notification->canLogToIM()) { - if (LLHandlerUtil::canLogToIM(notification)) - { - LLHandlerUtil::logToIMP2P(notification); - } + LLHandlerUtil::logToIMP2P(notification); + } - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) - { - LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); - } - else - { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(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); - - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - { - channel->addToast(p); - } - - // send a signal to the counter manager - mNewNotificationSignal(); - } + if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + { + LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } - else if (notify["sigtype"].asString() == "delete") + else { - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) - { - LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); - } - else + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(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); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) { - mChannel->killToastByNotificationID(notification->getID()); + channel->addToast(p); } + + // send a signal to the counter manager + mNewNotificationSignal(); } + return false; } + +void LLScriptHandler::onDelete( LLNotificationPtr notification ) +{ + if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + { + LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); + } + else + { + mChannel->killToastByNotificationID(notification->getID()); + } +} + + //-------------------------------------------------------------------------- void LLScriptHandler::onDeleteToast(LLToast* toast) @@ -158,9 +153,7 @@ void LLScriptHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index fb0891c4c5..0b0ac040cb 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -41,16 +41,15 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +LLTipHandler::LLTipHandler() +: LLSysHandler("NotificationTips", "notifytip") { - mType = type; - // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) - channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); + channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); } //-------------------------------------------------------------------------- @@ -67,90 +66,74 @@ void LLTipHandler::initChannel() } //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLSD& notify) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification) { if(!mChannel) { return false; } - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if(!notification) - return false; - // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") + // archive message in nearby chat + if (notification->canLogToChat()) { - // archive message in nearby chat - if (LLHandlerUtil::canLogToNearbyChat(notification)) - { - LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - - // don't show toast if Nearby Chat is opened - LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) - { - return false; - } - } + LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - std::string session_name = notification->getPayload()["SESSION_NAME"]; - const std::string name = notification->getSubstitutions()["NAME"]; - if (session_name.empty()) - { - session_name = name; - } - LLUUID from_id = notification->getPayload()["from_id"]; - if (LLHandlerUtil::canLogToIM(notification)) - { - LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, - notification->getMessage(), from_id, from_id); - } - - if (LLHandlerUtil::canSpawnIMSession(notification)) - { - LLHandlerUtil::spawnIMSession(name, from_id); - } - - // don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) - if (!LLHandlerUtil::canSpawnToast(notification)) + // don't show toast if Nearby Chat is opened + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); + LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); + if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) { return false; } + } - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); - p.panel = notify_box; - p.is_tip = true; - p.can_be_stored = false; - - removeExclusiveNotifications(notification); + std::string session_name = notification->getPayload()["SESSION_NAME"]; + const std::string name = notification->getSubstitutions()["NAME"]; + if (session_name.empty()) + { + session_name = name; + } + LLUUID from_id = notification->getPayload()["from_id"]; + if (notification->canLogToIM()) + { + LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, + notification->getMessage(), from_id, from_id); + } - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); + if (notification->canLogToIM() && notification->hasFormElements()) + { + LLHandlerUtil::spawnIMSession(name, from_id); } - else if (notify["sigtype"].asString() == "delete") + + if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification)) { - mChannel->killToastByNotificationID(notification->getID()); + return false; } - return false; -} -//-------------------------------------------------------------------------- -void LLTipHandler::onDeleteToast(LLToast* toast) -{ + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); + p.panel = notify_box; + p.is_tip = true; + p.can_be_stored = false; + + removeExclusiveNotifications(notification); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); + + + return false; } //-------------------------------------------------------------------------- @@ -159,9 +142,7 @@ void LLTipHandler::onRejectToast(const LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && LLNotificationManager::getInstance()->getHandlerForNotification( - notification->getType()) == this) + if (notification && mItems.find(notification) != mItems.end()) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index c9f8855fe6..2ea5b8e546 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -228,16 +228,16 @@ public: // Channel's signals // signal on storing of faded toasts event - typedef boost::function store_tost_callback_t; - typedef boost::signals2::signal store_tost_signal_t; - store_tost_signal_t mOnStoreToast; - boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } + typedef boost::signals2::signal store_toast_signal_t; + boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); } // signal on rejecting of a toast event - typedef boost::function reject_tost_callback_t; - typedef boost::signals2::signal reject_tost_signal_t; - reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } + typedef boost::signals2::signal reject_toast_signal_t; + boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); } private: + store_toast_signal_t mOnStoreToast; + reject_toast_signal_t mRejectToastSignal; + struct ToastElem { LLUUID id; diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..e8293ebe2b 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -437,9 +437,9 @@ LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) : LLSysWellWindow(key) { // init connections to the list's update events - connectListUpdaterToSignal("notify"); - connectListUpdaterToSignal("groupnotify"); - connectListUpdaterToSignal("offer"); + connectListUpdaterToSignal("Notifications"); + connectListUpdaterToSignal("Group Notifications"); + connectListUpdaterToSignal("Offer"); } // static @@ -519,7 +519,7 @@ void LLNotificationWellWindow::initChannel() LLSysWellWindow::initChannel(); if(mChannel) { - mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); + mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); } } @@ -548,8 +548,7 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) { - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast(LLNotifications::instance().getChannel(notification_type).get()); if(n_handler) { n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..707d2d9765 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,7 +51,7 @@ const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 7; -LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) +LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notification) : LLToastPanel(notification), mInventoryOffer(NULL) { diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 7794ec9f63..3b8b31eac1 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -53,7 +53,7 @@ public: // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". - LLToastGroupNotifyPanel(LLNotificationPtr& notification); + LLToastGroupNotifyPanel(const LLNotificationPtr& notification); /*virtual*/ ~LLToastGroupNotifyPanel(); protected: diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index de305bf3d9..dc5cc88dc4 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -52,7 +52,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect, bool show_images) : +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), mTextBox(NULL), mInfoPanel(NULL), @@ -536,7 +536,7 @@ void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id } } -void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) +void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) { LLSD response = notification->getResponse(); for (LLSD::map_const_iterator response_it = response.beginMap(); diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 57711b3d80..db517ec858 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -60,7 +60,7 @@ public: * @deprecated if you intend to instantiate LLToastNotifyPanel - it's point to * implement right class for desired toast panel. @see LLGenericTipPanel as example. */ - LLToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } @@ -118,7 +118,7 @@ protected: /** * Process response data. Will disable selected options */ - void disableRespondedOptions(LLNotificationPtr& notification); + void disableRespondedOptions(const LLNotificationPtr& notification); bool mIsTip; bool mAddedDefaultBtn; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3c6770df43..4f83d9096c 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2776,7 +2776,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mOwnerID = from_id; LLSD args; args["slurl"] = location; - args["type"] = LLNotificationsUI::NT_NEARBYCHAT; // Look for IRC-style emotes here so object name formatting is correct std::string prefix = message.substr(0, 4); @@ -3379,7 +3378,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // pass owner_id to chat so that we can display the remote // object inspect for an object that is chatting with you LLSD args; - args["type"] = LLNotificationsUI::NT_NEARBYCHAT; chat.mOwnerID = owner_id; if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e0653fec30..6d9b8b4eb3 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1548,11 +1548,11 @@ LLViewerWindow::LLViewerWindow(const Params& p) mViewerWindowListener(new LLViewerWindowListener(this)), mProgressView(NULL) { - LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alert")); - LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alertmodal")); + LLNotificationChannelPtr vw_alerts_channel(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alert"))); + LLNotificationChannelPtr vw_alerts_modal_channel(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alertmodal"))); - LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert); - LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert); + vw_alerts_channel->connectChanged(&LLViewerWindow::onAlert); + vw_alerts_modal_channel->connectChanged(&LLViewerWindow::onAlert); LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications")); llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index af75d49353..da83ffbab4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2904,6 +2904,7 @@ Would you like to trust this authority? icon="alertmodal.tga" name="GrantedModifyRights" persist="true" + log_to_im="true" type="notify"> [NAME] has given you permission to edit their objects. @@ -2912,6 +2913,7 @@ Would you like to trust this authority? icon="alertmodal.tga" name="RevokedModifyRights" persist="true" + log_to_im="true" type="notify"> Your privilege to modify [NAME]'s objects has been revoked @@ -5161,6 +5163,8 @@ The string [STRING_NAME] is missing from strings.xml [MESSAGE] @@ -5205,6 +5209,7 @@ Topic: [SUBJECT], Message: [MESSAGE] friendship <nolink>[NAME]</nolink> is Online @@ -5213,6 +5218,7 @@ Topic: [SUBJECT], Message: [MESSAGE] friendship <nolink>[NAME]</nolink> is Offline @@ -5459,6 +5465,8 @@ You don't have permission to copy this. [NAME] received your inventory offer. @@ -5466,6 +5474,8 @@ You don't have permission to copy this. [NAME] declined your inventory offer. @@ -5547,6 +5557,7 @@ Please select at least one type of content to search (General, Moderate, or Adul funds @@ -5556,6 +5567,7 @@ Please select at least one type of content to search (General, Moderate, or Adul funds @@ -5700,6 +5712,7 @@ The objects on the selected parcel that are NOT owned by you have been returned Message from [NAME]: @@ -6070,6 +6083,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th [NAME_SLURL] has given you this [OBJECTTYPE]: [ITEM_SLURL] @@ -6125,6 +6139,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th [NAME_SLURL] has offered to teleport you to their location: @@ -6145,6 +6160,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th Teleport offer sent to [TO_NAME] @@ -6172,6 +6188,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th friendship confirm @@ -6195,6 +6212,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th friendship You have offered friendship to [TO_NAME] @@ -6224,6 +6242,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th friendship <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6232,6 +6251,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th friendship @@ -6241,6 +6261,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th friendship Friendship offer accepted. @@ -6249,6 +6270,7 @@ Friendship offer accepted. friendship Friendship offer declined. -- cgit v1.2.3 From 27ce5c301633fa75c32087e347347ab9111aa787 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 28 Mar 2012 11:27:48 -0700 Subject: CHUI-51 WIP notifications routing code cleanup fixed crash on login --- indra/newview/llchiclet.cpp | 4 ++-- indra/newview/llnotificationmanager.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 9f19f8dd1c..5e07db0d59 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -339,8 +339,8 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) , mUreadSystemNotifications(0) { // connect counter handlers to the signals - connectCounterUpdatersToSignal("Notify"); - connectCounterUpdatersToSignal("Group Notify"); + connectCounterUpdatersToSignal("IM Notifications"); + connectCounterUpdatersToSignal("Group Notifications"); connectCounterUpdatersToSignal("Offer"); // ensure that notification well window exists, to synchronously diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 394ae2ac21..4e77b38757 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -52,6 +52,7 @@ LLNotificationManager::~LLNotificationManager() //-------------------------------------------------------------------------- void LLNotificationManager::init() { + new LLIMHandler(); new LLScriptHandler(); new LLTipHandler(); new LLGroupHandler(); -- cgit v1.2.3 From 2fa1c42aadbe2a29e1bcced9a487c0e5abf0602b Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 29 Mar 2012 23:48:29 -0700 Subject: CHUI-51 WIP notifications routig code cleanup phase 2, removal of extraneous signaling in favor of llnotificationchannels made notificationchannels work better with overrides and lifetime managed by creator --- indra/llcommon/llinstancetracker.h | 5 +- indra/llcommon/llrefcount.h | 19 +++++ indra/llcommon/llthread.h | 17 +++++ indra/llui/llnotifications.cpp | 92 +++++++++++++------------ indra/llui/llnotifications.h | 49 ++++++++----- indra/llui/llnotificationslistener.cpp | 8 +-- indra/newview/llchiclet.cpp | 26 +++---- indra/newview/llchiclet.h | 31 +++++++-- indra/newview/llfloaternotificationsconsole.cpp | 38 ++-------- indra/newview/llimhandler.cpp | 12 ---- indra/newview/llnotificationgrouphandler.cpp | 14 ---- indra/newview/llnotificationhandler.h | 23 +------ indra/newview/llnotificationhandlerutil.cpp | 88 ++++++++--------------- indra/newview/llnotificationmanager.cpp | 19 ++--- indra/newview/llnotificationmanager.h | 1 + indra/newview/llnotificationofferhandler.cpp | 42 ++--------- indra/newview/llnotificationscripthandler.cpp | 19 +---- indra/newview/llsyswellwindow.cpp | 37 +++++----- indra/newview/llsyswellwindow.h | 19 +++-- indra/newview/lltoastgroupnotifypanel.h | 3 - indra/newview/lltoastscripttextbox.h | 2 - 21 files changed, 241 insertions(+), 323 deletions(-) diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 34d841a4e0..11f582372e 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -43,7 +43,7 @@ * semantics: one instance per process, rather than one instance per module as * sometimes happens with data simply declared static. */ -class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +class LL_COMMON_API LLInstanceTrackerBase { protected: /// Get a process-unique void* pointer slot for the specified type_info @@ -209,6 +209,9 @@ protected: virtual const KEY& getKey() const { return mInstanceKey; } private: + LLInstanceTracker( const LLInstanceTracker& ); + const LLInstanceTracker& operator=( const LLInstanceTracker& ); + void add_(KEY key) { mInstanceKey = key; diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 8eb5d53f3f..32ae15435a 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -27,6 +27,7 @@ #define LLREFCOUNT_H #include +#include #define LL_REF_COUNT_DEBUG 0 #if LL_REF_COUNT_DEBUG @@ -86,4 +87,22 @@ private: #endif }; +/** + * intrusive pointer support + * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type + */ +namespace boost +{ + inline void intrusive_ptr_add_ref(LLRefCount* p) + { + p->ref(); + } + + inline void intrusive_ptr_release(LLRefCount* p) + { + p->unref(); + } +}; + + #endif diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index b52e70ab2e..cf39696b4f 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -30,6 +30,7 @@ #include "llapp.h" #include "llapr.h" #include "apr_thread_cond.h" +#include "boost/intrusive_ptr.hpp" class LLThread; class LLMutex; @@ -266,6 +267,22 @@ private: S32 mRef; }; +/** + * intrusive pointer support for LLThreadSafeRefCount + * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type + */ +namespace boost +{ + inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) + { + p->ref(); + } + + inline void intrusive_ptr_release(LLThreadSafeRefCount* p) + { + p->unref(); + } +}; //============================================================================ // Simple responder for self destructing callbacks diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 038a86d20a..c45899a4bd 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -966,7 +966,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt std::string cmd = payload["sigtype"]; LLNotificationSet::iterator foundItem = mItems.find(pNotification); bool wasFound = (foundItem != mItems.end()); - bool passesFilter = mFilter(pNotification); + bool passesFilter = mFilter ? mFilter(pNotification) : true; // first, we offer the result of the filter test to the simple // signals for pass/fail. One of these is guaranteed to be called. @@ -1071,27 +1071,28 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt return abortProcessing; } +LLNotificationChannel::LLNotificationChannel(const Params& p) +: LLNotificationChannelBase(p.filter(), p.comparator()), + LLInstanceTracker(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), + mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) +{ + BOOST_FOREACH(const std::string& source, p.sources) + { + connectToChannel(source); + } +} + + LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter, - LLNotificationComparator comparator) : -LLNotificationChannelBase(filter, comparator), -mName(name), -mParent(parent) + LLNotificationComparator comparator) +: LLNotificationChannelBase(filter, comparator), + LLInstanceTracker(name), + mName(name) { - // store myself in the channel map - LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); // bind to notification broadcast - if (parent.empty()) - { - LLNotifications::instance().connectChanged( - boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); - } - else - { - LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); - p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); - } + connectToChannel(parent); } @@ -1134,6 +1135,21 @@ std::string LLNotificationChannel::summarize() return s; } +void LLNotificationChannel::connectToChannel( const std::string& channel_name ) +{ + if (channel_name.empty()) + { + LLNotifications::instance().connectChanged( + boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } + else + { + LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); + p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); + } +} + + // --- // END OF LLNotificationChannel implementation @@ -1248,21 +1264,9 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) return false; } - -void LLNotifications::addChannel(LLNotificationChannelPtr pChan) -{ - mChannels[pChan->getName()] = pChan; -} - LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) { - ChannelMap::iterator p = mChannels.find(channelName); - if(p == mChannels.end()) - { - llerrs << "Did not find channel named " << channelName << llendl; - return LLNotificationChannelPtr(); - } - return p->second; + return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName)); } @@ -1278,20 +1282,20 @@ void LLNotifications::createDefaultChannels() { // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file - new LLNotificationChannel("Enabled", "", - !boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); - new LLNotificationChannel("Expiration", "Enabled", - boost::bind(&LLNotifications::expirationFilter, this, _1)); - new LLNotificationChannel("Unexpired", "Enabled", - !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind - new LLNotificationChannel("Unique", "Unexpired", - boost::bind(&LLNotifications::uniqueFilter, this, _1)); - new LLNotificationChannel("Ignore", "Unique", - filterIgnoredNotifications); - new LLNotificationChannel("VisibilityRules", "Ignore", - boost::bind(&LLNotifications::isVisibleByRules, this, _1)); - new LLNotificationChannel("Visible", "VisibilityRules", - &LLNotificationFilters::includeEverything); + mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", + !boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); + mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", + boost::bind(&LLNotifications::expirationFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", + !boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind + mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", + boost::bind(&LLNotifications::uniqueFilter, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", + filterIgnoredNotifications)); + mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", + boost::bind(&LLNotifications::isVisibleByRules, this, _1))); + mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", + &LLNotificationFilters::includeEverything)); // create special persistent notification channel // this isn't a leak, don't worry about the empty "new" diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index f83365a97d..344108ecbf 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -94,10 +94,11 @@ // and we need this to manage the notification callbacks #include "llevents.h" #include "llfunctorregistry.h" -#include "llpointer.h" #include "llinitparam.h" #include "llnotificationslistener.h" #include "llnotificationptr.h" +#include "llpointer.h" +#include "llrefcount.h" class LLAvatarName; typedef enum e_notification_priority @@ -707,7 +708,8 @@ typedef std::multimap LLNotificationMap; // all of the built-in tests should attach to the "Visible" channel // class LLNotificationChannelBase : - public LLEventTrackable + public LLEventTrackable, + public LLRefCount { LOG_CLASS(LLNotificationChannelBase); public: @@ -787,26 +789,48 @@ protected: // destroy it, but if it becomes necessary to do so, the shared_ptr model // will ensure that we don't leak resources. class LLNotificationChannel; -typedef boost::shared_ptr LLNotificationChannelPtr; +typedef boost::intrusive_ptr LLNotificationChannelPtr; // manages a list of notifications // Note that if this is ever copied around, we might find ourselves with multiple copies // of a queue with notifications being added to different nonequivalent copies. So we -// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. +// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it. // class LLNotificationChannel : boost::noncopyable, - public LLNotificationChannelBase + public LLNotificationChannelBase, + public LLInstanceTracker { LOG_CLASS(LLNotificationChannel); public: + // Notification Channels have a filter, which determines which notifications + // will be added to this channel. + // Channel filters cannot change. + struct Params : public LLInitParam::Block + { + Mandatory name; + Optional filter; + Optional comparator; + Multiple sources; + + Params() + : comparator("", LLNotificationComparators::orderByUUID()) + {} + }; + + LLNotificationChannel(const Params& p = Params()); + + LLNotificationChannel(const std::string& name, const std::string& parent, + LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); + virtual ~LLNotificationChannel() {} typedef LLNotificationSet::iterator Iterator; std::string getName() const { return mName; } - std::string getParentChannelName() { return mParent; } + void connectToChannel(const std::string& channel_name); + bool isEmpty() const; Iterator begin(); @@ -818,14 +842,6 @@ public: std::string summarize(); - // Notification Channels have a filter, which determines which notifications - // will be added to this channel. - // Channel filters cannot change. - // Channels have a protected constructor so you can't make smart pointers that don't - // come from our internal reference; call NotificationChannel::build(args) - LLNotificationChannel(const std::string& name, const std::string& parent, - LLNotificationFilter filter, LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); - private: std::string mName; std::string mParent; @@ -912,10 +928,6 @@ public: void createDefaultChannels(); - typedef std::map ChannelMap; - ChannelMap mChannels; - - void addChannel(LLNotificationChannelPtr pChan); LLNotificationChannelPtr getChannel(const std::string& channelName); std::string getGlobalString(const std::string& key) const; @@ -954,6 +966,7 @@ private: bool mIgnoreAllNotifications; boost::scoped_ptr mListener; + std::vector mDefaultChannels; }; /** diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 3bbeb3a778..e4e127336b 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -121,13 +121,13 @@ void LLNotificationsListener::listChannels(const LLSD& params) const { LLReqID reqID(params); LLSD response(reqID.makeResponse()); - for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), - cmend(mNotifications.mChannels.end()); + for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), + cmend(LLNotificationChannel::endInstances()); cmi != cmend; ++cmi) { LLSD channelInfo; - channelInfo["parent"] = cmi->second->getParentChannelName(); - response[cmi->first] = channelInfo; + //channelInfo["parent"] = cmi->second->getParentChannelName(); + response[cmi->getName()] = channelInfo; } LLEventPumps::instance().obtain(params["reply"]).post(response); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 9f19f8dd1c..67519a3ca6 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -335,29 +335,15 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) /* LLNotificationChiclet implementation */ /************************************************************************/ LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p) -, mUreadSystemNotifications(0) +: LLSysWellChiclet(p), + mUreadSystemNotifications(0) { - // connect counter handlers to the signals - connectCounterUpdatersToSignal("Notify"); - connectCounterUpdatersToSignal("Group Notify"); - connectCounterUpdatersToSignal("Offer"); - + mNotificationChannel.reset(new ChicletNotificationChannel(this)); // ensure that notification well window exists, to synchronously // handle toast add/delete events. LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); } -void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) -{ - LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast(LLNotifications::instance().getChannel(notification_type).get()); - if(n_handler) - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); - } -} - void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) { std::string action = user_data.asString(); @@ -406,6 +392,12 @@ void LLNotificationChiclet::setCounter(S32 counter) updateWidget(getCounter() == 0); } + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notify ) +{ + return !(notify->canLogToIM() && notify->hasFormElements()); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 1f1069dcb4..dd0d47cccd 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@ #include "lloutputmonitorctrl.h" #include "llgroupmgr.h" #include "llimview.h" +#include "llnotifications.h" class LLMenuGL; class LLIMFloater; @@ -911,11 +912,35 @@ protected: class LLNotificationChiclet : public LLSysWellChiclet { + LOG_CLASS(LLNotificationChiclet); + friend class LLUICtrlFactory; public: struct Params : public LLInitParam::Block{}; protected: + struct ChicletNotificationChannel : public LLNotificationChannel + { + ChicletNotificationChannel(LLNotificationChiclet* chiclet) + : LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), + mChiclet(chiclet) + { + // connect counter handlers to the signals + connectToChannel("IM Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); + } + + static bool filterNotification(LLNotificationPtr notify); + // connect counter updaters to the corresponding signals + /*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } + /*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + + LLNotificationChiclet* const mChiclet; + }; + + boost::scoped_ptr mNotificationChannel; + LLNotificationChiclet(const Params& p); /** @@ -933,12 +958,6 @@ protected: */ /*virtual*/ void createMenu(); - // connect counter updaters to the corresponding signals - void connectCounterUpdatersToSignal(const std::string& notification_type); - - // methods for updating a number of unread System notifications - void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } - void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } /*virtual*/ void setCounter(S32 counter); S32 mUreadSystemNotifications; }; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 90dbabebfb..4f35c325a8 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -44,21 +44,16 @@ public: BOOL postBuild(); private: - bool update(const LLSD& payload, bool passed_filter); + bool update(const LLSD& payload); static void toggleClick(void* user_data); static void onClickNotification(void* user_data); - static void onClickNotificationReject(void* user_data); LLNotificationChannelPtr mChannelPtr; - LLNotificationChannelPtr mChannelRejectsPtr; }; LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChannelPanel::Params& p) : LLLayoutPanel(p) { mChannelPtr = LLNotifications::instance().getChannel(p.name); - mChannelRejectsPtr = LLNotificationChannelPtr( - new LLNotificationChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), - !boost::bind(mChannelPtr->getFilter(), _1))); buildFromFile( "panel_notifications_channel.xml"); } @@ -68,15 +63,11 @@ BOOL LLNotificationChannelPanel::postBuild() header_button->setLabel(mChannelPtr->getName()); header_button->setClickedCallback(toggleClick, this); - mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true)); - mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); + mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1)); LLScrollListCtrl* scroll = getChild("notifications_list"); scroll->setDoubleClickCallback(onClickNotification, this); scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); - scroll = getChild("notification_rejects_list"); - scroll->setDoubleClickCallback(onClickNotificationReject, this); - scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); return TRUE; } @@ -97,8 +88,6 @@ void LLNotificationChannelPanel::toggleClick(void *user_data) // turn off tab stop for collapsed panel self->getChild("notifications_list")->setTabStop(!header_button->getToggleState()); self->getChild("notifications_list")->setVisible(!header_button->getToggleState()); - self->getChild("notification_rejects_list")->setTabStop(!header_button->getToggleState()); - self->getChild("notification_rejects_list")->setVisible(!header_button->getToggleState()); } /*static*/ @@ -118,24 +107,7 @@ void LLNotificationChannelPanel::onClickNotification(void* user_data) } } -/*static*/ -void LLNotificationChannelPanel::onClickNotificationReject(void* user_data) -{ - LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data; - if (!self) return; - LLScrollListItem* firstselected = self->getChild("notification_rejects_list")->getFirstSelected(); - llassert(firstselected); - if (firstselected) - { - void* data = firstselected->getUserdata(); - if (data) - { - gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE); - } - } -} - -bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) +bool LLNotificationChannelPanel::update(const LLSD& payload) { LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID()); if (notification) @@ -151,9 +123,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) row["columns"][2]["column"] = "date"; row["columns"][2]["type"] = "date"; - LLScrollListItem* sli = passed_filter ? - getChild("notifications_list")->addElement(row) : - getChild("notification_rejects_list")->addElement(row); + LLScrollListItem* sli = getChild("notifications_list")->addElement(row); sli->setUserdata(&(*notification)); } diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index a92c4fa387..1437d0747c 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -95,24 +95,12 @@ bool LLIMHandler::processNotification(const LLNotificationPtr& notification) p.notification = notification; p.panel = im_box; p.can_be_stored = false; - p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) channel->addToast(p); - // send a signal to the counter manager; - mNewNotificationSignal(); - return false; } -//-------------------------------------------------------------------------- -void LLIMHandler::onDeleteToast(LLToast* toast) -{ - // send a signal to the counter manager - mDelNotificationSignal(); -} - -//-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 2ce51fa094..97e382e42f 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -87,25 +87,11 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) if(channel) channel->addToast(p); - // send a signal to the counter manager - mNewNotificationSignal(); - LLGroupActions::refresh_notices(); return false; } -//-------------------------------------------------------------------------- -void LLGroupHandler::onDeleteToast(LLToast* toast) -{ - // send a signal to the counter manager - mDelNotificationSignal(); - - // send a signal to a listener to let him perform some action - // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); -} - //-------------------------------------------------------------------------- void LLGroupHandler::onRejectToast(LLUUID& id) { diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index ff9371f7df..419b8a14b6 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -67,19 +67,6 @@ class LLEventHandler public: virtual ~LLEventHandler() {}; - // callbacks for counters - typedef boost::function notification_callback_t; - typedef boost::signals2::signal notification_signal_t; - notification_signal_t mNewNotificationSignal; - notification_signal_t mDelNotificationSignal; - boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } - boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } - // callback for notification/toast - typedef boost::function notification_id_callback_t; - typedef boost::signals2::signal notification_id_signal_t; - notification_id_signal_t mNotificationIDSignal; - boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } - protected: virtual void onDeleteToast(LLToast* toast) {} @@ -143,7 +130,6 @@ public: protected: bool processNotification(const LLNotificationPtr& p); - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); }; @@ -201,7 +187,6 @@ public: virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); // own handlers @@ -244,7 +229,6 @@ public: virtual bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); virtual void initChannel(); // own handlers @@ -313,12 +297,7 @@ public: /** * Writes notification message to IM p2p session. */ - static void logToIMP2P(const LLNotificationPtr& notification); - - /** - * Writes notification message to IM p2p session. - */ - static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only); + static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false); /** * Writes group notice notification message to IM group session. diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index dca7fda151..3ebf0bcc9e 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -111,37 +111,18 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) } } -const static std::string OBJECT_GIVE_ITEM("ObjectGiveItem"); - -static LLIMFloater* find_im_floater(const LLNotificationPtr& notification) -{ - LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); - return LLFloaterReg::findTypedInstance("impanel", session_id); -} - // static bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) { bool res = false; - LLIMFloater* im_floater = find_im_floater(notification); - if (im_floater != NULL) - { - res = im_floater->getVisible() == TRUE; - } - - return res; -} - -static bool is_IM_floater_focused(const LLNotificationPtr& notification) -{ - bool res = false; + LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + LLIMFloater* im_floater = LLFloaterReg::findTypedInstance("impanel", session_id); - LLIMFloater* im_floater = find_im_floater(notification); if (im_floater != NULL) { - res = im_floater->hasFocus() == TRUE; + res = im_floater->getVisible() == TRUE; } return res; @@ -208,12 +189,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type, } } -// static -void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) -{ - logToIMP2P(notification, false); -} - void log_name_callback(const std::string& full_name, const std::string& from_name, const std::string& message, const LLUUID& from_id) @@ -225,25 +200,21 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam // static void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only) { - // don't create IM p2p session with objects, it's necessary condition to log - //if (notification->getName() != OBJECT_GIVE_ITEM) - { - LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID from_id = notification->getPayload()["from_id"]; - if (from_id.isNull()) - { - llwarns << " from_id for notification " << notification->getName() << " is null " << llendl; - return; - } + if (from_id.isNull()) + { + llwarns << " from_id for notification " << notification->getName() << " is null " << llendl; + return; + } - if(to_file_only) - { - gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID())); - } - else - { - gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id)); - } + if(to_file_only) + { + gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID())); + } + else + { + gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id)); } } @@ -377,23 +348,20 @@ void LLHandlerUtil::updateVisibleIMFLoaterMesages(const LLNotificationPtr& notif void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) { const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); - LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( - session_id); + LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(session_id); - if (session == NULL) + if (session) { - return; + LLSD arg; + arg["session_id"] = session_id; + session->mNumUnread--; + arg["num_unread"] = session->mNumUnread; + session->mParticipantUnreadMessageCount--; + arg["participant_unread"] = session->mParticipantUnreadMessageCount; + LLIMModel::getInstance()->mNewMsgSignal(arg); } - - LLSD arg; - arg["session_id"] = session_id; - session->mNumUnread--; - arg["num_unread"] = session->mNumUnread; - session->mParticipantUnreadMessageCount--; - arg["participant_unread"] = session->mParticipantUnreadMessageCount; - LLIMModel::getInstance()->mNewMsgSignal(arg); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 394ae2ac21..9beb8afac6 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -52,15 +52,16 @@ LLNotificationManager::~LLNotificationManager() //-------------------------------------------------------------------------- void LLNotificationManager::init() { - new LLScriptHandler(); - new LLTipHandler(); - new LLGroupHandler(); - new LLAlertHandler("Alerts", "alert", false); - new LLAlertHandler("AlertModal", "alertmodal", true); - new LLOfferHandler(); - new LLHintHandler(); - new LLBrowserNotification(); - new LLOutboxNotification(); + mChannels.push_back(new LLScriptHandler()); + mChannels.push_back(new LLTipHandler()); + mChannels.push_back(new LLGroupHandler()); + mChannels.push_back(new LLAlertHandler("Alerts", "alert", false)); + mChannels.push_back(new LLAlertHandler("AlertModal", "alertmodal", true)); + mChannels.push_back(new LLOfferHandler()); + mChannels.push_back(new LLHintHandler()); + mChannels.push_back(new LLBrowserNotification()); + mChannels.push_back(new LLOutboxNotification()); + mChannels.push_back(new LLIMHandler()); mChatHandler = boost::shared_ptr(new LLNearbyChatHandler()); } diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 4d124e1379..c8afdf9e46 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -61,6 +61,7 @@ public: private: boost::shared_ptr mChatHandler; + std::vector mChannels; }; } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8010417d43..051075cff9 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -79,16 +79,17 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) initChannel(); } - bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + && notification->getPayload()["give_inventory_notification"].asBoolean() == false) { // This is an original inventory offer, so add a script floater LLScriptFloaterManager::instance().onAddNotification(notification->getID()); } else { + bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); + notification->setReusable(add_notif_to_im); LLUUID session_id; @@ -99,10 +100,6 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLUUID from_id = notification->getPayload()["from_id"]; session_id = LLHandlerUtil::spawnIMSession(name, from_id); - } - - if (add_notif_to_im) - { LLHandlerUtil::addNotifPanelToIM(notification); } @@ -120,33 +117,19 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; LLScreenChannel* channel = dynamic_cast(mChannel); if(channel) channel->addToast(p); - - // if we not add notification to IM - add it to notification well - if (!add_notif_to_im) - { - // send a signal to the counter manager - mNewNotificationSignal(); - } } if (notification->canLogToIM()) { // log only to file if notif panel can be embedded to IM and IM is opened - if (add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::logToIMP2P(notification, true); - } - else - { - LLHandlerUtil::logToIMP2P(notification); - } + bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); + LLHandlerUtil::logToIMP2P(notification, file_only); } } @@ -173,21 +156,6 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) } } -//-------------------------------------------------------------------------- - -void LLOfferHandler::onDeleteToast(LLToast* toast) -{ - if (!toast->getNotification()->canLogToIM() || !toast->getNotification()->hasFormElements()) - { - // send a signal to the counter manager - mDelNotificationSignal(); - } - - // send a signal to a listener to let him perform some action - // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); -} - //-------------------------------------------------------------------------- void LLOfferHandler::onRejectToast(LLUUID& id) { diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 714f14963c..c74c967722 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,10 +37,6 @@ using namespace LLNotificationsUI; -static const std::string SCRIPT_DIALOG ("ScriptDialog"); -static const std::string SCRIPT_DIALOG_GROUP ("ScriptDialogGroup"); -static const std::string SCRIPT_LOAD_URL ("LoadWebPage"); - //-------------------------------------------------------------------------- LLScriptHandler::LLScriptHandler() : LLSysHandler("Notifications", "notify") @@ -87,7 +83,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToIMP2P(notification); } - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + if(notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); } @@ -106,9 +102,6 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) { channel->addToast(p); } - - // send a signal to the counter manager - mNewNotificationSignal(); } return false; @@ -117,7 +110,7 @@ bool LLScriptHandler::processNotification(const LLNotificationPtr& notification) void LLScriptHandler::onDelete( LLNotificationPtr notification ) { - if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) + if(notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } @@ -132,17 +125,11 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification ) void LLScriptHandler::onDeleteToast(LLToast* toast) { - // send a signal to the counter manager - mDelNotificationSignal(); - // send a signal to a listener to let him perform some action // in this case listener is a SysWellWindow and it will remove a corresponding item from its list - mNotificationIDSignal(toast->getNotificationID()); - LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); - if( notification && - (SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) + if( notification && notification->hasFormElements()) { LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index e8293ebe2b..18e0d9d0d2 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -433,13 +433,19 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +: LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), + mWellWindow(well_window) +{ + connectToChannel("Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); +} + LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) +: LLSysWellWindow(key) { - // init connections to the list's update events - connectListUpdaterToSignal("Notifications"); - connectListUpdaterToSignal("Group Notifications"); - connectListUpdaterToSignal("Offer"); + mNotificationUpdates.reset(new WellNotificationChannel(this)); } // static @@ -546,19 +552,6 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) addItem(p); } -void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ - LLNotificationsUI::LLEventHandler* n_handler = dynamic_cast(LLNotifications::instance().getChannel(notification_type).get()); - if(n_handler) - { - n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); - } - else - { - llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; - } -} - void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) { LLUUID id = item->getID(); @@ -573,6 +566,12 @@ void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) mChannel->killToastByNotificationID(id); } +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ + removeItemByID(notify->getID()); +} + + /************************************************************************/ @@ -866,4 +865,4 @@ bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& respo return false; } -// EOF + diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 272e9cfcb1..caf30cfd67 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -34,6 +34,7 @@ #include "llscreenchannel.h" #include "llscrollcontainer.h" #include "llimview.h" +#include "llnotifications.h" #include "boost/shared_ptr.hpp" @@ -111,7 +112,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void setVisible(BOOL visible); - + /*virtual*/ void onAdd(LLNotificationPtr notify); // Operating with items void addItem(LLSysWellItem::Params p); @@ -119,6 +120,18 @@ public: void closeAll(); protected: + struct WellNotificationChannel : public LLNotificationChannel + { + WellNotificationChannel(LLNotificationWellWindow*); + void onAdd(LLNotificationPtr notify) + { + mWellWindow->removeItemByID(notify->getID()); + } + + LLNotificationWellWindow* mWellWindow; + }; + + LLNotificationChannelPtr mNotificationUpdates; /*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; } private: @@ -126,12 +139,8 @@ private: void initChannel(); void clearScreenChannels(); - void onStoreToast(LLPanel* info_panel, LLUUID id); - // connect counter and list updaters to the corresponding signals - void connectListUpdaterToSignal(std::string notification_type); - // Handlers void onItemClick(LLSysWellItem* item); void onItemClose(LLSysWellItem* item); diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 3b8b31eac1..dfdc6ae559 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -47,9 +47,6 @@ class LLToastGroupNotifyPanel public: void close(); - static bool onNewNotification(const LLSD& notification); - - // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h index 8e69d8834d..7d33446248 100644 --- a/indra/newview/lltoastscripttextbox.h +++ b/indra/newview/lltoastscripttextbox.h @@ -39,8 +39,6 @@ class LLToastScriptTextbox public: void close(); - static bool onNewNotification(const LLSD& notification); - // Non-transient messages. You can specify non-default button // layouts (like one for script dialogs) by passing various // numbers in for "layout". -- cgit v1.2.3 From c2afd200a0d55c5137de6f89200a8d4b09ba8b6e Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 30 Mar 2012 18:36:43 -0700 Subject: CHUI-51 WIP notifications routing code cleanup object inventory offers don't increment system menu count added customizable merging behavior for duplicate "unique" notifications fixed overeager notification channels --- indra/llui/llnotifications.cpp | 43 ++++++++++++++++------------- indra/llui/llnotifications.h | 8 ++++++ indra/llui/llnotificationtemplate.h | 14 ++++++++++ indra/newview/llchiclet.cpp | 10 +++++-- indra/newview/llnotificationhandler.h | 33 +++++++++++----------- indra/newview/llnotificationhinthandler.cpp | 2 +- indra/newview/llscreenchannel.cpp | 9 +++++- 7 files changed, 80 insertions(+), 39 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index c45899a4bd..79135d2c60 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -246,7 +246,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica LLParamSDParser parser; parser.writeSD(mFormData, p.form_elements); - if (!mFormData.isArray()) + if (!mFormData.isArray() && !mFormData.isUndefined()) { // change existing contents to a one element array LLSD new_llsd_array = LLSD::emptyArray(); @@ -407,6 +407,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mURLOption(p.url.option), mURLTarget(p.url.target), mUnique(p.unique.isProvided()), + mCombineBehavior(p.unique.combine), mPriority(p.priority), mPersist(p.persist), mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), @@ -903,6 +904,10 @@ bool LLNotification::hasFormElements() const return mTemplatep->mForm->getNumElements() != 0; } +LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const +{ + return mTemplatep->mCombineBehavior; +} @@ -1242,22 +1247,25 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) return false; } - // Update 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) + if (pNotif->getCombineBehavior() == LLNotification::USE_NEWEST) { - LLNotificationPtr existing_notification = existing_it->second; - if (pNotif != existing_notification - && pNotif->isEquivalentTo(existing_notification)) + // Update 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) { - // copy notification instance data over to oldest instance - // of this unique notification and update it - existing_notification->updateFrom(pNotif); - // then delete the new one - cancel(pNotif); + LLNotificationPtr existing_notification = existing_it->second; + if (pNotif != existing_notification + && pNotif->isEquivalentTo(existing_notification)) + { + // copy notification instance data over to oldest instance + // of this unique notification and update it + existing_notification->updateFrom(pNotif); + // then delete the new one + cancel(pNotif); + } } } @@ -1296,10 +1304,7 @@ void LLNotifications::createDefaultChannels() boost::bind(&LLNotifications::isVisibleByRules, this, _1))); mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", &LLNotificationFilters::includeEverything)); - - // create special persistent notification channel - // this isn't a leak, don't worry about the empty "new" - new LLPersistentNotificationChannel(); + mDefaultChannels.push_back(new LLPersistentNotificationChannel()); // connect action methods to these channels LLNotifications::instance().getChannel("Enabled")-> diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 344108ecbf..4e2b997156 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -297,6 +297,7 @@ LOG_CLASS(LLNotification); friend class LLNotifications; public: + // parameter object used to instantiate a new notification struct Params : public LLInitParam::Block { @@ -518,6 +519,13 @@ public: bool canLogToIM() const; bool hasFormElements() const; + typedef enum e_combine_behavior + { + USE_NEWEST, + USE_OLDEST + } ECombineBehavior; + + ECombineBehavior getCombineBehavior() const; const LLNotificationFormPtr getForm(); const LLDate getExpiration() const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 1df7205b23..8080acbf87 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -61,6 +61,17 @@ typedef boost::shared_ptr LLNotificationFormPtr; // from the appropriate local language directory). struct LLNotificationTemplate { + struct CombineBehaviorNames + : public LLInitParam::TypeValuesHelper + { + static void declareValues() + { + declare("newest", LLNotification::USE_NEWEST); + declare("oldest", LLNotification::USE_OLDEST); + } + }; + + struct GlobalString : public LLInitParam::Block { Mandatory name, @@ -94,9 +105,11 @@ struct LLNotificationTemplate Optional dummy_val; public: Multiple contexts; + Optional combine; UniquenessConstraint() : contexts("context"), + combine("combine", LLNotification::USE_NEWEST), dummy_val("") {} }; @@ -249,6 +262,7 @@ struct LLNotificationTemplate // (used for things like progress indications, or repeating warnings // like "the grid is going down in N minutes") bool mUnique; + LLNotification::ECombineBehavior mCombineBehavior; // if we want to be unique only if a certain part of the payload or substitutions args // are constant specify the field names for the payload. The notification will only be // combined if all of the fields named in the context are identical in the diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 67519a3ca6..b4c70b6edb 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -393,9 +393,15 @@ void LLNotificationChiclet::setCounter(S32 counter) } -bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notify ) +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) { - return !(notify->canLogToIM() && notify->hasFormElements()); + if( !(notification->canLogToIM() && notification->hasFormElements()) + && (!notification->getPayload().has("give_inventory_notification") + || notification->getPayload()["give_inventory_notification"])) + { + return true; + } + return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 419b8a14b6..21f3961d18 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -94,7 +94,7 @@ public: // base interface functions /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel) mChannel->killToastByNotificationID(p->getID());} virtual bool processNotification(const LLNotificationPtr& notify)=0; @@ -130,7 +130,7 @@ public: protected: bool processNotification(const LLNotificationPtr& p); - virtual void initChannel(); + /*virtual*/ void initChannel(); }; /** @@ -144,11 +144,12 @@ public: virtual ~LLTipHandler(); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void onRejectToast(const LLUUID& id); - virtual void initChannel(); + /*virtual*/ void onRejectToast(const LLUUID& id); + /*virtual*/ void initChannel(); }; /** @@ -161,13 +162,13 @@ public: LLScriptHandler(); virtual ~LLScriptHandler(); - virtual void onDelete(LLNotificationPtr p); + /*virtual*/ void onDelete(LLNotificationPtr p); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void onDeleteToast(LLToast* toast); - virtual void initChannel(); + /*virtual*/ void onDeleteToast(LLToast* toast); + /*virtual*/ void initChannel(); // own handlers void onRejectToast(LLUUID& id); @@ -184,7 +185,8 @@ public: virtual ~LLGroupHandler(); // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -204,9 +206,7 @@ public: /*virtual*/ void onChange(LLNotificationPtr p); /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - - // base interface functions - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -225,11 +225,12 @@ public: virtual ~LLOfferHandler(); // base interface functions + /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onDelete(LLNotificationPtr notification); - virtual bool processNotification(const LLNotificationPtr& p); + /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - virtual void initChannel(); + /*virtual*/ void initChannel(); // own handlers void onRejectToast(LLUUID& id); @@ -246,7 +247,7 @@ public: virtual ~LLHintHandler() {} /*virtual*/ void onAdd(LLNotificationPtr p); - /*virtual*/ void onChange(LLNotificationPtr p); + /*virtual*/ void onLoad(LLNotificationPtr p); /*virtual*/ void onDelete(LLNotificationPtr p); }; diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index 47156a3915..271f418507 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -34,5 +34,5 @@ using namespace LLNotificationsUI; void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onChange(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 5301955964..cc68c4c91a 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -251,7 +251,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p) { bool store_toast = false, show_toast = false; - mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); + if (mDisplayToastsAlways) + { + show_toast = true; + } + else + { + show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); + } store_toast = !show_toast && p.can_be_stored && mCanStoreToasts; if(!show_toast && !store_toast) -- cgit v1.2.3 From 10503b13e0cd5b6f89d885982b72ed23ec131e85 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Thu, 5 Apr 2012 19:22:37 +0300 Subject: CHUI-77 WIP People panel layout change: filter pane moved inside the tab. --- .../newview/skins/default/xui/en/panel_people.xml | 587 ++++++++++----------- 1 file changed, 285 insertions(+), 302 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 98c7c49ff4..919661eff6 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -60,21 +60,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M - - + + + + + - - + + + + + - + left_pad="2" + name="recent_add_btn" + top="1" + width="31" /> + + Date: Wed, 4 Apr 2012 22:04:38 +0300 Subject: CHUI-78 WIP Fixed parsing of menu_button.menu_position XUI parameter. --- indra/llui/llmenubutton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index e2396e7fb2..84e63911a3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -53,7 +53,7 @@ public: { // filename for it's toggleable menu Optional menu_filename; - Optional position; + Optional position; Params(); }; -- cgit v1.2.3 From 69cf10a1e9b969a1c87473a8b153281dc60e7b56 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Thu, 5 Apr 2012 17:29:25 +0300 Subject: CHUI-78 WIP Renamamed menu_button.position XUI attribute to menu_position for consistency with menu_filename. --- indra/llui/llmenubutton.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 50d59f79f4..cfae524f3b 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -44,8 +44,9 @@ void LLMenuButton::MenuPositions::declareValues() LLMenuButton::Params::Params() : menu_filename("menu_filename"), - position("position", MP_BOTTOM_LEFT) + position("menu_position", MP_BOTTOM_LEFT) { + addSynonym(position, "position"); } -- cgit v1.2.3 From 177c1f80bc132fdad4e46009b074c0609454332f Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Thu, 5 Apr 2012 20:37:28 +0300 Subject: CHUI-78 WIP Enabled LLMenuButton to manage its menu's lifetime. --- indra/llui/llmenubutton.cpp | 53 +++++++++++++++++++++++++++++++-------------- indra/llui/llmenubutton.h | 9 +++++++- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index cfae524f3b..2f5e29c36e 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -53,25 +53,18 @@ LLMenuButton::Params::Params() LLMenuButton::LLMenuButton(const LLMenuButton::Params& p) : LLButton(p), mIsMenuShown(false), - mMenuPosition(p.position) + mMenuPosition(p.position), + mOwnMenu(false) { std::string menu_filename = p.menu_filename; - if (!menu_filename.empty()) - { - LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - llwarns << "Error loading menu_button menu" << llendl; - return; - } - - menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); - - mMenuHandle = menu->getHandle(); + setMenu(menu_filename, mMenuPosition); + updateMenuOrigin(); +} - updateMenuOrigin(); - } +LLMenuButton::~LLMenuButton() +{ + cleanup(); } boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) @@ -95,12 +88,32 @@ LLToggleableMenu* LLMenuButton::getMenu() return dynamic_cast(mMenuHandle.get()); } -void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/) +void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) +{ + if (menu_filename.empty()) + { + return; + } + + LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + llwarns << "Error loading menu_button menu" << llendl; + return; + } + + setMenu(menu, position, true); +} + +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/) { if (!menu) return; + cleanup(); // destroy the previous memnu if we own it + mMenuHandle = menu->getHandle(); mMenuPosition = position; + mOwnMenu = take_ownership; menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); } @@ -212,3 +225,11 @@ void LLMenuButton::onMenuVisibilityChange(const LLSD& param) mIsMenuShown = false; } } + +void LLMenuButton::cleanup() +{ + if (mMenuHandle.get() && mOwnMenu) + { + mMenuHandle.get()->die(); + } +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 84e63911a3..67ec1983b3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -34,6 +34,8 @@ class LLToggleableMenu; class LLMenuButton : public LLButton { + LOG_CLASS(LLMenuButton); + public: typedef enum e_menu_position { @@ -68,13 +70,15 @@ public: void hideMenu(); LLToggleableMenu* getMenu(); - void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT); + void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); + void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false); void setMenuPosition(EMenuPosition position) { mMenuPosition = position; } protected: friend class LLUICtrlFactory; LLMenuButton(const Params&); + ~LLMenuButton(); void toggleMenu(); void updateMenuOrigin(); @@ -82,11 +86,14 @@ protected: void onMenuVisibilityChange(const LLSD& param); private: + void cleanup(); + LLHandle mMenuHandle; bool mIsMenuShown; EMenuPosition mMenuPosition; S32 mX; S32 mY; + bool mOwnMenu; // true if we manage the menu lifetime }; -- cgit v1.2.3 From 2dc032e3e582d39a04c40b7cfb3366424491b491 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Thu, 5 Apr 2012 22:56:18 +0300 Subject: CHUI-78 WIP Added drop-down menus and connected callbacks to the new view/sort/add/remove buttons. --- indra/llui/llmenubutton.cpp | 5 + indra/newview/llpanelpeople.cpp | 137 +++++-------------- indra/newview/llpanelpeople.h | 16 +-- .../skins/default/xui/en/menu_group_plus.xml | 4 +- .../default/xui/en/menu_people_friends_sort.xml | 26 ++++ .../default/xui/en/menu_people_friends_view.xml | 26 ++++ .../xui/en/menu_people_friends_view_sort.xml | 47 ------- .../default/xui/en/menu_people_groups_view.xml | 17 +++ .../xui/en/menu_people_groups_view_sort.xml | 26 ---- .../default/xui/en/menu_people_nearby_sort.xml | 36 +++++ .../default/xui/en/menu_people_nearby_view.xml | 31 +++++ .../xui/en/menu_people_nearby_view_sort.xml | 57 -------- .../default/xui/en/menu_people_recent_sort.xml | 26 ++++ .../default/xui/en/menu_people_recent_view.xml | 18 +++ .../xui/en/menu_people_recent_view_sort.xml | 39 ------ .../newview/skins/default/xui/en/panel_people.xml | 152 ++++++++++++++++----- 16 files changed, 339 insertions(+), 324 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_groups_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_view.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 2f5e29c36e..98f7e0540c 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -153,6 +153,11 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask) void LLMenuButton::toggleMenu() { + if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) + { + return; + } + if(mMenuHandle.isDead()) return; LLToggleableMenu* menu = dynamic_cast(mMenuHandle.get()); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9c46f04abf..238834aa92 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -501,17 +501,38 @@ LLPanelPeople::LLPanelPeople() mNearbyList(NULL), mRecentList(NULL), mGroupList(NULL), - mNearbyGearButton(NULL), - mFriendsGearButton(NULL), - mGroupsGearButton(NULL), - mRecentGearButton(NULL), mMiniMap(NULL) { mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this)); mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this)); mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this)); mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); - mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + + mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + mCommitCallbackRegistrar.add("People.AddFriendWizard", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); + mCommitCallbackRegistrar.add("People.DelFriend", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Group.Activate", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Group.Minus", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); + mCommitCallbackRegistrar.add("People.ViewProfile", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); + mCommitCallbackRegistrar.add("People.GroupInfo", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Chat", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); + mCommitCallbackRegistrar.add("People.IM", boost::bind(&LLPanelPeople::onImButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Call", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); + mCommitCallbackRegistrar.add("People.GroupCall", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Teleport", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); + mCommitCallbackRegistrar.add("People.Share", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); + + mCommitCallbackRegistrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); + mCommitCallbackRegistrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); + + mEnableCallbackRegistrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); + mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); + + mEnableCallbackRegistrar.add("People.Group.Plus.Validate", boost::bind(&LLPanelPeople::onGroupPlusButtonValidate, this)); } LLPanelPeople::~LLPanelPeople() @@ -525,13 +546,6 @@ LLPanelPeople::~LLPanelPeople() { LLVoiceClient::getInstance()->removeObserver(this); } - - if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); - if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); - if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); - if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); - if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); - } void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list) @@ -601,14 +615,6 @@ BOOL LLPanelPeople::postBuild() setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false); - LLPanel* groups_panel = getChild(GROUP_TAB_NAME); - groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); - groups_panel->childSetAction("plus_btn", boost::bind(&LLPanelPeople::onGroupPlusButtonClicked, this)); - - LLPanel* friends_panel = getChild(FRIENDS_TAB_NAME); - friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); - friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); - mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); @@ -637,70 +643,9 @@ BOOL LLPanelPeople::postBuild() accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList)); - buttonSetAction("view_profile_btn", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); - buttonSetAction("group_info_btn", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); - buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); - buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this)); - buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); - buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); - buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); - buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); - // Must go after setting commit callback and initializing all pointers to children. mTabContainer->selectTabByName(NEARBY_TAB_NAME); - // Create menus. - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); - registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this)); - registrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); - registrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2)); - registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); - registrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); - - enable_registrar.add("People.Group.Minus.Enable", boost::bind(&LLPanelPeople::isRealGroup, this)); - enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); - enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); - enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); - - mNearbyGearButton = getChild("nearby_view_sort_btn"); - mFriendsGearButton = getChild("friends_viewsort_btn"); - mGroupsGearButton = getChild("groups_viewsort_btn"); - mRecentGearButton = getChild("recent_viewsort_btn"); - - LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mGroupPlusMenuHandle = plus_menu->getHandle(); - - LLToggleableMenu* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(nearby_view_sort) - { - mNearbyViewSortMenuHandle = nearby_view_sort->getHandle(); - mNearbyGearButton->setMenu(nearby_view_sort); - } - - LLToggleableMenu* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(friend_view_sort) - { - mFriendsViewSortMenuHandle = friend_view_sort->getHandle(); - mFriendsGearButton->setMenu(friend_view_sort); - } - - LLToggleableMenu* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(group_view_sort) - { - mGroupsViewSortMenuHandle = group_view_sort->getHandle(); - mGroupsGearButton->setMenu(group_view_sort); - } - - LLToggleableMenu* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(recent_view_sort) - { - mRecentViewSortMenuHandle = recent_view_sort->getHandle(); - mRecentGearButton->setMenu(recent_view_sort); - } - LLVoiceClient::getInstance()->addObserver(this); // call this method in case some list is empty and buttons can be in inconsistent state @@ -835,13 +780,6 @@ void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) button->setEnabled(enabled); } -void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb) -{ - // To make sure we're referencing the right widget (a child of the button bar). - LLButton* button = getChild("button_bar")->getChild(btn_name); - button->setClickedCallback(cb); -} - void LLPanelPeople::updateButtons() { std::string cur_tab = getActiveTabName(); @@ -877,7 +815,7 @@ void LLPanelPeople::updateButtons() LLPanel* groups_panel = mTabContainer->getCurrentPanel(); groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected - groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); + groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected } else { @@ -893,10 +831,12 @@ void LLPanelPeople::updateButtons() LLPanel* cur_panel = mTabContainer->getCurrentPanel(); if (cur_panel) { - cur_panel->getChildView("add_friend_btn")->setEnabled(!is_friend); + if (cur_panel->hasChild("add_friend_btn", TRUE)) + cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); + if (friends_tab_active) { - cur_panel->getChildView("del_btn")->setEnabled(multiple_selected); + cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); } } } @@ -1031,11 +971,6 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save } } -bool LLPanelPeople::isRealGroup() -{ - return getCurrentItemID() != LLUUID::null; -} - void LLPanelPeople::onFilterEdit(const std::string& search_string) { mFilterSubStringOrig = search_string; @@ -1226,19 +1161,15 @@ void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector mGroupPlusMenuHandle; - LLHandle mNearbyViewSortMenuHandle; - LLHandle mFriendsViewSortMenuHandle; - LLHandle mGroupsViewSortMenuHandle; - LLHandle mRecentViewSortMenuHandle; - Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; Updater* mButtonsUpdater; - LLMenuButton* mNearbyGearButton; - LLMenuButton* mFriendsGearButton; - LLMenuButton* mGroupsGearButton; - LLMenuButton* mRecentGearButton; - std::string mFilterSubString; std::string mFilterSubStringOrig; }; diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index fce7414d80..eca9e7f3c9 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,5 +1,5 @@ - @@ -8,4 +8,4 @@ - + diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml new file mode 100644 index 0000000000..532e295386 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml new file mode 100644 index 0000000000..be23e91587 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml deleted file mode 100644 index b452f96e7a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml new file mode 100644 index 0000000000..73f79f1e70 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml deleted file mode 100644 index c710fe3b9b..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml new file mode 100644 index 0000000000..cf7f4f4fce --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml new file mode 100644 index 0000000000..187dd3bcb5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml deleted file mode 100644 index 614dd693c5..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml new file mode 100644 index 0000000000..f14be88780 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_recent_sort.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml new file mode 100644 index 0000000000..5520bc993c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml deleted file mode 100644 index 485a5a658c..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 919661eff6..f61b0b3dbd 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -73,6 +73,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M top="0" halign="center" width="319"> + + + + width="31"> + + + + + + width="31"> + + + + + + + width="31"> + + + width="31"> + + + + + + width="31"> + + + width="67"> + + + width="40"> + + + width="51"> + + + width="65"> + + + width="76"> + + @@ -706,7 +779,10 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M name="group_info_btn" tool_tip="Show group information" top="0" - width="107" /> + width="107"> + + + width="100"> + + + width="95"> + + -- cgit v1.2.3 From 9626ab8fec34f73cd60822bd34376c1cb94e11d7 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 5 Apr 2012 16:10:07 -0700 Subject: CHUI-89 FIX Make nametags appear consistently next to avatar heads nametags now track avatar head avatar_skeleton now loaded as param block vector3 param block parsing support fixes for param block recursion --- indra/llxuixml/llinitparam.h | 227 +++++---- indra/llxuixml/llxuiparser.cpp | 27 + indra/llxuixml/llxuiparser.h | 2 + indra/newview/llhudnametag.cpp | 279 +++-------- indra/newview/llhudnametag.h | 2 - indra/newview/llspatialpartition.cpp | 4 +- indra/newview/llviewermenu.cpp | 9 - indra/newview/llvoavatar.cpp | 948 ++++++++++++++++------------------- indra/newview/llvoavatar.h | 15 +- indra/newview/pipeline.cpp | 5 - 10 files changed, 689 insertions(+), 829 deletions(-) diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ab20957760..6fffb73acd 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -377,8 +377,9 @@ namespace LLInitParam class Lazy { public: + Lazy() - : mPtr(NULL) + : mPtr(NULL) {} ~Lazy() @@ -386,6 +387,11 @@ namespace LLInitParam delete mPtr; } + Lazy(const T& value) + { + mPtr = new T(value); + } + Lazy(const Lazy& other) { if (other.mPtr) @@ -424,12 +430,17 @@ namespace LLInitParam const T& get() const { - return ensureInstance(); + return *ensureInstance(); } T& get() { - return ensureInstance(); + return *ensureInstance(); + } + + operator const T&() const + { + return get(); } private: @@ -520,8 +531,8 @@ namespace LLInitParam void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } // take all provided params from other and apply to self bool overwriteFrom(const BaseBlock& other) @@ -539,6 +550,15 @@ namespace LLInitParam ParamDescriptorPtr findParamDescriptor(const Param& param); + // take all provided params from other and apply to self + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + + static BlockDescriptor& getBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + protected: void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -547,25 +567,11 @@ namespace LLInitParam { return mergeBlock(block_data, source, overwrite); } - // take all provided params from other and apply to self - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; - template - struct ParamCompare, false > - { - static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) { return !a.empty() || !b.empty(); } - }; - class Param { public: @@ -607,26 +613,16 @@ namespace LLInitParam // these templates allow us to distinguish between template parameters // that derive from BaseBlock and those that don't - template + template struct IsBlock { static const bool value = false; - struct EmptyBase {}; - typedef EmptyBase base_class_t; }; template struct IsBlock { static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template - struct IsBlock, typename T::baseblock_base_class_t > - { - static const bool value = true; - typedef BaseBlock base_class_t; }; template::value> @@ -817,13 +813,13 @@ namespace LLInitParam public: typedef TypedParam self_t; typedef ParamValue param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef typename param_value_t::value_assignment_t value_assignment_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr), + param_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { @@ -837,8 +833,6 @@ namespace LLInitParam min_count, max_count)); BaseBlock::addParam(block_descriptor, param_descriptor, name); } - - setValue(value); } bool isProvided() const { return Param::anyProvided(); } @@ -857,14 +851,14 @@ namespace LLInitParam } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + if (param_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -917,9 +911,9 @@ namespace LLInitParam // tell parser about our actual type parser.inspectValue(name_stack, min_count, max_count, NULL); // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (name_value_lookup_t::getPossibleValues()) + if (param_value_t::getPossibleValues()) { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue(name_stack, min_count, max_count, param_value_t::getPossibleValues()); } } @@ -969,11 +963,10 @@ namespace LLInitParam typedef ParamValue param_value_t; typedef typename param_value_t::value_assignment_t value_assignment_t; typedef TypedParam self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; using param_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const T& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), param_value_t(value) { @@ -1002,14 +995,14 @@ namespace LLInitParam return true; } - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + if (param_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -1041,7 +1034,7 @@ namespace LLInitParam } else { - typed_param.serializeBlock(parser, name_stack, static_cast(diff_param)); + typed_param.serializeBlock(parser, name_stack, &static_cast(*static_cast(diff_param))); } } @@ -1115,7 +1108,7 @@ namespace LLInitParam if (src_typed_param.anyProvided()) { - if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) + if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite)) { dst_typed_param.clearValueName(); dst_typed_param.setProvided(true); @@ -1138,9 +1131,8 @@ namespace LLInitParam typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); @@ -1176,14 +1168,14 @@ namespace LLInitParam } // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) + if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { typed_param.add(value); typed_param.mValues.back().setValueName(name); @@ -1234,9 +1226,9 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { parser.inspectValue(name_stack, min_count, max_count, NULL); - if (name_value_lookup_t::getPossibleValues()) + if (param_value_t::getPossibleValues()) { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue(name_stack, min_count, max_count, param_value_t::getPossibleValues()); } } @@ -1261,12 +1253,12 @@ namespace LLInitParam setProvided(); } - void add(const typename name_value_lookup_t::name_t& name) + void add(const typename param_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1330,9 +1322,8 @@ namespace LLInitParam typedef typename std::vector container_t; typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const container_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), back_inserter(mValues)); @@ -1372,14 +1363,14 @@ namespace LLInitParam typed_param.setProvided(); return true; } - else if(name_value_lookup_t::valueNamesExist()) + else if(param_value_t::valueNamesExist()) { // try to parse a known named value std::string name; if (parser.readValue(name)) { // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value.getValue())) + if (param_value_t::getValueFromName(name, value.getValue())) { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); @@ -1447,12 +1438,12 @@ namespace LLInitParam setProvided(); } - void add(const typename name_value_lookup_t::name_t& name) + void add(const typename param_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (param_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1526,13 +1517,13 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, false); } bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1550,7 +1541,7 @@ namespace LLInitParam bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) { mCurChoice = other.mCurChoice; - return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); + return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite); } // clear out old choice when param has changed @@ -1571,14 +1562,14 @@ namespace LLInitParam base_block_t::paramChanged(changed_param, user_provided); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: ChoiceBlock() : mCurChoice(0) { - BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // Alternatives are mutually exclusive wrt other Alternatives in the same block. @@ -1596,13 +1587,13 @@ namespace LLInitParam using super_t::operator =; - explicit Alternative(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), + explicit Alternative(const char* name = "", const T& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { // assign initial choice to first declared option - DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); - if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); + if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) { if(blockp->mCurChoice == 0) { @@ -1654,8 +1645,8 @@ namespace LLInitParam T mOriginalValue; }; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; @@ -1683,23 +1674,23 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, false); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: Block() { //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // @@ -1715,8 +1706,8 @@ namespace LLInitParam using super_t::operator(); using super_t::operator =; - explicit Optional(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) + explicit Optional(const char* name = "", const T& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") } @@ -1746,8 +1737,8 @@ namespace LLInitParam using super_t::operator =; // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) + explicit Mandatory(const char* name = "", const T& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} Mandatory& operator =(value_assignment_t val) @@ -1782,7 +1773,7 @@ namespace LLInitParam typedef typename super_t::const_iterator const_iterator; explicit Multiple(const char* name = "") - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} Multiple& operator =(value_assignment_t val) @@ -1808,9 +1799,9 @@ namespace LLInitParam { public: explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1841,13 +1832,14 @@ namespace LLInitParam // different semantics for documentation purposes, but functionally identical typedef Deprecated Ignored; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } + protected: template void changeDefault(TypedParam& param, typename TypedParam::value_assignment_t value) @@ -1887,7 +1879,7 @@ namespace LLInitParam { *static_cast(this) = defaultBatchValue(); // merge individual parameters into destination - return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); + return super_t::mergeBlock(super_t::getBlockDescriptor(), other, overwrite); } return false; } @@ -1955,14 +1947,36 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag }; - template + template + struct IsBlock, TypeValues > > , BLOCK_IDENTIFIER> + { + static const bool value = true;//IsBlock::value; + }; + + template + struct ParamCompare, false> + { + static bool equals(const T&a, const T &b) + { + return a == b; + } + + static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) + { + if (a.empty() || b.empty()) return false; + return a.get() == b.get(); + } + }; + + + template class ParamValue , - TypeValues, - IS_BLOCK> - : public IsBlock::base_class_t + TypeValues >, + VALUE_IS_BLOCK> + : public TypeValues { public: - typedef ParamValue , TypeValues, false> self_t; + typedef ParamValue , TypeValues >, false> self_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1971,11 +1985,16 @@ namespace LLInitParam mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const BaseBlock::Lazy& other) : mValue(other), mValidated(false) {} + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + void setValue(value_assignment_t val) { mValue.set(val); @@ -1991,6 +2010,11 @@ namespace LLInitParam return mValue.get(); } + operator const BaseBlock&() const + { + return mValue.get(); + } + operator value_assignment_t() const { return mValue.get(); @@ -2020,7 +2044,22 @@ namespace LLInitParam return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } - protected: + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.get().validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return T::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag private: diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index afc76024d1..3c89fa3aaf 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -42,6 +42,7 @@ #include #include "lluicolor.h" +#include "v3math.h" using namespace BOOST_SPIRIT_CLASSIC_NS; @@ -670,6 +671,7 @@ LLXUIParser::LLXUIParser() registerParserFuncs(readS32Value, writeS32Value); registerParserFuncs(readF32Value, writeF32Value); registerParserFuncs(readF64Value, writeF64Value); + registerParserFuncs(readVector3Value, writeVector3Value); registerParserFuncs(readColor4Value, writeColor4Value); registerParserFuncs(readUIColorValue, writeUIColorValue); registerParserFuncs(readUUIDValue, writeUUIDValue); @@ -1144,6 +1146,31 @@ bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_ return false; } +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLVector3* vecp = (LLVector3*)val_ptr; + if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLVector3 vector = *((LLVector3*)val_ptr); + node->setFloatValue(3, vector.mV); + return true; + } + return false; +} + bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) { LLXUIParser& self = static_cast(parser); diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index d7cd256967..e48663e5cc 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -127,6 +127,7 @@ private: static bool readS32Value(Parser& parser, void* val_ptr); static bool readF32Value(Parser& parser, void* val_ptr); static bool readF64Value(Parser& parser, void* val_ptr); + static bool readVector3Value(Parser& parser, void* val_ptr); static bool readColor4Value(Parser& parser, void* val_ptr); static bool readUIColorValue(Parser& parser, void* val_ptr); static bool readUUIDValue(Parser& parser, void* val_ptr); @@ -144,6 +145,7 @@ private: static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..cf55954d7d 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -187,45 +187,42 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& + (y_pixel_vec * screen_offset.mV[VY]); - //if (mUseBubble) - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - LLVector3 v[] = - { - bg_pos, - bg_pos + width_vec, - bg_pos + width_vec + height_vec, - bg_pos + height_vec, - }; + LLVector3 v[] = + { + bg_pos, + bg_pos + width_vec, + bg_pos + width_vec + height_vec, + bg_pos + height_vec, + }; - if (debug_render) - { - gGL.begin(LLRender::LINE_STRIP); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - gGL.end(); - } + if (debug_render) + { + gGL.begin(LLRender::LINE_STRIP); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + gGL.end(); + } - LLVector3 dir = end-start; - F32 a, b, t; + LLVector3 dir = end-start; + F32 a, b, t; - if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || - LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || + LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) + { + if (t <= 1.f) { - if (t <= 1.f) - { - intersection = start + dir*t; - return TRUE; - } + intersection = start + dir*t; + return TRUE; } } @@ -241,12 +238,6 @@ void LLHUDNameTag::render() } } -void LLHUDNameTag::renderForSelect() -{ - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderText(TRUE); -} - void LLHUDNameTag::renderText(BOOL for_select) { if (!mVisible || mHidden) @@ -336,142 +327,53 @@ void LLHUDNameTag::renderText(BOOL for_select) LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); - LLVector2 screen_offset; -// if (!mUseBubble) -// { -// screen_offset = mPositionOffset; -// } -// else -// { - screen_offset = updateScreenPos(mPositionOffset); -// } + LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); -// if (mUseBubble) + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLUI::pushMatrix(); { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLUI::pushMatrix(); - { - LLVector3 bg_pos = render_position - + (F32)mOffsetY * y_pixel_vec - - (width_vec / 2.f) - - (height_vec); - LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); + LLVector3 bg_pos = render_position + + (F32)mOffsetY * y_pixel_vec + - (width_vec / 2.f) + - (height_vec); + LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - if (for_select) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(imagep->getImage()); + if (for_select) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + S32 name = mSourceObject->mGLName; + LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); + gGL.color4ubv(coloru.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + LLUI::popMatrix(); + return; + } + else + { + gGL.getTexUnit(0)->bind(imagep->getImage()); - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); + gGL.color4fv(bg_color.mV); + gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - - BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; - BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); - - // draw line segments pointing to parent object - if (!mOffscreen && (outside_width || outside_height)) + if ( mLabelSegments.size()) { LLUI::pushMatrix(); { - gGL.color4fv(bg_color.mV); - LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); - target_pos += (width_vec / 2.f); - target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; - target_pos -= 3.f * x_pixel_vec; - target_pos -= 6.f * y_pixel_vec; - LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); - gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec); + gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); + LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; + LLVector3 label_offset = height_vec - label_height; + LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); + gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); } LLUI::popMatrix(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); - - LLVector3 box_center_offset; - box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); - LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); - gGL.color4fv(bg_color.mV); - LLUI::setLineWidth(2.0); - gGL.begin(LLRender::LINES); - { - if (outside_width) - { - LLVector3 vert; - // draw line in x then y - if (mPositionOffset.mV[VX] < 0.f) - { - // start at right edge - vert = width_vec * 0.5f; - gGL.vertex3fv(vert.mV); - } - else - { - // start at left edge - vert = width_vec * -0.5f; - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VX] * x_pixel_vec; - gGL.vertex3fv(vert.mV); - gGL.vertex3fv(vert.mV); - vert -= mPositionOffset.mV[VY] * y_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - else - { - LLVector3 vert; - // draw line in y then x - if (mPositionOffset.mV[VY] < 0.f) - { - // start at top edge - vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - else - { - // start at bottom edge - vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); - gGL.vertex3fv(vert.mV); - } - } - gGL.end(); - LLUI::setLineWidth(1.0); - } } - LLUI::popMatrix(); } + LLUI::popMatrix(); F32 y_offset = (F32)mOffsetY; @@ -874,29 +776,26 @@ void LLHUDNameTag::updateAll() for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it) { LLHUDNameTag* textp = (*r_it); -// if (textp->mUseBubble) -// { - if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) - { - textp->setLOD(3); - } - else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) - { - textp->setLOD(2); - } - else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) - { - textp->setLOD(1); - } - else - { - textp->setLOD(0); - } - textp->updateSize(); - // find on-screen position and initialize collision rectangle - textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); - current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -// } + if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) + { + textp->setLOD(3); + } + else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) + { + textp->setLOD(2); + } + else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) + { + textp->setLOD(1); + } + else + { + textp->setLOD(0); + } + textp->updateSize(); + // find on-screen position and initialize collision rectangle + textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); + current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); } LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +813,12 @@ void LLHUDNameTag::updateAll() { LLHUDNameTag* src_textp = (*src_it); -// if (!src_textp->mUseBubble) -// { -// continue; -// } VisibleTextObjectIterator dst_it = src_it; ++dst_it; for (; dst_it != sVisibleTextObjects.end(); ++dst_it) { LLHUDNameTag* dst_textp = (*dst_it); -// if (!dst_textp->mUseBubble) -// { -// continue; -// } if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect)) { LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +867,6 @@ void LLHUDNameTag::updateAll() VisibleTextObjectIterator this_object_it; for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it) { -// if (!(*this_object_it)->mUseBubble) -// { -// continue; -// } (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC)); } } @@ -1037,10 +924,6 @@ void LLHUDNameTag::addPickable(std::set &pick_list) VisibleTextObjectIterator text_it; for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it) { -// if (!(*text_it)->mUseBubble) -// { -// continue; -// } pick_list.insert((*text_it)->mSourceObject); } } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public: /*virtual*/ void markDead(); friend class LLHUDObject; /*virtual*/ F32 getDistance() const { return mLastDistance; } - //void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; } S32 getLOD() { return mLOD; } BOOL getVisible() { return mVisible; } BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected: LLHUDNameTag(const U8 type); /*virtual*/ void render(); - /*virtual*/ void renderForSelect(); void renderText(BOOL for_select); static void updateAll(); void setLOD(S32 lod); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5d196a465f..1333862855 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2774,7 +2774,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) { - gGL.diffuseColor4fv(color.mV); + gGL.color4fv(color.mV); gGL.begin(LLRender::LINES); { gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -3904,7 +3904,7 @@ void renderAgentTarget(LLVOAvatar* avatar) if (avatar->isSelf()) { renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); + renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99540ccce9..ae32683c99 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3190,15 +3190,6 @@ bool enable_freeze_eject(const LLSD& avatar_id) return new_value; } - -void login_done(S32 which, void *user) -{ - llinfos << "Login done " << which << llendl; - - LLPanelLogin::closePanel(); -} - - bool callback_leave_group(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bc7f5a9744..f00363bfa6 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -62,6 +62,7 @@ #include "llhudmanager.h" #include "llhudnametag.h" #include "llhudtext.h" // for mText/mDebugText +#include "llinitparam.h" #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" @@ -193,6 +194,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN; const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.15f; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -224,55 +228,62 @@ struct LLTextureMaskData **/ //------------------------------------------------------------------------ -// LLVOBoneInfo +// LLVOAvatarBoneInfo // Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. //------------------------------------------------------------------------ -class LLVOAvatarBoneInfo +struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block { - friend class LLVOAvatar; - friend class LLVOAvatarSkeletonInfo; -public: - LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} - ~LLVOAvatarBoneInfo() - { - std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); + LLVOAvatarCollisionVolumeInfo() + : name("name"), + pos("pos"), + rot("rot"), + scale("scale") + {} + + Mandatory name; + Mandatory pos, + rot, + scale; +}; + +struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock +{ + Alternative > bone; + Alternative collision_volume; + + LLVOAvatarChildJoint() + : bone("bone"), + collision_volume("collision_volume") + {} +}; + +struct LLVOAvatarBoneInfo : public LLInitParam::Block +{ + LLVOAvatarBoneInfo() + : pivot("pivot") + {} -private: - std::string mName; - BOOL mIsJoint; - LLVector3 mPos; - LLVector3 mRot; - LLVector3 mScale; - LLVector3 mPivot; - typedef std::vector child_list_t; - child_list_t mChildList; + Mandatory pivot; + Multiple children; }; //------------------------------------------------------------------------ // LLVOAvatarSkeletonInfo // Overall avatar skeleton //------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo +struct LLVOAvatarSkeletonInfo : public LLInitParam::Block { - friend class LLVOAvatar; -public: - LLVOAvatarSkeletonInfo() : - mNumBones(0), mNumCollisionVolumes(0) {} - ~LLVOAvatarSkeletonInfo() - { - std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - S32 getNumBones() const { return mNumBones; } - S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + LLVOAvatarSkeletonInfo() + : skeleton_root(""), + num_bones("num_bones"), + num_collision_volumes("num_collision_volumes"), + version("version") + {} -private: - S32 mNumBones; - S32 mNumCollisionVolumes; - typedef std::vector bone_info_list_t; - bone_info_list_t mBoneInfoList; + Mandatory version; + Mandatory num_bones, + num_collision_volumes; + Mandatory skeleton_root; }; //----------------------------------------------------------------------------- @@ -597,7 +608,7 @@ private: // Static Data //----------------------------------------------------------------------------- LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; +LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree; LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; @@ -1123,18 +1134,6 @@ void LLVOAvatar::initClass() llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; } - // Process XML data - - // avatar_skeleton.xml - if (sAvatarSkeletonInfo) - { //this can happen if a login attempt failed - delete sAvatarSkeletonInfo; - } - sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; - if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) - { - llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; - } // parse avatar_lad.xml if (sAvatarXmlInfo) { //this can happen if a login attempt failed @@ -1183,7 +1182,7 @@ void LLVOAvatar::initClass() void LLVOAvatar::cleanupClass() { deleteAndClear(sAvatarXmlInfo); - sSkeletonXMLTree.cleanup(); + sSkeletonXMLTree = NULL; sXMLTree.cleanup(); } @@ -1655,33 +1654,39 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); + + LLXMLNodePtr skeleton_xml; + BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); - if (!parsesuccess) + if (!parsesuccess || skeleton_xml.isNull()) { llerrs << "Can't parse skeleton file: " << filename << llendl; return FALSE; } - // now sanity check xml file - LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); - if (!root) + // Process XML data + if (sAvatarSkeletonInfo) + { //this can happen if a login attempt failed + delete sAvatarSkeletonInfo; + } + sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + + LLXUIParser parser; + parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); + if (!sAvatarSkeletonInfo->validateBlock()) { - llerrs << "No root node found in avatar skeleton file: " << filename << llendl; - return FALSE; + llerrs << "Error parsing skeleton XML file: " << filename << llendl; } - if( !root->hasName( "linden_skeleton" ) ) + if( !skeleton_xml->hasName( "linden_skeleton" ) ) { llerrs << "Invalid avatar skeleton file header: " << filename << llendl; return FALSE; } - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + if (sAvatarSkeletonInfo->version() != "1.0") { - llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; + llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl; return FALSE; } @@ -1690,14 +1695,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //----------------------------------------------------------------------------- // setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) +//----------------------------------------------------------- +BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) { LLMemType mt(LLMemType::MTYPE_AVATAR); LLViewerJoint* joint = NULL; - - if (info->mIsJoint) + if (info.bone.isChosen()) { joint = (LLViewerJoint*)getCharacterJoint(joint_num); if (!joint) @@ -1705,7 +1709,23 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent llwarns << "Too many bones" << llendl; return FALSE; } - joint->setName( info->mName ); + joint->setName( info.bone().name ); + joint->setPosition(info.bone().pos); + joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info.bone().scale); + joint->setSkinOffset( info.bone().pivot ); + joint_num++; + + for (LLInitParam::ParamIterator::const_iterator child_it = info.bone().children.begin(), + end_it = info.bone().children.end(); + child_it != end_it; + ++child_it) + { + if (!setupBone(*child_it, joint, volume_num, joint_num)) + { + return FALSE; + } + } } else // collision volume { @@ -1715,7 +1735,11 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent return FALSE; } joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); - joint->setName( info->mName ); + joint->setName( info.collision_volume.name); + joint->setPosition(info.collision_volume.pos); + joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info.collision_volume.scale); + volume_num++; } // add to parent @@ -1724,34 +1748,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent parent->addChild( joint ); } - joint->setPosition(info->mPos); - joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], - info->mRot.mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info->mScale); - joint->setDefaultFromCurrentXform(); - if (info->mIsJoint) - { - joint->setSkinOffset( info->mPivot ); - joint_num++; - } - else // collision volume - { - volume_num++; - } - - // setup children - LLVOAvatarBoneInfo::child_list_t::const_iterator iter; - for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) - { - LLVOAvatarBoneInfo *child_info = *iter; - if (!setupBone(child_info, joint, volume_num, joint_num)) - { - return FALSE; - } - } - return TRUE; } @@ -1765,35 +1763,31 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) //------------------------------------------------------------------------- // allocate joints //------------------------------------------------------------------------- - if (!allocateCharacterJoints(info->mNumBones)) + if (!allocateCharacterJoints(info->num_bones)) { - llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; + llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl; return FALSE; } //------------------------------------------------------------------------- // allocate volumes //------------------------------------------------------------------------- - if (info->mNumCollisionVolumes) + if (info->num_collision_volumes) { - if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) + if (!allocateCollisionVolumes(info->num_collision_volumes)) { - llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; + llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl; return FALSE; } } S32 current_joint_num = 0; S32 current_volume_num = 0; - LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; - for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + + if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num)) { - LLVOAvatarBoneInfo *info = *iter; - if (!setupBone(info, NULL, current_volume_num, current_joint_num)) - { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; } return TRUE; @@ -2922,43 +2916,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; - if (visible_chat != mVisibleChat) - { - mVisibleChat = visible_chat; - new_name = TRUE; - } + BOOL new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } - if (sRenderGroupTitles != mRenderGroupTitles) - { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; - } + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } - else if (mAppAngle > 2.f) + else { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; + // ...not fading, full alpha + alpha = 1.f; } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } if (alpha <= 0.f) - { + { if (mNameText) { mNameText->markDead(); @@ -2968,31 +2962,30 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - if (!mNameText) - { + if (!mNameText) + { mNameText = static_cast( LLHUDObject::addHUDObject( LLHUDObject::LL_HUD_NAME_TAG) ); //mNameText->setMass(10.f); - mNameText->setSourceObject(this); + mNameText->setSourceObject(this); mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } - LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); - mNameText->setPositionAgent(name_position); + idleUpdateNameTagPosition(root_pos_last); idleUpdateNameTagText(new_name); idleUpdateNameTagAlpha(new_name, alpha); } void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) - { - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); +{ + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("LastName"); // Avatars must have a first and last name if (!firstname || !lastname) return; @@ -3006,34 +2999,29 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) is_muted = false; } else - { + { is_muted = LLMuteList::getInstance()->isMuted(getID()); } bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - if (is_appearance != mNameAppearance) - { - if (is_appearance) - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; - } - else - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); - llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; - } - } - } + if (gSavedSettings.getBOOL("DebugAvatarRezTime") + && is_appearance != mNameAppearance) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + if (is_appearance) + { + LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; + } + else + { + LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); + llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; + } + } // Rebuild name tag if state change detected if (mNameString.empty() @@ -3043,39 +3031,39 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute - || is_appearance != mNameAppearance + || is_appearance != mNameAppearance || is_friend != mNameFriend || is_cloud != mNameCloud) - { + { LLColor4 name_tag_color = getNameTagColor(is_friend); clearNameTag(); if (is_away || is_muted || is_busy || is_appearance) - { + { std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); + if (is_away) + { + line += LLTrans::getString("AvatarAway"); line += ", "; - } - if (is_busy) - { + } + if (is_busy) + { line += LLTrans::getString("AvatarBusy"); line += ", "; } if (is_muted) - { + { line += LLTrans::getString("AvatarMuted"); - line += ", "; - } + line += ", "; + } if (is_appearance) { line += LLTrans::getString("AvatarEditingAppearance"); line += ", "; - } + } if (is_cloud) - { + { line += LLTrans::getString("LoadingData"); line += ", "; } @@ -3087,12 +3075,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0') - { + { std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); - } + } static LLUICachedControl show_display_names("NameTagShowDisplayNames"); static LLUICachedControl show_usernames("NameTagShowUsernames"); @@ -3106,119 +3094,118 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // and force a rebuild LLAvatarNameCache::get(getID(), boost::bind(&LLVOAvatar::clearNameTag, this)); - } + } // Might be blank if name not available yet, that's OK if (show_display_names) { addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); - } + } // Suppress SLID display if display name matches exactly (ugh) if (show_usernames && !av_name.mIsDisplayNameDefault) - { + { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } - } + } else - { + { const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = - LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); - } + } - mNameAway = is_away; - mNameBusy = is_busy; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; - } + mNameAway = is_away; + mNameBusy = is_busy; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle, LL_UNKNOWN_CHAR); + new_name = TRUE; + } if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); + { + mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - - char line[MAX_STRING]; /* Flawfinder: ignore */ - line[0] = '\0'; - std::deque::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; - } + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); + char line[MAX_STRING]; /* Flawfinder: ignore */ + line[0] = '\0'; + std::deque::iterator chat_iter = mChats.begin(); + mNameText->clearString(); - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; + } - } + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; } - else + if (chat_fade_amt < 1.f) { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) + { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { // ...not using chat bubbles, just names mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); } } @@ -3241,8 +3228,8 @@ void LLVOAvatar::clearNameTag() { mNameString.clear(); if (mNameText) - { - mNameText->setLabel(""); + { + mNameText->setLabel(""); mNameText->setString( "" ); } } @@ -3270,34 +3257,45 @@ void LLVOAvatar::invalidateNameTags() if (avatar->isDead()) continue; avatar->clearNameTag(); - } } // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { LLQuaternion root_rot = mRoot.getWorldRotation(); + LLQuaternion inv_root_rot = ~root_rot; LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * ~root_rot; + LLVector3 local_camera_at = camera_to_av * inv_root_rot; LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); local_camera_up.normalize(); - local_camera_up = local_camera_up * ~root_rot; + local_camera_up = local_camera_up * inv_root_rot; + + LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, + mBodySize.mV[VY] * 0.4f, + mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); - local_camera_up.scaleVec(mBodySize * 0.5f); - local_camera_at.scaleVec(mBodySize * 0.5f); + local_camera_up.scaleVec(avatar_ellipsoid); + local_camera_at.scaleVec(avatar_ellipsoid); - LLVector3 name_position = mRoot.getWorldPosition(); - name_position[VZ] -= mPelvisToFoot; - name_position[VZ] += (mBodySize[VZ]* 0.55f); + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + + if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) + { + mTargetRootToHeadOffset = head_offset; + } + + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + + LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * 15.f; + name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; - return name_position; + mNameText->setPositionAgent(name_position); } void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3333,7 +3331,7 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) else { color_name = "NameTagMismatch"; - } + } } else { @@ -3370,9 +3368,9 @@ bool LLVOAvatar::isVisuallyMuted() static LLCachedControl max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); - return LLMuteList::getInstance()->isMuted(getID()) || - (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); + return LLMuteList::getInstance()->isMuted(getID()) + || (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) + || (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); } //------------------------------------------------------------------------ @@ -3413,8 +3411,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - LLVector3d root_pos_global; - if (!mIsBuilt) { return FALSE; @@ -3428,7 +3424,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { mTimeVisible.reset(); } - //-------------------------------------------------------------------- // the rest should only be done occasionally for far away avatars @@ -3823,10 +3818,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if ( playSound ) { -// F32 gain = clamp_rescale( mSpeedAccum, -// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - const F32 STEP_VOLUME = 0.1f; const LLUUID& step_sound_id = getStepSound(); @@ -4043,13 +4034,6 @@ void LLVOAvatar::updateVisibility() { releaseMeshData(); } - // this breaks off-screen chat bubbles - //if (mNameText) - //{ - // mNameText->markDead(); - // mNameText = NULL; - // sNumVisibleChatBubbles--; - //} } mVisible = visible; @@ -4065,46 +4049,6 @@ bool LLVOAvatar::shouldAlphaMask() } -U32 LLVOAvatar::renderSkinnedAttachments() -{ - /*U32 num_indices = 0; - - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = (*attachment_iter); - if (attached_object && !attached_object->isHUDAttachment()) - { - const LLDrawable* drawable = attached_object->mDrawable; - if (drawable) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face->isState(LLFace::RIGGED)) - { - - } - } - } - } - - return num_indices;*/ - return 0; -} - //----------------------------------------------------------------------------- // renderSkinned() //----------------------------------------------------------------------------- @@ -4125,11 +4069,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -5790,36 +5734,34 @@ BOOL LLVOAvatar::updateJointLODs() F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); F32 area_scale = 0.16f; + if (isSelf()) { - if (isSelf()) - { - if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - mAdjustedPixelArea = mPixelArea*area_scale; - } - } - else if (mIsDummy) + if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) { mAdjustedPixelArea = MAX_PIXEL_AREA; } else { - // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars - mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + mAdjustedPixelArea = mPixelArea*area_scale; } + } + else if (mIsDummy) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars + mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + } - // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); - if (res) - { - sNumLODChangesThisFrame++; - dirtyMesh(2); - return TRUE; - } + // now select meshes to render based on adjusted pixel area + BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + if (res) + { + sNumLODChangesThisFrame++; + dirtyMesh(2); + return TRUE; } return FALSE; @@ -6109,25 +6051,18 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) if ( pVObj ) { const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if ( pSkinData ) - { - const int jointCnt = pSkinData->mJointNames.size(); - bool fullRig = ( jointCnt>=20 ) ? true : false; - if ( fullRig ) + if (pSkinData + && pSkinData->mJointNames.size() > 20 // full rig + && pSkinData->mAlternateBindMatrix.size() > 0) + { + LLVOAvatar::resetJointPositionsToDefault(); + //Need to handle the repositioning of the cam, updating rig data etc during outfit editing + //This handles the case where we detach a replacement rig. + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -6281,11 +6216,7 @@ void LLVOAvatar::getOffObject() at_axis.mV[VZ] = 0.f; at_axis.normalize(); gAgent.resetAxes(at_axis); - - //reset orientation -// mRoot.setRotation(avWorldRot); gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); - gAgentCamera.setSitCamera(LLUUID::null); } } @@ -6335,7 +6266,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const } else { -// return LLColor4( .5f, .5f, .5f, .5f ); return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color } } @@ -7067,10 +6997,6 @@ LLBBox LLVOAvatar::getHUDBBox() const return bbox; } -void LLVOAvatar::rebuildHUD() -{ -} - //----------------------------------------------------------------------------- // onFirstTEMessageReceived() //----------------------------------------------------------------------------- @@ -7192,7 +7118,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) && baked_index != BAKED_SKIRT) { setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, + TRUE, + LLViewerTexture::BOOST_NONE, + LLViewerTexture::LOD_TEXTURE)); } } @@ -7483,11 +7412,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_ // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - /* if(id == head_baked->getID()) - mHeadBakedLoaded = TRUE; - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -7718,111 +7642,111 @@ LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); } -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ - if (node->hasName("bone")) - { - mIsJoint = TRUE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - llwarns << "Bone without name" << llendl; - return FALSE; - } - } - else if (node->hasName("collision_volume")) - { - mIsJoint = FALSE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - mName = "Collision Volume"; - } - } - else - { - llwarns << "Invalid node " << node->getName() << llendl; - return FALSE; - } - - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - if (!node->getFastAttributeVector3(pos_string, mPos)) - { - llwarns << "Bone without position" << llendl; - return FALSE; - } - - static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); - if (!node->getFastAttributeVector3(rot_string, mRot)) - { - llwarns << "Bone without rotation" << llendl; - return FALSE; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!node->getFastAttributeVector3(scale_string, mScale)) - { - llwarns << "Bone without scale" << llendl; - return FALSE; - } - - if (mIsJoint) - { - static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); - if (!node->getFastAttributeVector3(pivot_string, mPivot)) - { - llwarns << "Bone without pivot" << llendl; - return FALSE; - } - } - - // parse children - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; - if (!child_info->parseXml(child)) - { - delete child_info; - return FALSE; - } - mChildList.push_back(child_info); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ - static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); - if (!node->getFastAttributeS32(num_bones_string, mNumBones)) - { - llwarns << "Couldn't find number of bones." << llendl; - return FALSE; - } - - static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); - node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; - if (!info->parseXml(child)) - { - delete info; - llwarns << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } - mBoneInfoList.push_back(info); - } - return TRUE; -} +////----------------------------------------------------------------------------- +//// LLVOAvatarBoneInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +//{ +// if (node->hasName("bone")) +// { +// mIsJoint = TRUE; +// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +// if (!node->getFastAttributeString(name_string, mName)) +// { +// llwarns << "Bone without name" << llendl; +// return FALSE; +// } +// } +// else if (node->hasName("collision_volume")) +// { +// mIsJoint = FALSE; +// static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +// if (!node->getFastAttributeString(name_string, mName)) +// { +// mName = "Collision Volume"; +// } +// } +// else +// { +// llwarns << "Invalid node " << node->getName() << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); +// if (!node->getFastAttributeVector3(pos_string, mPos)) +// { +// llwarns << "Bone without position" << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); +// if (!node->getFastAttributeVector3(rot_string, mRot)) +// { +// llwarns << "Bone without rotation" << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); +// if (!node->getFastAttributeVector3(scale_string, mScale)) +// { +// llwarns << "Bone without scale" << llendl; +// return FALSE; +// } +// +// if (mIsJoint) +// { +// static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); +// if (!node->getFastAttributeVector3(pivot_string, mPivot)) +// { +// llwarns << "Bone without pivot" << llendl; +// return FALSE; +// } +// } +// +// // parse children +// LLXmlTreeNode* child; +// for( child = node->getFirstChild(); child; child = node->getNextChild() ) +// { +// LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; +// if (!child_info->parseXml(child)) +// { +// delete child_info; +// return FALSE; +// } +// mChildList.push_back(child_info); +// } +// return TRUE; +//} +// +////----------------------------------------------------------------------------- +//// LLVOAvatarSkeletonInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +//{ +// static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); +// if (!node->getFastAttributeS32(num_bones_string, mNumBones)) +// { +// llwarns << "Couldn't find number of bones." << llendl; +// return FALSE; +// } +// +// static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); +// node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); +// +// LLXmlTreeNode* child; +// for( child = node->getFirstChild(); child; child = node->getNextChild() ) +// { +// LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; +// if (!info->parseXml(child)) +// { +// delete info; +// llwarns << "Error parsing bone in skeleton file" << llendl; +// return FALSE; +// } +// mBoneInfoList.push_back(info); +// } +// return TRUE; +//} //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses nodes from XML tree diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index dd0317f555..e84acd51ff 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -66,8 +66,9 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -232,7 +233,7 @@ public: void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); void idleUpdateNameTagText(BOOL new_name); - LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last); + void idleUpdateNameTagPosition(const LLVector3& root_pos_last); void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); @@ -317,6 +318,8 @@ public: F32 mLastPelvisToFoot; F32 mPelvisFixup; F32 mLastPelvisFixup; + LLVector3 mCurRootToHeadOffset; + LLVector3 mTargetRootToHeadOffset; LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; @@ -325,7 +328,7 @@ protected: void buildCharacter(); virtual BOOL loadAvatar(); - BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); private: BOOL mIsBuilt; // state of deferred character building @@ -369,7 +372,7 @@ public: //-------------------------------------------------------------------- private: static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + static LLXMLNodePtr sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** @@ -387,7 +390,6 @@ public: U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); F32 getLastSkinTime() { return mLastSkinTime; } - U32 renderSkinnedAttachments(); U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); static void deleteCachedImages(bool clearAll=true); @@ -735,7 +737,6 @@ public: public: BOOL hasHUDAttachment() const; LLBBox getHUDBBox() const; - void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; BOOL canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c523a78b22..fc499bfe9c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4678,11 +4678,6 @@ void LLPipeline::rebuildPools() } max_count--; } - - if (isAgentAvatarValid()) - { - gAgentAvatarp->rebuildHUD(); - } } void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) -- cgit v1.2.3 From 2eb0096dd7f173debc27c155c57969ae5cb67682 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 5 Apr 2012 17:50:22 -0700 Subject: added support for LLInitParam::Lazy to support lazy-initialized non-param-block values --- indra/llxuixml/llinitparam.h | 94 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 6fffb73acd..6c054b934b 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -369,11 +369,30 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; + struct IS_BLOCK {}; + struct NOT_BLOCK {}; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template + struct IsBlock + { + static const bool value = false; + typedef NOT_BLOCK value_t; + }; + + template + struct IsBlock + { + static const bool value = true; + typedef IS_BLOCK value_t; + }; + class BaseBlock { public: //TODO: implement in terms of owned_ptr - template + template class Lazy { public: @@ -404,7 +423,7 @@ namespace LLInitParam } } - Lazy& operator = (const Lazy& other) + Lazy& operator = (const Lazy& other) { if (other.mPtr) { @@ -462,6 +481,7 @@ namespace LLInitParam mutable T* mPtr; }; + // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount { @@ -611,19 +631,6 @@ namespace LLInitParam }; - // these templates allow us to distinguish between template parameters - // that derive from BaseBlock and those that don't - template - struct IsBlock - { - static const bool value = false; - }; - - template - struct IsBlock - { - static const bool value = true; - }; template::value> class ParamValue : public NAME_VALUE_LOOKUP @@ -805,7 +812,7 @@ namespace LLInitParam template, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBlock >::value> + bool VALUE_IS_BLOCK = IsBlock::value> class TypedParam : public Param, public ParamValue @@ -1034,7 +1041,7 @@ namespace LLInitParam } else { - typed_param.serializeBlock(parser, name_stack, &static_cast(*static_cast(diff_param))); + typed_param.serializeBlock(parser, name_stack, static_cast(diff_param)); } } @@ -1582,7 +1589,7 @@ namespace LLInitParam friend class ChoiceBlock; typedef Alternative self_t; - typedef TypedParam >::value> super_t; + typedef TypedParam::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator =; @@ -1700,7 +1707,7 @@ namespace LLInitParam class Optional : public TypedParam { public: - typedef TypedParam >::value> super_t; + typedef TypedParam::value> super_t; typedef typename super_t::value_assignment_t value_assignment_t; using super_t::operator(); @@ -1729,7 +1736,7 @@ namespace LLInitParam class Mandatory : public TypedParam { public: - typedef TypedParam >::value> super_t; + typedef TypedParam::value> super_t; typedef Mandatory self_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1765,7 +1772,7 @@ namespace LLInitParam class Multiple : public TypedParam { public: - typedef TypedParam >::value> super_t; + typedef TypedParam::value> super_t; typedef Multiple self_t; typedef typename super_t::container_t container_t; typedef typename super_t::value_assignment_t value_assignment_t; @@ -1948,20 +1955,21 @@ namespace LLInitParam }; template - struct IsBlock, TypeValues > > , BLOCK_IDENTIFIER> + struct IsBlock, BLOCK_IDENTIFIER> { - static const bool value = true;//IsBlock::value; + static const bool value = true; }; - template - struct ParamCompare, false> + template + struct IsBlock, BLOCK_IDENTIFIER> { - static bool equals(const T&a, const T &b) - { - return a == b; - } + static const bool value = false; + }; - static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) + template + struct ParamCompare, false> + { + static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) { if (a.empty() || b.empty()) return false; return a.get() == b.get(); @@ -1969,14 +1977,14 @@ namespace LLInitParam }; - template - class ParamValue , - TypeValues >, - VALUE_IS_BLOCK> + template + class ParamValue , + TypeValues >, + true> : public TypeValues { public: - typedef ParamValue , TypeValues >, false> self_t; + typedef ParamValue , TypeValues >, true> self_t; typedef const T& value_assignment_t; typedef T value_t; @@ -1985,7 +1993,7 @@ namespace LLInitParam mValidated(false) {} - ParamValue(const BaseBlock::Lazy& other) + ParamValue(const BaseBlock::Lazy& other) : mValue(other), mValidated(false) {} @@ -2010,11 +2018,6 @@ namespace LLInitParam return mValue.get(); } - operator const BaseBlock&() const - { - return mValue.get(); - } - operator value_assignment_t() const { return mValue.get(); @@ -2030,11 +2033,14 @@ namespace LLInitParam return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { if (mValue.empty()) return; - mValue.get().serializeBlock(p, name_stack, diff_block); + const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) + ? &(diff_block->mValue.get()) + : NULL; + mValue.get().serializeBlock(p, name_stack, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const @@ -2063,7 +2069,7 @@ namespace LLInitParam mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy mValue; + BaseBlock::Lazy mValue; }; template <> -- cgit v1.2.3 From 6dd7029942dcc381d670657e0c4bb7d8dcd24594 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 5 Apr 2012 18:11:45 -0700 Subject: optimized Lazy params - don't generate block when checking validity or merging --- indra/llxuixml/llinitparam.h | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 6c054b934b..1f0dec5d94 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -436,6 +436,12 @@ namespace LLInitParam return *this; } + bool operator==(const Lazy& other) const + { + if (empty() || other.empty()) return false; + return *mPtr == *other.mPtr; + } + bool empty() const { return mPtr == NULL; @@ -1966,17 +1972,6 @@ namespace LLInitParam static const bool value = false; }; - template - struct ParamCompare, false> - { - static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) - { - if (a.empty() || b.empty()) return false; - return a.get() == b.get(); - } - }; - - template class ParamValue , TypeValues >, @@ -2045,19 +2040,17 @@ namespace LLInitParam bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { - if (mValue.empty()) return false; - return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { - return mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); } bool validateBlock(bool emit_errors = true) const { - return mValue.get().validateBlock(emit_errors); + return mValue.empty() || mValue.get().validateBlock(emit_errors); } static BlockDescriptor& getBlockDescriptor() -- cgit v1.2.3 From 7996857500004ed9b717e049423c52be96db9191 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Thu, 12 Apr 2012 00:43:37 +0300 Subject: CHUI-80 FIXED Implemented volume indicator pop-up. It is invoked by clicking on any speaking indicator except yours. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llavataractions.cpp | 26 +++ indra/newview/llavataractions.h | 10 + indra/newview/llfloatervoicevolume.cpp | 209 +++++++++++++++++++++ indra/newview/llfloatervoicevolume.h | 35 ++++ indra/newview/llinspectavatar.cpp | 3 +- indra/newview/lloutputmonitorctrl.cpp | 12 ++ indra/newview/lloutputmonitorctrl.h | 1 + indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/xui/en/floater_voice_volume.xml | 59 ++++++ 10 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 indra/newview/llfloatervoicevolume.cpp create mode 100644 indra/newview/llfloatervoicevolume.h create mode 100644 indra/newview/skins/default/xui/en/floater_voice_volume.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85b943c70..6197856512 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -244,6 +244,7 @@ set(viewer_SOURCE_FILES llfloateruipreview.cpp llfloaterurlentry.cpp llfloatervoiceeffect.cpp + llfloatervoicevolume.cpp llfloaterwebcontent.cpp llfloaterwebprofile.cpp llfloaterwhitelistentry.cpp @@ -800,6 +801,7 @@ set(viewer_HEADER_FILES llfloateruipreview.h llfloaterurlentry.h llfloatervoiceeffect.h + llfloatervoicevolume.h llfloaterwebcontent.h llfloaterwebprofile.h llfloaterwhitelistentry.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 9a7cdcfa21..ac14ec2cc0 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -808,6 +808,26 @@ void LLAvatarActions::toggleBlock(const LLUUID& id) } } +// static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ + std::string name; + gCacheName->getFullName(id, name); // needed for mute + + LLMuteList* mute_list = LLMuteList::getInstance(); + bool is_muted = mute_list->isMuted(id, LLMute::flagVoiceChat); + + LLMute mute(id, name, LLMute::AGENT); + if (!is_muted) + { + mute_list->add(mute, LLMute::flagVoiceChat); + } + else + { + mute_list->remove(mute, LLMute::flagVoiceChat); + } +} + // static bool LLAvatarActions::canOfferTeleport(const LLUUID& id) { @@ -1022,6 +1042,12 @@ bool LLAvatarActions::isBlocked(const LLUUID& id) return LLMuteList::getInstance()->isMuted(id, name); } +// static +bool LLAvatarActions::isVoiceMuted(const LLUUID& id) +{ + return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +} + // static bool LLAvatarActions::canBlock(const LLUUID& id) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 748b7cb3d1..e5dad74fc8 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -123,6 +123,11 @@ public: */ static void toggleBlock(const LLUUID& id); + /** + * Block/unblock the avatar voice. + */ + static void toggleMuteVoice(const LLUUID& id); + /** * Return true if avatar with "id" is a friend */ @@ -133,6 +138,11 @@ public: */ static bool isBlocked(const LLUUID& id); + /** + * @return true if the avatar voice is blocked + */ + static bool isVoiceMuted(const LLUUID& id); + /** * @return true if you can block the avatar */ diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp new file mode 100644 index 0000000000..87b388b30a --- /dev/null +++ b/indra/newview/llfloatervoicevolume.cpp @@ -0,0 +1,209 @@ +/** + * @file llfloatervoicevolume.cpp + * + * $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 "llfloatervoicevolume.h" + +// Linden libraries +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lltextbox.h" + +// viewer files +#include "llagent.h" +#include "llavataractions.h" +#include "llinspect.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +class LLAvatarName; + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolume +////////////////////////////////////////////////////////////////////////////// + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. +class LLFloaterVoiceVolume : public LLInspect, LLTransientFloater +{ + friend class LLFloaterReg; + +public: + // avatar_id - Avatar ID for which to show information + // Inspector will be positioned relative to current mouse position + LLFloaterVoiceVolume(const LLSD& avatar_id); + virtual ~LLFloaterVoiceVolume(); + + /*virtual*/ BOOL postBuild(void); + + // Because floater is single instance, need to re-parse data on each spawn + // (for example, inspector about same avatar but in different position) + /*virtual*/ void onOpen(const LLSD& avatar_id); + + /*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } + +private: + // Set the volume slider to this user's current client-side volume setting, + // hiding/disabling if the user is not nearby. + void updateVolumeControls(); + + void onClickMuteVolume(); + void onVolumeChange(const LLSD& data); + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +private: + LLUUID mAvatarID; + // Need avatar name information to spawn friend add request + LLAvatarName mAvatarName; +}; + +LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) +: LLInspect(LLSD()) // single_instance, doesn't really need key +, mAvatarID() // set in onOpen() *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* +, mAvatarName() +{ + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); + LLTransientFloater::init(this); +} + +LLFloaterVoiceVolume::~LLFloaterVoiceVolume() +{ + LLTransientFloaterMgr::getInstance()->removeControlView(this); +} + +/*virtual*/ +BOOL LLFloaterVoiceVolume::postBuild(void) +{ + getChild("mute_btn")->setCommitCallback( + boost::bind(&LLFloaterVoiceVolume::onClickMuteVolume, this) ); + + getChild("volume_slider")->setCommitCallback( + boost::bind(&LLFloaterVoiceVolume::onVolumeChange, this, _2)); + + return TRUE; +} + + +// Multiple calls to showInstance("floater_voice_volume", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLFloaterVoiceVolume::onOpen(const LLSD& data) +{ + // Start open animation + LLInspect::onOpen(data); + + // Extract appropriate avatar id + mAvatarID = data["avatar_id"]; + + LLUI::positionViewNearMouse(this); + + getChild("avatar_name")->setValue(""); + updateVolumeControls(); + + LLAvatarNameCache::get(mAvatarID, + boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterVoiceVolume::updateVolumeControls() +{ + bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + + LLUICtrl* mute_btn = getChild("mute_btn"); + LLUICtrl* volume_slider = getChild("volume_slider"); + + // Do not display volume slider and mute button if it + // is ourself or we are not in a voice channel together + if (!voice_enabled || (mAvatarID == gAgent.getID())) + { + mute_btn->setVisible(false); + volume_slider->setVisible(false); + } + else + { + mute_btn->setVisible(true); + volume_slider->setVisible(true); + + // By convention, we only display and toggle voice mutes, not all mutes + bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); + bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + + mute_btn->setEnabled(!is_linden); + mute_btn->setValue(is_muted); + + volume_slider->setEnabled(!is_muted); + + F32 volume; + if (is_muted) + { + // it's clearer to display their volume as zero + volume = 0.f; + } + else + { + // actual volume + volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); + } + volume_slider->setValue((F64)volume); + } + +} + +void LLFloaterVoiceVolume::onClickMuteVolume() +{ + LLAvatarActions::toggleMuteVoice(mAvatarID); + updateVolumeControls(); +} + +void LLFloaterVoiceVolume::onVolumeChange(const LLSD& data) +{ + F32 volume = (F32)data.asReal(); + LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + +void LLFloaterVoiceVolume::onAvatarNameCache( + const LLUUID& agent_id, + const LLAvatarName& av_name) +{ + if (agent_id != mAvatarID) + { + return; + } + + getChild("avatar_name")->setValue(av_name.getCompleteName()); + mAvatarName = av_name; +} + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolumeUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterVoiceVolumeUtil::registerFloater() +{ + LLFloaterReg::add("floater_voice_volume", "floater_voice_volume.xml", + &LLFloaterReg::build); +} diff --git a/indra/newview/llfloatervoicevolume.h b/indra/newview/llfloatervoicevolume.h new file mode 100644 index 0000000000..8fcf7f250b --- /dev/null +++ b/indra/newview/llfloatervoicevolume.h @@ -0,0 +1,35 @@ +/** + * @file llfloatervoicevolume.h + * + * $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_LLFLOATERVOICEVOLUME_H +#define LL_LLFLOATERVOICEVOLUME_H + +namespace LLFloaterVoiceVolumeUtil +{ + // Register with LLFloaterReg + void registerFloater(); +} + +#endif // LL_LLFLOATERVOICEVOLUME_H diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 17d0b0ffbb..b2a8c6e3e6 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -558,8 +558,7 @@ void LLInspectAvatar::updateVolumeSlider() getChild("volume_slider")->setVisible(true); // By convention, we only display and toggle voice mutes, not all mutes - bool is_muted = LLMuteList::getInstance()-> - isMuted(mAvatarID, LLMute::flagVoiceChat); + bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); LLUICtrl* mute_btn = getChild("mute_btn"); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 85626d8783..096e714981 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -28,6 +28,7 @@ #include "lloutputmonitorctrl.h" // library includes +#include "llfloaterreg.h" #include "llui.h" // viewer includes @@ -241,6 +242,17 @@ void LLOutputMonitorCtrl::draw() gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE); } +// virtual +BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if (mSpeakerId != gAgentID) + { + LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); + } + + return TRUE; +} + void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/) { if (speaker_id.isNull() && mSpeakerId.notNull()) diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 2d23753d46..7b02e84744 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -68,6 +68,7 @@ public: // llview overrides virtual void draw(); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); void setPower(F32 val); F32 getPower(F32 val) const { return mPower; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bb870f7651..685ef44921 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -110,6 +110,7 @@ #include "llfloatertranslationsettings.h" #include "llfloateruipreview.h" #include "llfloatervoiceeffect.h" +#include "llfloatervoicevolume.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindowsize.h" #include "llfloaterworldmap.h" @@ -220,6 +221,7 @@ void LLViewerFloaterReg::registerFloaters() LLInspectGroupUtil::registerFloater(); LLInspectObjectUtil::registerFloater(); LLInspectRemoteObjectUtil::registerFloater(); + LLFloaterVoiceVolumeUtil::registerFloater(); LLNotificationsUI::registerFloater(); LLFloaterDisplayNameUtil::registerFloater(); diff --git a/indra/newview/skins/default/xui/en/floater_voice_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_volume.xml new file mode 100644 index 0000000000..9346295d5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_volume.xml @@ -0,0 +1,59 @@ + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.3 From 33e78bfe64240f71bcc40ca34950770ce549dc69 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Sat, 14 Apr 2012 02:04:37 +0300 Subject: CHUI-78 WIP Re-combined view and sort menus in the People panel. --- .../default/xui/en/menu_people_friends_sort.xml | 26 ---------------- .../default/xui/en/menu_people_friends_view.xml | 21 +++++++++++++ .../skins/default/xui/en/menu_people_groups.xml | 4 +-- .../default/xui/en/menu_people_nearby_sort.xml | 36 ---------------------- .../default/xui/en/menu_people_nearby_view.xml | 31 +++++++++++++++++++ .../default/xui/en/menu_people_recent_sort.xml | 26 ---------------- .../default/xui/en/menu_people_recent_view.xml | 21 +++++++++++++ .../newview/skins/default/xui/en/panel_people.xml | 35 +++++++++++---------- 8 files changed, 93 insertions(+), 107 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/menu_people_friends_sort.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_people_recent_sort.xml diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml deleted file mode 100644 index 532e295386..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_friends_sort.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index 14a3e1f13d..eab7b8c085 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -3,6 +3,27 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + + + + + + + + + - - + diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml deleted file mode 100644 index cf7f4f4fce..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_sort.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml index 4c94cf53af..da88ca9f4d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -3,6 +3,37 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + + + + + + + + + + + + + - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 0eaca47d9a..1dbc90dd2b 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -3,6 +3,27 @@ name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false"> + + + + + + + + + + + + - + + + + + - + + width="384" /> + diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d683116eb8..b415ba780d 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,20 +1,21 @@ + width="394"> + width="394"> + width="387"> + width="374" /> + width="394"> + width="384" /> -- cgit v1.2.3 From fe252836ebfb8a1247b0ae3222056d0543203a44 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 30 May 2012 22:58:22 +0300 Subject: Build fix --- indra/newview/llimconversation.cpp | 2 ++ indra/newview/llnearbychatbar.cpp | 7 ------- indra/newview/llnearbychatbar.h | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 7220ab6a82..f5d84e80c1 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -25,6 +25,8 @@ * $/LicenseInfo$ */ +#include "llviewerprecompiledheaders.h" + #include "llpanelimcontrolpanel.h" #include "lldraghandle.h" diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 82c00253e8..68934be11a 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -116,8 +116,6 @@ BOOL LLNearbyChatBar::postBuild() // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - // childSetAction("voice_call_btn", boost::bind(&LLNearbyChatBar::onCallButtonClicked, this)); - enableResizeCtrls(true, true, false); addToHost(); @@ -125,11 +123,6 @@ BOOL LLNearbyChatBar::postBuild() return LLIMConversation::postBuild();; } -void LLNearbyChatBar::onCallButtonClicked() -{ - LLAgent::toggleMicrophone(NULL); -} - void LLNearbyChatBar::enableDisableCallBtn() { // bool btn_enabled = LLAgent::isActionAllowed("speak"); diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index e714c04498..b7c4c993c6 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -88,8 +88,6 @@ protected: void displaySpeakingIndicator(); - void onCallButtonClicked(); - // set the enable/disable state for the Call button virtual void enableDisableCallBtn(); -- cgit v1.2.3 From bba0f4f74e56d911df8fc534d83cd4a84993bc8b Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Thu, 31 May 2012 16:37:22 +0300 Subject: CHUI-119 WIP --- indra/newview/CMakeLists.txt | 4 - indra/newview/llagent.cpp | 6 +- indra/newview/llchatitemscontainerctrl.cpp | 6 +- indra/newview/llfloatertranslationsettings.cpp | 4 +- indra/newview/llgesturemgr.cpp | 4 +- indra/newview/llimconversation.cpp | 97 ++- indra/newview/llimconversation.h | 12 +- indra/newview/llimfloater.cpp | 67 +- indra/newview/llimfloater.h | 9 +- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llimview.cpp | 5 +- indra/newview/llnearbychat.cpp | 840 ++++++++++++++++++--- indra/newview/llnearbychat.h | 107 ++- indra/newview/llnearbychatbar.cpp | 709 ----------------- indra/newview/llnearbychatbar.h | 105 --- indra/newview/llnearbychatbarlistener.cpp | 4 +- indra/newview/llnearbychatbarlistener.h | 6 +- indra/newview/llnearbychathandler.cpp | 9 +- indra/newview/llnotificationtiphandler.cpp | 5 +- indra/newview/llpanelimcontrolpanel.cpp | 81 -- indra/newview/llviewerfloaterreg.cpp | 4 +- indra/newview/llviewergesture.cpp | 4 +- indra/newview/llviewerkeyboard.cpp | 10 +- indra/newview/llviewerwindow.cpp | 8 +- .../skins/default/xui/en/floater_chat_bar.xml | 202 ----- .../skins/default/xui/en/floater_im_session.xml | 119 ++- .../default/xui/en/panel_adhoc_control_panel.xml | 95 --- .../default/xui/en/panel_group_control_panel.xml | 60 -- .../skins/default/xui/en/panel_nearby_chat.xml | 19 +- 29 files changed, 1037 insertions(+), 1566 deletions(-) delete mode 100644 indra/newview/llnearbychatbar.cpp delete mode 100644 indra/newview/llnearbychatbar.h delete mode 100644 indra/newview/skins/default/xui/en/floater_chat_bar.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_group_control_panel.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 86d30c239f..509f9581d6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -332,7 +332,6 @@ set(viewer_SOURCE_FILES llnamelistctrl.cpp llnavigationbar.cpp llnearbychat.cpp - llnearbychatbar.cpp llnearbychathandler.cpp llnearbychatbarlistener.cpp llnetmap.cpp @@ -364,7 +363,6 @@ set(viewer_SOURCE_FILES llpanelgroupnotices.cpp llpanelgrouproles.cpp llpanelhome.cpp - llpanelimcontrolpanel.cpp llpanelland.cpp llpanellandaudio.cpp llpanellandmarkinfo.cpp @@ -890,7 +888,6 @@ set(viewer_HEADER_FILES llnamelistctrl.h llnavigationbar.h llnearbychat.h - llnearbychatbar.h llnearbychathandler.h llnearbychatbarlistener.h llnetmap.h @@ -916,7 +913,6 @@ set(viewer_HEADER_FILES llpanelgroupnotices.h llpanelgrouproles.h llpanelhome.h - llpanelimcontrolpanel.h llpanelland.h llpanellandaudio.h llpanellandmarkinfo.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3870a3be2e..0db03289d8 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llnotificationsutil.h" #include "llpaneltopinfobar.h" #include "llparcel.h" @@ -1778,7 +1778,7 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -1790,7 +1790,7 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 7477fbd656..477bdb3967 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@ #include "llfloaterreg.h" #include "lllocalcliprect.h" #include "lltrans.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llviewercontrol.h" #include "llagentdata.h" @@ -316,12 +316,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - LLNearbyChatBar::getInstance()->showHistory(); + LLNearbyChat::getInstance()->showHistory(); return FALSE; } } - LLNearbyChatBar::getInstance()->showHistory(); + LLNearbyChat::getInstance()->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 1a17183efd..bb01ce5a7e 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@ #include "llfloatertranslationsettings.h" // Viewer includes -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "lltranslate.h" #include "llviewercontrol.h" // for gSavedSettings @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 66ca76bfb0..26b63bdacb 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -51,7 +51,7 @@ #include "llviewermessage.h" #include "llvoavatarself.h" #include "llviewerstats.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llappearancemgr.h" #include "llgesturelistener.h" @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f5d84e80c1..893d8dc83f 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -27,25 +27,27 @@ #include "llviewerprecompiledheaders.h" -#include "llpanelimcontrolpanel.h" +#include "llimconversation.h" #include "lldraghandle.h" #include "llfloaterreg.h" -#include "llimconversation.h" #include "llimfloater.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) - , mControlPanel(NULL) + , LLEventTimer(REFRESH_INTERVAL) , mIsP2PChat(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) , mSessionID(session_id) + , mParticipantList(NULL) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); @@ -63,6 +65,15 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); } +LLIMConversation::~LLIMConversation() +{ + if (mParticipantList) + { + delete mParticipantList; + mParticipantList = NULL; + } +} + BOOL LLIMConversation::postBuild() { mCloseBtn = getChild("close_btn"); @@ -71,19 +82,12 @@ BOOL LLIMConversation::postBuild() mExpandCollapseBtn = getChild("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); - if (mControlPanel) - { - mControlPanel->setSessionId(mSessionID); - mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); - - mExpandCollapseBtn->setImageOverlay( - getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); - } - else - { - mExpandCollapseBtn->setEnabled(false); - getChild("im_control_panel_holder")->setVisible(false); - } + mParticipantListPanel = getChild("speakers_list_panel"); + mParticipantListPanel->setVisible( + mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel")); + mExpandCollapseBtn->setImageOverlay( + getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setEnabled(!mIsP2PChat); mTearOffBtn = getChild("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); @@ -93,6 +97,8 @@ BOOL LLIMConversation::postBuild() setOpenPositioning(LLFloaterEnums::OPEN_POSITIONING_NONE); } + buildParticipantList(); + if (isChatMultiTab()) { return LLFloater::postBuild(); @@ -104,6 +110,47 @@ BOOL LLIMConversation::postBuild() } +BOOL LLIMConversation::tick() +{ + // Need to resort the participant list if it's in sort by recent speaker order. + if (mParticipantList) + { + mParticipantList->update(); + } + + return false; +} + +void LLIMConversation::buildParticipantList() +{ if (mIsNearbyChat) + { + } + else + { + // for group and Ad-hoc chat we need to include agent into list + if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) + { + LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + mParticipantList = new LLParticipantList(speaker_manager, getChild("speakers_list"), true, false); + } + } +} + +void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +{ + // TODO: Check this code when when sort order menu will be added. (EM) + if (true || !mParticipantList) + return; + + std::string chosen_item = userdata.asString(); + + if (chosen_item == "sort_name") + { + mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); + } + +} + void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) { std::string item = userdata.asString(); @@ -162,11 +209,11 @@ void LLIMConversation::updateHeaderAndToolbar() } bool is_control_panel_visible = false; - if (mControlPanel) + if (!mIsP2PChat) { // Control panel should be visible only in torn off floaters. is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); - mControlPanel->getParent()->setVisible(is_control_panel_visible); + mParticipantListPanel->setVisible(is_control_panel_visible); } // Display collapse image (<<) if the floater is hosted @@ -215,10 +262,10 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (nearby_chat_bar) + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); + if (nearby_chat) { - nearby_chat_bar->reloadMessages(); + nearby_chat->reloadMessages(); } } @@ -240,12 +287,12 @@ void LLIMConversation::onSlide(LLIMConversation* self) } else ///< floater is torn off { - if (self->mControlPanel) + if (!self->mIsP2PChat) { - bool expand = !self->mControlPanel->getParent()->getVisible(); + bool expand = !self->mParticipantListPanel->getVisible(); // Expand/collapse the IM control panel - self->mControlPanel->getParent()->setVisible(expand); + self->mParticipantListPanel->setVisible(expand); gSavedSettings.setBOOL("IMShowControlPanel", expand); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 501977e061..d31ae0808a 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -28,19 +28,24 @@ #ifndef LL_IMCONVERSATION_H #define LL_IMCONVERSATION_H +#include "lllayoutstack.h" +#include "llparticipantlist.h" #include "lltransientdockablefloater.h" #include "llviewercontrol.h" +#include "lleventtimer.h" class LLPanelChatControlPanel; class LLIMConversation : public LLTransientDockableFloater + , public LLEventTimer { public: LOG_CLASS(LLIMConversation); LLIMConversation(const LLUUID& session_id); + ~LLIMConversation(); // reload all message with new settings of visual modes static void processChatHistoryStyleUpdate(); @@ -75,13 +80,16 @@ protected: // set the enable/disable state for the Call button virtual void enableDisableCallBtn() = 0; -// /* virtual */ void updateTitleButtons(); + void buildParticipantList(); + void onSortMenuItemClicked(const LLSD& userdata); + /*virtual*/ BOOL tick(); - LLPanelChatControlPanel* mControlPanel; bool mIsNearbyChat; bool mIsP2PChat; + LLLayoutPanel* mParticipantListPanel; + LLParticipantList* mParticipantList; LLUUID mSessionID; LLButton* mExpandCollapseBtn; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 5339bcb936..c99da9e9c1 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -44,7 +44,6 @@ //#include "lllayoutstack.h" #include "lllineeditor.h" #include "lllogchat.h" -#include "llpanelimcontrolpanel.h" #include "llscreenchannel.h" #include "llsyswellwindow.h" #include "lltrans.h" @@ -82,29 +81,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) { mIsP2PChat = mSession->isP2PSessionType(); mSessionInitialized = mSession->mSessionInitialized; - mDialog = mSession->mType; - switch (mDialog) - { - case IM_SESSION_CONFERENCE_START: - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); - break; - case IM_SESSION_GROUP_START: - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); - break; - case IM_SESSION_INVITE: - if (gAgent.isInGroup(mSessionID)) - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); - } - else - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); - } - break; - default: - break; - } } setOverlapsScreenChannel(true); @@ -113,24 +90,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) setDocked(true); } -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*) userdata; - self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); - return self->mControlPanel; -} - -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*) userdata; - self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); - self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); - return self->mControlPanel; -} - void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); @@ -409,8 +368,10 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, } // virtual -void LLIMFloater::draw() +BOOL LLIMFloater::tick() { + BOOL parents_retcode = LLIMConversation::tick(); + if ( mMeTyping ) { // Time out if user hasn't typed for a while. @@ -420,7 +381,7 @@ void LLIMFloater::draw() } } - LLTransientDockableFloater::draw(); + return parents_retcode; } //static @@ -643,16 +604,14 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) if (mSessionID != im_session_id) { mSessionID = im_session_id; - setKey(im_session_id); - if (mControlPanel) - { - mControlPanel->setSessionId(im_session_id); - } + boundVoiceChannel(); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mIsP2PChat = mSession && mSession->isP2PSessionType(); + + buildParticipantList(); } //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) @@ -841,10 +800,14 @@ void LLIMFloater::setTyping(bool typing) } } - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) - speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); - + if (!mIsNearbyChat) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); + } + } } void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index c7793f73eb..24f28c8aee 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -61,15 +61,15 @@ public: /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. - /*virtual*/ void draw(); - - static void* createPanelGroupControl(void* userdata); - static void* createPanelAdHocControl(void* userdata); + /*virtual*/ BOOL tick(); static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); static void addToHost(const LLUUID& session_id); + static void* createPanelGroupControl(void* userdata); + static void* createPanelAdHocControl(void* userdata); + // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); @@ -147,7 +147,6 @@ private: static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); void setTyping(bool typing); - void onCallButtonClicked(); // set the enable/disable state for the Call button diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f72ddef412..3b6240de44 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -31,7 +31,7 @@ #include "llfloaterreg.h" #include "lllayoutstack.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagent.h" #include "llavatariconctrl.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c3ac1d32cb..46b1cb5f18 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -907,7 +907,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const LLIMSession* session = findIMSession(session_id); if (!session) { - llwarns << "session " << session_id << "does not exist " << llendl; + llwarns << "session " << session_id << " does not exist " << llendl; return LLUUID::null; } @@ -2483,8 +2483,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - LLNearbyChat* nearby_chat = chat_bar->findChild("nearby_chat"); + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); if(nearby_chat) { diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 497690d656..2d7095957e 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -1,8 +1,8 @@ /** * @file LLNearbyChat.cpp - * @brief Nearby chat history scrolling panel implementation + * @brief LLNearbyChat class implementation * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -25,34 +25,50 @@ */ #include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llrootview.h" -//#include "llchatitemscontainerctrl.h" + +#include "message.h" + #include "lliconctrl.h" +#include "llappviewer.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llimfloatercontainer.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" #include "lllogchat.h" #include "llresizebar.h" #include "llresizehandle.h" +#include "lldraghandle.h" #include "llmenugl.h" -#include "llviewermenu.h"//for gMenuHolder - +#include "llviewermenu.h" // for gMenuHolder #include "llnearbychathandler.h" #include "llchannelmanager.h" - -#include "llagent.h" // gAgent #include "llchathistory.h" #include "llstylemap.h" - #include "llavatarnamecache.h" - -#include "lldraghandle.h" - -#include "llnearbychatbar.h" #include "llfloaterreg.h" #include "lltrans.h" +#include "llfirstuse.h" +#include "llnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" + +S32 LLNearbyChat::sLastSpecialChatChannel = 0; + + // --- 2 functions in the global namespace :( --- bool isWordsName(const std::string& name) { @@ -88,90 +104,83 @@ std::string appendTime() return timeStr; } -static const S32 RESIZE_BAR_THICKNESS = 3; -static LLRegisterPanelClassWrapper t_panel_nearby_chat("panel_nearby_chat"); +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p) - : LLPanel(p), - mChatHistory(NULL) -{ -} +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); -BOOL LLNearbyChat::postBuild() -{ - //menu - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +struct LLChatTypeTrigger { + std::string name; + EChatType type; +}; - enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); - registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); +static LLChatTypeTrigger sChatTypeTriggers[] = { + { "/whisper" , CHAT_TYPE_WHISPER}, + { "/shout" , CHAT_TYPE_SHOUT} +}; - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) - mPopupMenuHandle = menu->getHandle(); - gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); +LLNearbyChat::LLNearbyChat(const LLSD& key) +: LLIMConversation(key), + mChatBox(NULL), + mChatHistory(NULL), + mOutputMonitor(NULL), + mSpeakerMgr(NULL), + mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) +{ + mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +} - mChatHistory = getChild("chat_history"); +//virtual +BOOL LLNearbyChat::postBuild() +{ + mChatBox = getChild("chat_editor"); - return LLPanel::postBuild(); -} + mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); + mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); + mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); + mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); + mChatBox->setIgnoreArrowKeys( FALSE ); + mChatBox->setCommitOnFocusLost( FALSE ); + mChatBox->setRevertOnEsc( FALSE ); + mChatBox->setIgnoreTab(TRUE); + mChatBox->setPassDelete(TRUE); + mChatBox->setReplaceNewlinesWithSpaces(FALSE); + mChatBox->setEnableLineHistory(TRUE); + mChatBox->setFont(LLViewerChat::getChatFont()); + mOutputMonitor = getChild("chat_zone_indicator"); + mOutputMonitor->setVisible(FALSE); -void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast(chat); + // Register for font change notifications + LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); - if(tmp_chat.mTimeStr.empty()) - tmp_chat.mTimeStr = appendTime(); + enableResizeCtrls(true, true, false); - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = true; + addToHost(); - mChatHistory->appendMessage(chat, chat_args); - } -} + //for menu + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) -{ - appendMessage(chat, args); + enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); + registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - if(archive) + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(menu) { - mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) - mMessageArchive.erase(mMessageArchive.begin()); + mPopupMenuHandle = menu->getHandle(); } - // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) - { - std::string from_name = chat.mFromName; - - if (chat.mSourceType == CHAT_SOURCE_AGENT) - { - // if the chat is coming from an agent, log the complete name - LLAvatarName av_name; - LLAvatarNameCache::get(chat.mFromID, &av_name); + // obsolete, but may be needed for backward compatibility? + gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); - if (!av_name.mIsDisplayNameDefault) - { - from_name = av_name.getCompleteName(); - } - } + mChatHistory = getChild("chat_history"); - LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); - } + return LLIMConversation::postBuild();; } void LLNearbyChat::onNearbySpeakers() @@ -189,33 +198,40 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) { std::string str = userdata.asString(); if(str == "nearby_people") - onNearbySpeakers(); + onNearbySpeakers(); return false; } -void LLNearbyChat::removeScreenChat() +void LLNearbyChat::getAllowedRect(LLRect& rect) { - LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - if(chat_channel) - { - chat_channel->removeToastsFromChannel(); - } + rect = gViewerWindow->getWorldViewRectScaled(); } - -void LLNearbyChat::setVisible(BOOL visible) +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusReceived() { - if(visible) - { - removeScreenChat(); - } - - LLPanel::setVisible(visible); + setBackgroundOpaque(true); + LLIMConversation::onFocusReceived(); } +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusLost() +{ + setBackgroundOpaque(false); + LLIMConversation::onFocusLost(); +} -void LLNearbyChat::getAllowedRect(LLRect& rect) +BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) { - rect = gViewerWindow->getWorldViewRectScaled(); + //fix for EXT-6625 + //highlight NearbyChat history whenever mouseclick happen in NearbyChat + //setting focus to eidtor will force onFocusLost() call that in its turn will change + //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + + if(mChatHistory) + mChatHistory->setFocus(TRUE); + return LLPanel::handleMouseDown(x, y, mask); } void LLNearbyChat::reloadMessages() @@ -265,9 +281,9 @@ void LLNearbyChat::loadHistory() chat.mSourceType = CHAT_SOURCE_AGENT; if (from_id.isNull() && SYSTEM_FROM == from) - { + { chat.mSourceType = CHAT_SOURCE_SYSTEM; - + } else if (from_id.isNull()) { @@ -280,43 +296,117 @@ void LLNearbyChat::loadHistory() } } -//static -LLNearbyChat* LLNearbyChat::getInstance() +void LLNearbyChat::removeScreenChat() { - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - return chat_bar->findChild("nearby_chat"); + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + if(chat_channel) + { + chat_channel->removeToastsFromChannel(); + } } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() +void LLNearbyChat::setVisible(BOOL visible) { - setBackgroundOpaque(true); - LLPanel::onFocusReceived(); + if(visible) + { + removeScreenChat(); + } + + LLIMConversation::setVisible(visible); } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() +void LLNearbyChat::onCallButtonClicked() { - setBackgroundOpaque(false); - LLPanel::onFocusLost(); + LLAgent::toggleMicrophone(NULL); } -BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +void LLNearbyChat::enableDisableCallBtn() { - //fix for EXT-6625 - //highlight NearbyChat history whenever mouseclick happen in NearbyChat - //setting focus to eidtor will force onFocusLost() call that in its turn will change - //background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + // bool btn_enabled = LLAgent::isActionAllowed("speak"); + + getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); +} + +void LLNearbyChat::addToHost() +{ + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + + if (im_box) + { + im_box->addFloater(this, FALSE, LLTabContainer::END); + } + } +} + +// virtual +void LLNearbyChat::onOpen(const LLSD& key) +{ + LLIMConversation::onOpen(key); + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +bool LLNearbyChat::applyRectControl() +{ + bool rect_controlled = LLFloater::applyRectControl(); + +/* if (!mNearbyChat->getVisible()) + { + reshape(getRect().getWidth(), getMinHeight()); + enableResizeCtrls(true, true, false); + } + else + {*/ + enableResizeCtrls(true); + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +// } - if(mChatHistory) - mChatHistory->setFocus(TRUE); - return LLPanel::handleMouseDown(x, y, mask); + return rect_controlled; +} + +void LLNearbyChat::onChatFontChange(LLFontGL* fontp) +{ + // Update things with the new font whohoo + if (mChatBox) + { + mChatBox->setFont(fontp); + } +} + +//static +LLNearbyChat* LLNearbyChat::getInstance() +{ + return LLFloaterReg::getTypedInstance("chat_bar"); +} + +//static +//LLNearbyChat* LLNearbyChat::findInstance() +//{ +// return LLFloaterReg::findTypedInstance("chat_bar"); +//} + +void LLNearbyChat::showHistory() +{ + openFloater(); + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); + reshape(getRect().getWidth(), mExpandedHeight); + enableResizeCtrls(true); + storeRectControl(); } -void LLNearbyChat::draw() +void LLNearbyChat::showTranslationCheckbox(BOOL show) { + getChild("translate_chat_checkbox_lp")->setVisible(show); +} + +BOOL LLNearbyChat::tick() +{ + BOOL parents_retcode = LLIMConversation::tick(); + + displaySpeakingIndicator(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + // *HACK: Update transparency type depending on whether our children have focus. // This is needed because this floater is chrome and thus cannot accept focus, so // the transparency type setting code from LLFloater::setFocus() isn't reached. @@ -325,5 +415,511 @@ void LLNearbyChat::draw() setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); } - LLPanel::draw(); + return parents_retcode; } + +std::string LLNearbyChat::getCurrentChat() +{ + return mChatBox ? mChatBox->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + if( KEY_RETURN == key && mask == MASK_CONTROL) + { + // shout + sendChat(CHAT_TYPE_SHOUT); + handled = TRUE; + } + + return handled; +} + +BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ + U32 in_len = in_str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + bool string_was_found = false; + + for (S32 n = 0; n < cnt && !string_was_found; n++) + { + if (in_len <= sChatTypeTriggers[n].name.length()) + { + std::string trigger_trunc = sChatTypeTriggers[n].name; + LLStringUtil::truncate(trigger_trunc, in_len); + + if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + { + *out_str = sChatTypeTriggers[n].name; + string_was_found = true; + } + } + } + + return string_was_found; +} + +void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) +{ + LLFirstUse::otherAvatarChatFirst(false); + + LLNearbyChat* self = (LLNearbyChat *)userdata; + + LLWString raw_text = self->mChatBox->getWText(); + + // Can't trim the end, because that will cause autocompletion + // to eat trailing spaces that might be part of a gesture. + LLWStringUtil::trimHead(raw_text); + + S32 length = raw_text.length(); + + if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences + { + gAgent.startTyping(); + } + else + { + gAgent.stopTyping(); + } + + /* Doesn't work -- can't tell the difference between a backspace + that killed the selection vs. backspace at the end of line. + if (length > 1 + && text[0] == '/' + && key == KEY_BACKSPACE) + { + // the selection will already be deleted, but we need to trim + // off the character before + std::string new_text = raw_text.substr(0, length-1); + self->mInputEditor->setText( new_text ); + self->mInputEditor->setCursorToEnd(); + length = length - 1; + } + */ + + KEY key = gKeyboard->currentKey(); + + // Ignore "special" keys, like backspace, arrows, etc. + if (length > 1 + && raw_text[0] == '/' + && key < KEY_SPECIAL) + { + // we're starting a gesture, attempt to autocomplete + + std::string utf8_trigger = wstring_to_utf8str(raw_text); + std::string utf8_out_str(utf8_trigger); + + if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + S32 outlength = self->mChatBox->getLength(); // in characters + + // Select to end of line, starting from the character + // after the last one the user typed. + self->mChatBox->setSelection(length, outlength); + } + else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part + self->mChatBox->setCursorToEnd(); + } + + //llinfos << "GESTUREDEBUG " << trigger + // << " len " << length + // << " outlen " << out_str.getLength() + // << llendl; + } +} + +// static +void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ + // stop typing animation + gAgent.stopTyping(); +} + +void LLNearbyChat::onChatBoxFocusReceived() +{ + mChatBox->setEnabled(!gDisconnected); +} + +EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ + U32 length = str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + for (S32 n = 0; n < cnt; n++) + { + if (length >= sChatTypeTriggers[n].name.length()) + { + std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + + if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) + { + U32 trigger_length = sChatTypeTriggers[n].name.length(); + + // It's to remove space after trigger name + if (length > trigger_length && str[trigger_length] == ' ') + trigger_length++; + + str = str.substr(trigger_length, length); + + if (CHAT_TYPE_NORMAL == type) + return sChatTypeTriggers[n].type; + else + break; + } + } + } + + return type; +} + +void LLNearbyChat::sendChat( EChatType type ) +{ + if (mChatBox) + { + LLWString text = mChatBox->getConvertedText(); + if (!text.empty()) + { + // store sent line in history, duplicates will get filtered + mChatBox->updateHistory(); + // Check if this is destined for another channel + S32 channel = 0; + stripChannelNumber(text, &channel); + + std::string utf8text = wstring_to_utf8str(text); + // Try to trigger a gesture, if not chat to a script. + std::string utf8_revised_text; + if (0 == channel) + { + // discard returned "found" boolean + LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); + } + else + { + utf8_revised_text = utf8text; + } + + utf8_revised_text = utf8str_trim(utf8_revised_text); + + type = processChatTypeTriggers(type, utf8_revised_text); + + if (!utf8_revised_text.empty()) + { + // Chat with animation + sendChatFromViewer(utf8_revised_text, type, TRUE); + } + } + + mChatBox->setText(LLStringExplicit("")); + } + + gAgent.stopTyping(); + + // If the user wants to stop chatting on hitting return, lose focus + // and go out of chat mode. + if (gSavedSettings.getBOOL("CloseChatOnReturn")) + { + stopChat(); + } +} + + +void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) +{ + LLChat& tmp_chat = const_cast(chat); + + if(tmp_chat.mTimeStr.empty()) + tmp_chat.mTimeStr = appendTime(); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = true; + + mChatHistory->appendMessage(chat, chat_args); + } +} + +void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ + appendMessage(chat, args); + + if(archive) + { + mMessageArchive.push_back(chat); + if(mMessageArchive.size()>200) + mMessageArchive.erase(mMessageArchive.begin()); + } + + // logging + if (!args["do_not_log"].asBoolean() + && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + { + std::string from_name = chat.mFromName; + + if (chat.mSourceType == CHAT_SOURCE_AGENT) + { + // if the chat is coming from an agent, log the complete name + LLAvatarName av_name; + LLAvatarNameCache::get(chat.mFromID, &av_name); + + if (!av_name.mIsDisplayNameDefault) + { + from_name = av_name.getCompleteName(); + } + } + + LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); + } +} + + +void LLNearbyChat::onChatBoxCommit() +{ + if (mChatBox->getText().length() > 0) + { + sendChat(CHAT_TYPE_NORMAL); + } + + gAgent.stopTyping(); +} + +void LLNearbyChat::displaySpeakingIndicator() +{ + LLSpeakerMgr::speaker_list_t speaker_list; + LLUUID id; + + id.setNull(); + mSpeakerMgr->update(TRUE); + mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + + for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) + { + LLPointer s = *i; + if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) + { + id = s->mID; + break; + } + } + + if (!id.isNull()) + { + mOutputMonitor->setVisible(TRUE); + mOutputMonitor->setSpeakerId(id); + } + else + { + mOutputMonitor->setVisible(FALSE); + } +} + +void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ + sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) +{ + // Look for "/20 foo" channel chats. + S32 channel = 0; + LLWString out_text = stripChannelNumber(wtext, &channel); + std::string utf8_out_text = wstring_to_utf8str(out_text); + std::string utf8_text = wstring_to_utf8str(wtext); + + utf8_text = utf8str_trim(utf8_text); + if (!utf8_text.empty()) + { + utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); + } + + // Don't animate for chats people can't hear (chat to scripts) + if (animate && (channel == 0)) + { + if (type == CHAT_TYPE_WHISPER) + { + lldebugs << "You whisper " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); + } + else if (type == CHAT_TYPE_NORMAL) + { + lldebugs << "You say " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); + } + else if (type == CHAT_TYPE_SHOUT) + { + lldebugs << "You shout " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); + } + else + { + llinfos << "send_chat_from_viewer() - invalid volume" << llendl; + return; + } + } + else + { + if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) + { + lldebugs << "Channel chat: " << utf8_text << llendl; + } + } + + send_chat_from_viewer(utf8_out_text, type, channel); +} + +// static +void LLNearbyChat::startChat(const char* line) +{ + LLNearbyChat* cb = LLNearbyChat::getInstance(); + + if (cb ) + { + cb->setVisible(TRUE); + cb->setFocus(TRUE); + cb->mChatBox->setFocus(TRUE); + + if (line) + { + std::string line_string(line); + cb->mChatBox->setText(line_string); + } + + cb->mChatBox->setCursorToEnd(); + } +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLNearbyChat::stopChat() +{ + LLNearbyChat* cb = LLNearbyChat::getInstance(); + + if (cb) + { + cb->mChatBox->setFocus(FALSE); + + // stop typing animation + gAgent.stopTyping(); + } +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel) +{ + if (mesg[0] == '/' + && mesg[1] == '/') + { + // This is a "repeat channel send" + *channel = sLastSpecialChatChannel; + return mesg.substr(2, mesg.length() - 2); + } + else if (mesg[0] == '/' + && mesg[1] + && LLStringOps::isDigit(mesg[1])) + { + // This a special "/20" speak on a channel + S32 pos = 0; + + // Copy the channel number into a string + LLWString channel_string; + llwchar c; + do + { + c = mesg[pos+1]; + channel_string.push_back(c); + pos++; + } + while(c && pos < 64 && LLStringOps::isDigit(c)); + + // Move the pointer forward to the first non-whitespace char + // Check isspace before looping, so we can handle "/33foo" + // as well as "/33 foo" + while(c && iswspace(c)) + { + c = mesg[pos+1]; + pos++; + } + + sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); + *channel = sLastSpecialChatChannel; + return mesg.substr(pos, mesg.length() - pos); + } + else + { + // This is normal chat. + *channel = 0; + return mesg; + } +} + +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ChatFromViewer); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ChatData); + msg->addStringFast(_PREHASH_Message, utf8_out_text); + msg->addU8Fast(_PREHASH_Type, type); + msg->addS32("Channel", channel); + + gAgent.sendReliableMessage(); + + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); +} + +class LLChatCommandHandler : public LLCommandHandler +{ +public: + // not allowed from outside the app + LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + + // Your code here + bool handle(const LLSD& tokens, const LLSD& query_map, + LLMediaCtrl* web) + { + bool retval = false; + // Need at least 2 tokens to have a valid message. + if (tokens.size() < 2) + { + retval = false; + } + else + { + S32 channel = tokens[0].asInteger(); + // VWR-19499 Restrict function to chat channels greater than 0. + if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) + { + retval = true; + // Send unescaped message, see EXT-6353. + std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); + send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); + } + else + { + retval = false; + // Tell us this is an unsupported SLurl. + } + } + return retval; + } +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 62a41c17cb..b38111defa 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -1,8 +1,8 @@ - /** +/** * @file llnearbychat.h - * @brief nearby chat history scrolling panel implementation + * @brief LLNearbyChat class definition * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -24,9 +24,16 @@ * $/LicenseInfo$ */ -#ifndef LL_LLNEARBYCHAT_H_ -#define LL_LLNEARBYCHAT_H_ +#ifndef LL_LLNEARBYCHAT_H +#define LL_LLNEARBYCHAT_H +#include "llimconversation.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h" #include "llscrollbar.h" #include "llviewerchat.h" #include "llpanel.h" @@ -35,32 +42,88 @@ class LLResizeBar; class LLChatHistory; class LLNearbyChat - : public LLPanel + : public LLIMConversation { public: - LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); + // constructor for inline chat-bars (e.g. hosted in chat history window) + LLNearbyChat(const LLSD& key); + ~LLNearbyChat() {} - BOOL postBuild (); - - /** @param archive true - to save a message to the chat history log */ - void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); - void onNearbyChatContextMenuItemClicked(const LLSD& userdata); - bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual void draw(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); // focus overrides /*virtual*/ void onFocusLost(); /*virtual*/ void onFocusReceived(); - + /*virtual*/ void setVisible(BOOL visible); - + void loadHistory(); void reloadMessages(); - static LLNearbyChat* getInstance(); void removeScreenChat(); + static LLNearbyChat* getInstance(); + + void addToHost(); + + /** @param archive true - to save a message to the chat history log */ + void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); + void onNearbyChatContextMenuItemClicked(const LLSD& userdata); + bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); + + LLLineEditor* getChatBox() { return mChatBox; } + + //virtual void draw(); + + std::string getCurrentChat(); + + virtual BOOL handleKeyHere( KEY key, MASK mask ); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + static void startChat(const char* line); + static void stopChat(); + + static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); + static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); + + void showHistory(); + void showTranslationCheckbox(BOOL show); + +protected: + static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); + static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); + static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); + void onChatBoxFocusReceived(); + + void sendChat( EChatType type ); + void onChatBoxCommit(); + void onChatFontChange(LLFontGL* fontp); + + /* virtual */ bool applyRectControl(); + + void onToggleNearbyChatPanel(); + + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); + EChatType processChatTypeTriggers(EChatType type, std::string &str); + + void displaySpeakingIndicator(); + + void onCallButtonClicked(); + + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + + // Which non-zero channel did we last chat on? + static S32 sLastSpecialChatChannel; + + LLLineEditor* mChatBox; + LLOutputMonitorCtrl* mOutputMonitor; + LLLocalSpeakerMgr* mSpeakerMgr; + + S32 mExpandedHeight; + + /*virtual*/ BOOL tick(); + private: void getAllowedRect (LLRect& rect); @@ -68,14 +131,10 @@ private: void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); - -private: LLHandle mPopupMenuHandle; + std::vector mMessageArchive; LLChatHistory* mChatHistory; - std::vector mMessageArchive; }; #endif - - diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp deleted file mode 100644 index 68934be11a..0000000000 --- a/indra/newview/llnearbychatbar.cpp +++ /dev/null @@ -1,709 +0,0 @@ -/** - * @file llnearbychatbar.cpp - * @brief LLNearbyChatBar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "llappviewer.h" -#include "llfloaterreg.h" -#include "lltrans.h" -#include "llimfloatercontainer.h" -#include "llfirstuse.h" -#include "llnearbychatbar.h" -#include "llagent.h" -#include "llgesturemgr.h" -#include "llmultigesture.h" -#include "llkeyboard.h" -#include "llanimationstates.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" -#include "llviewercontrol.h" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "llnearbychat.h" -#include "lltranslate.h" - -#include "llresizehandle.h" - -S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 266; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { - std::string name; - EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { - { "/whisper" , CHAT_TYPE_WHISPER}, - { "/shout" , CHAT_TYPE_SHOUT} -}; - -LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -: LLIMConversation(key), - mChatBox(NULL), - mNearbyChat(NULL), - mOutputMonitor(NULL), - mSpeakerMgr(NULL), - mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ - mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); -} - -//virtual -BOOL LLNearbyChatBar::postBuild() -{ - mChatBox = getChild("chat_box"); - - mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); - mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); - mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); - mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this)); - - mChatBox->setIgnoreArrowKeys( FALSE ); - mChatBox->setCommitOnFocusLost( FALSE ); - mChatBox->setRevertOnEsc( FALSE ); - mChatBox->setIgnoreTab(TRUE); - mChatBox->setPassDelete(TRUE); - mChatBox->setReplaceNewlinesWithSpaces(FALSE); - mChatBox->setEnableLineHistory(TRUE); - mChatBox->setFont(LLViewerChat::getChatFont()); - - mNearbyChat = getChildView("nearby_chat"); - - LLUICtrl* show_btn = getChild("show_nearby_chat"); - show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); - - mOutputMonitor = getChild("chat_zone_indicator"); - mOutputMonitor->setVisible(FALSE); - - gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); - - mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility")); - - // Register for font change notifications - LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - - enableResizeCtrls(true, true, false); - - addToHost(); - - return LLIMConversation::postBuild();; -} - -void LLNearbyChatBar::enableDisableCallBtn() -{ - // bool btn_enabled = LLAgent::isActionAllowed("speak"); - - getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); -} - -void LLNearbyChatBar::addToHost() -{ - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - - if (im_box) - { - im_box->addFloater(this, FALSE, LLTabContainer::END); - } - } -} - -// virtual -void LLNearbyChatBar::onOpen(const LLSD& key) -{ - LLIMConversation::onOpen(key); - showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -bool LLNearbyChatBar::applyRectControl() -{ - bool rect_controlled = LLFloater::applyRectControl(); - - if (!mNearbyChat->getVisible()) - { - reshape(getRect().getWidth(), getMinHeight()); - enableResizeCtrls(true, true, false); - } - else - { - enableResizeCtrls(true); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - } - - return rect_controlled; -} - -void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp) -{ - // Update things with the new font whohoo - if (mChatBox) - { - mChatBox->setFont(fontp); - } -} - -//static -LLNearbyChatBar* LLNearbyChatBar::getInstance() -{ - return LLFloaterReg::getTypedInstance("chat_bar"); -} - -//static -//LLNearbyChatBar* LLNearbyChatBar::findInstance() -//{ -// return LLFloaterReg::findTypedInstance("chat_bar"); -//} - -void LLNearbyChatBar::showHistory() -{ - openFloater(); - - if (!getChildView("nearby_chat")->getVisible()) - { - onToggleNearbyChatPanel(); - } -} - -void LLNearbyChatBar::showTranslationCheckbox(BOOL show) -{ - getChild("translate_chat_checkbox_lp")->setVisible(show); -} - -void LLNearbyChatBar::draw() -{ - displaySpeakingIndicator(); - updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); - LLIMConversation::draw(); -} - -std::string LLNearbyChatBar::getCurrentChat() -{ - return mChatBox ? mChatBox->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - if( KEY_RETURN == key && mask == MASK_CONTROL) - { - // shout - sendChat(CHAT_TYPE_SHOUT); - handled = TRUE; - } - - return handled; -} - -BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ - U32 in_len = in_str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - bool string_was_found = false; - - for (S32 n = 0; n < cnt && !string_was_found; n++) - { - if (in_len <= sChatTypeTriggers[n].name.length()) - { - std::string trigger_trunc = sChatTypeTriggers[n].name; - LLStringUtil::truncate(trigger_trunc, in_len); - - if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) - { - *out_str = sChatTypeTriggers[n].name; - string_was_found = true; - } - } - } - - return string_was_found; -} - -void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ - LLFirstUse::otherAvatarChatFirst(false); - - LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - - LLWString raw_text = self->mChatBox->getWText(); - - // Can't trim the end, because that will cause autocompletion - // to eat trailing spaces that might be part of a gesture. - LLWStringUtil::trimHead(raw_text); - - S32 length = raw_text.length(); - - if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences - { - gAgent.startTyping(); - } - else - { - gAgent.stopTyping(); - } - - /* Doesn't work -- can't tell the difference between a backspace - that killed the selection vs. backspace at the end of line. - if (length > 1 - && text[0] == '/' - && key == KEY_BACKSPACE) - { - // the selection will already be deleted, but we need to trim - // off the character before - std::string new_text = raw_text.substr(0, length-1); - self->mInputEditor->setText( new_text ); - self->mInputEditor->setCursorToEnd(); - length = length - 1; - } - */ - - KEY key = gKeyboard->currentKey(); - - // Ignore "special" keys, like backspace, arrows, etc. - if (length > 1 - && raw_text[0] == '/' - && key < KEY_SPECIAL) - { - // we're starting a gesture, attempt to autocomplete - - std::string utf8_trigger = wstring_to_utf8str(raw_text); - std::string utf8_out_str(utf8_trigger); - - if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part - S32 outlength = self->mChatBox->getLength(); // in characters - - // Select to end of line, starting from the character - // after the last one the user typed. - self->mChatBox->setSelection(length, outlength); - } - else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part - self->mChatBox->setCursorToEnd(); - } - - //llinfos << "GESTUREDEBUG " << trigger - // << " len " << length - // << " outlen " << out_str.getLength() - // << llendl; - } -} - -// static -void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) -{ - // stop typing animation - gAgent.stopTyping(); -} - -void LLNearbyChatBar::onChatBoxFocusReceived() -{ - mChatBox->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) -{ - U32 length = str.length(); - S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); - - for (S32 n = 0; n < cnt; n++) - { - if (length >= sChatTypeTriggers[n].name.length()) - { - std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - - if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) - { - U32 trigger_length = sChatTypeTriggers[n].name.length(); - - // It's to remove space after trigger name - if (length > trigger_length && str[trigger_length] == ' ') - trigger_length++; - - str = str.substr(trigger_length, length); - - if (CHAT_TYPE_NORMAL == type) - return sChatTypeTriggers[n].type; - else - break; - } - } - } - - return type; -} - -void LLNearbyChatBar::sendChat( EChatType type ) -{ - if (mChatBox) - { - LLWString text = mChatBox->getConvertedText(); - if (!text.empty()) - { - // store sent line in history, duplicates will get filtered - mChatBox->updateHistory(); - // Check if this is destined for another channel - S32 channel = 0; - stripChannelNumber(text, &channel); - - std::string utf8text = wstring_to_utf8str(text); - // Try to trigger a gesture, if not chat to a script. - std::string utf8_revised_text; - if (0 == channel) - { - // discard returned "found" boolean - LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); - } - else - { - utf8_revised_text = utf8text; - } - - utf8_revised_text = utf8str_trim(utf8_revised_text); - - type = processChatTypeTriggers(type, utf8_revised_text); - - if (!utf8_revised_text.empty()) - { - // Chat with animation - sendChatFromViewer(utf8_revised_text, type, TRUE); - } - } - - mChatBox->setText(LLStringExplicit("")); - } - - gAgent.stopTyping(); - - // If the user wants to stop chatting on hitting return, lose focus - // and go out of chat mode. - if (gSavedSettings.getBOOL("CloseChatOnReturn")) - { - stopChat(); - } -} - - -void LLNearbyChatBar::onToggleNearbyChatPanel() -{ - LLView* nearby_chat = getChildView("nearby_chat"); - - if (nearby_chat->getVisible()) - { - if (!isMinimized()) - { - mExpandedHeight = getRect().getHeight(); - } - setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); - nearby_chat->setVisible(FALSE); - reshape(getRect().getWidth(), COLLAPSED_HEIGHT); - enableResizeCtrls(true, true, false); - storeRectControl(); - } - else - { - nearby_chat->setVisible(TRUE); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - reshape(getRect().getWidth(), mExpandedHeight); - enableResizeCtrls(true); - storeRectControl(); - } - - gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::reloadMessages() -{ - LLNearbyChat::getInstance()->reloadMessages(); -} - -void LLNearbyChatBar::setMinimized(BOOL b) -{ - LLNearbyChat* nearby_chat = getChild("nearby_chat"); - // when unminimizing with nearby chat visible, go ahead and kill off screen chats - if (!b && nearby_chat->getVisible()) - { - nearby_chat->removeScreenChat(); - } - LLFloater::setMinimized(b); -} - -void LLNearbyChatBar::onChatBoxCommit() -{ - if (mChatBox->getText().length() > 0) - { - sendChat(CHAT_TYPE_NORMAL); - } - - gAgent.stopTyping(); -} - -void LLNearbyChatBar::displaySpeakingIndicator() -{ - LLSpeakerMgr::speaker_list_t speaker_list; - LLUUID id; - - id.setNull(); - mSpeakerMgr->update(TRUE); - mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - id = s->mID; - break; - } - } - - if (!id.isNull()) - { - mOutputMonitor->setVisible(TRUE); - mOutputMonitor->setSpeakerId(id); - } - else - { - mOutputMonitor->setVisible(FALSE); - } -} - -void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ - sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) -{ - // Look for "/20 foo" channel chats. - S32 channel = 0; - LLWString out_text = stripChannelNumber(wtext, &channel); - std::string utf8_out_text = wstring_to_utf8str(out_text); - std::string utf8_text = wstring_to_utf8str(wtext); - - utf8_text = utf8str_trim(utf8_text); - if (!utf8_text.empty()) - { - utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); - } - - // Don't animate for chats people can't hear (chat to scripts) - if (animate && (channel == 0)) - { - if (type == CHAT_TYPE_WHISPER) - { - lldebugs << "You whisper " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); - } - else if (type == CHAT_TYPE_NORMAL) - { - lldebugs << "You say " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); - } - else if (type == CHAT_TYPE_SHOUT) - { - lldebugs << "You shout " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); - } - else - { - llinfos << "send_chat_from_viewer() - invalid volume" << llendl; - return; - } - } - else - { - if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) - { - lldebugs << "Channel chat: " << utf8_text << llendl; - } - } - - send_chat_from_viewer(utf8_out_text, type, channel); -} - -// static -void LLNearbyChatBar::startChat(const char* line) -{ - LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - - if (cb ) - { - cb->setVisible(TRUE); - cb->setFocus(TRUE); - cb->mChatBox->setFocus(TRUE); - - if (line) - { - std::string line_string(line); - cb->mChatBox->setText(line_string); - } - - cb->mChatBox->setCursorToEnd(); - } -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLNearbyChatBar::stopChat() -{ - LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - - if (cb) - { - cb->mChatBox->setFocus(FALSE); - - // stop typing animation - gAgent.stopTyping(); - } -} - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) -{ - if (mesg[0] == '/' - && mesg[1] == '/') - { - // This is a "repeat channel send" - *channel = sLastSpecialChatChannel; - return mesg.substr(2, mesg.length() - 2); - } - else if (mesg[0] == '/' - && mesg[1] - && LLStringOps::isDigit(mesg[1])) - { - // This a special "/20" speak on a channel - S32 pos = 0; - - // Copy the channel number into a string - LLWString channel_string; - llwchar c; - do - { - c = mesg[pos+1]; - channel_string.push_back(c); - pos++; - } - while(c && pos < 64 && LLStringOps::isDigit(c)); - - // Move the pointer forward to the first non-whitespace char - // Check isspace before looping, so we can handle "/33foo" - // as well as "/33 foo" - while(c && iswspace(c)) - { - c = mesg[pos+1]; - pos++; - } - - sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); - *channel = sLastSpecialChatChannel; - return mesg.substr(pos, mesg.length() - pos); - } - else - { - // This is normal chat. - *channel = 0; - return mesg; - } -} - -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ChatFromViewer); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ChatData); - msg->addStringFast(_PREHASH_Message, utf8_out_text); - msg->addU8Fast(_PREHASH_Type, type); - msg->addS32("Channel", channel); - - gAgent.sendReliableMessage(); - - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} - -class LLChatCommandHandler : public LLCommandHandler -{ -public: - // not allowed from outside the app - LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - - // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) - { - bool retval = false; - // Need at least 2 tokens to have a valid message. - if (tokens.size() < 2) - { - retval = false; - } - else - { - S32 channel = tokens[0].asInteger(); - // VWR-19499 Restrict function to chat channels greater than 0. - if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) - { - retval = true; - // Send unescaped message, see EXT-6353. - std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); - send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); - } - else - { - retval = false; - // Tell us this is an unsupported SLurl. - } - } - return retval; - } -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; - - diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h deleted file mode 100644 index b7c4c993c6..0000000000 --- a/indra/newview/llnearbychatbar.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file llnearbychatbar.h - * @brief LLNearbyChatBar class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHATBAR_H -#define LL_LLNEARBYCHATBAR_H - -#include "llimconversation.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llnearbychat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" - -class LLNearbyChatBar : public LLIMConversation -{ -public: - // constructor for inline chat-bars (e.g. hosted in chat history window) - LLNearbyChatBar(const LLSD& key); - ~LLNearbyChatBar() {} - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - - static LLNearbyChatBar* getInstance(); -// static LLNearbyChatBar* findInstance(); - - void addToHost(); - - void reloadMessages(); - LLLineEditor* getChatBox() { return mChatBox; } - - virtual void draw(); - - std::string getCurrentChat(); - virtual BOOL handleKeyHere( KEY key, MASK mask ); - - static void startChat(const char* line); - static void stopChat(); - - static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); - static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); - - void showHistory(); - void showTranslationCheckbox(BOOL show); - /*virtual*/void setMinimized(BOOL b); - -protected: - static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); - static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); - static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); - void onChatBoxFocusReceived(); - - void sendChat( EChatType type ); - void onChatBoxCommit(); - void onChatFontChange(LLFontGL* fontp); - - /* virtual */ bool applyRectControl(); - - void onToggleNearbyChatPanel(); - - static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); - EChatType processChatTypeTriggers(EChatType type, std::string &str); - - void displaySpeakingIndicator(); - - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - - // Which non-zero channel did we last chat on? - static S32 sLastSpecialChatChannel; - - LLLineEditor* mChatBox; - LLView* mNearbyChat; - LLOutputMonitorCtrl* mOutputMonitor; - LLLocalSpeakerMgr* mSpeakerMgr; - - S32 mExpandedHeight; -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp index a63e1fb76e..61815d1864 100644 --- a/indra/newview/llnearbychatbarlistener.cpp +++ b/indra/newview/llnearbychatbarlistener.cpp @@ -29,14 +29,14 @@ #include "llviewerprecompiledheaders.h" #include "llnearbychatbarlistener.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagent.h" #include "llchat.h" -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar) +LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar) : LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc."), mChatbar(chatbar) diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h index 9af9bc1f7b..0537275424 100644 --- a/indra/newview/llnearbychatbarlistener.h +++ b/indra/newview/llnearbychatbarlistener.h @@ -33,17 +33,17 @@ #include "lleventapi.h" class LLSD; -class LLNearbyChatBar; +class LLNearbyChat; class LLNearbyChatBarListener : public LLEventAPI { public: - LLNearbyChatBarListener(LLNearbyChatBar & chatbar); + LLNearbyChatBarListener(LLNearbyChat & chatbar); private: void sendChat(LLSD const & chat_data) const; - LLNearbyChatBar & mChatbar; + LLNearbyChat & mChatbar; }; #endif // LL_LLNEARBYCHATBARLISTENER_H diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index f26cc85019..e91a3fc334 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -40,7 +40,7 @@ #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance #include "llviewerwindow.h"//for screen channel position -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llrootview.h" #include "lllayoutstack.h" @@ -487,9 +487,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages - LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - - LLNearbyChat* nearby_chat = chat_bar->findChild("nearby_chat"); + LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); // Build notification data LLSD chat; @@ -558,8 +556,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, sChatWatcher->post(chat); - if( !chat_bar->isMinimized() - && nearby_chat->isInVisibleChain() + if( nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a1d5db2e27..507c6686fd 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -29,7 +29,7 @@ #include "llfloaterreg.h" #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llnotificationhandler.h" #include "llnotifications.h" #include "lltoastnotifypanel.h" @@ -86,8 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); - if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) + if (!nearby_chat->isMinimized() && nearby_chat->getVisible()) { return false; } diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index bc4097cd93..389baa86cd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -41,85 +41,4 @@ #include "llspeakers.h" #include "lltrans.h" -LLPanelChatControlPanel::~LLPanelChatControlPanel() -{ -} -BOOL LLPanelChatControlPanel::postBuild() -{ - return TRUE; -} - -void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) -{ - //Method is called twice for AdHoc and Group chat. Second time when server init reply received - mSessionId = session_id; -} - - -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): -mParticipantList(NULL) -{ -} - -BOOL LLPanelGroupControlPanel::postBuild() -{ - - return LLPanelChatControlPanel::postBuild(); -} - -LLPanelGroupControlPanel::~LLPanelGroupControlPanel() -{ - delete mParticipantList; - mParticipantList = NULL; -} - -// virtual -void LLPanelGroupControlPanel::draw() -{ - // Need to resort the participant list if it's in sort by recent speaker order. - if (mParticipantList) - mParticipantList->update(); - LLPanelChatControlPanel::draw(); -} - - -void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) -{ - // TODO: Check this code when when sort order menu will be added. (EM) - if (false && !mParticipantList) - return; - - std::string chosen_item = userdata.asString(); - - if (chosen_item == "sort_name") - { - mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); - } - -} - -void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) -{ - LLPanelChatControlPanel::setSessionId(session_id); - - mGroupID = session_id; - - // for group and Ad-hoc chat we need to include agent into list - if(!mParticipantList) - { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); - mParticipantList = new LLParticipantList(speaker_manager, getChild("speakers_list"), true, false); - } -} - - -LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id) -{ -} - -BOOL LLPanelAdHocControlPanel::postBuild() -{ - //We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat - return LLPanelChatControlPanel::postBuild(); -} diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5ced32a9ab..df1962f5fe 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -134,7 +134,6 @@ #include "llscriptfloater.h" #include "llfloatermodelpreview.h" #include "llcommandhandler.h" -#include "llnearbychatbar.h" // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -187,8 +186,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -211,6 +208,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a32a78cbf9..c7d37e102e 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -40,7 +40,7 @@ #include "llviewermessage.h" // send_guid_sound_trigger #include "llviewernetwork.h" #include "llagent.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" // Globals LLViewerGestureList gGestureList; @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..385d3cd29a 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -31,7 +31,7 @@ #include "llmath.h" #include "llagent.h" #include "llagentcamera.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llviewercontrol.h" #include "llfocusmgr.h" #include "llmorphview.h" @@ -534,7 +534,7 @@ void stop_moving( EKeystate s ) void start_chat( EKeystate s ) { // start chat - LLNearbyChatBar::startChat(NULL); + LLNearbyChat::startChat(NULL); } void start_gesture( EKeystate s ) @@ -543,15 +543,15 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) + if (LLNearbyChat::getInstance()->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' - LLNearbyChatBar::startChat("/"); + LLNearbyChat::startChat("/"); } else { // Don't overwrite existing text in chat editor - LLNearbyChatBar::startChat(NULL); + LLNearbyChat::startChat(NULL); } } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 32f693b009..5b8cf52298 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -185,7 +185,7 @@ #include "llviewerjoystick.h" #include "llviewernetwork.h" #include "llpostprocess.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h" #include "llagentui.h" #include "llwearablelist.h" @@ -2482,7 +2482,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // Traverses up the hierarchy if( keyboard_focus ) { - LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance("chat_bar"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("chat_bar"); if (nearby_chat) { @@ -2549,11 +2549,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance("chat_bar")->getChatBox(); + LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance("chat_bar")->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. - LLNearbyChatBar::getInstance()->startChat(NULL); + LLNearbyChat::getInstance()->startChat(NULL); return TRUE; } } diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml deleted file mode 100644 index 7688525e13..0000000000 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - VoicePTT_Off - VoicePTT_On - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index a332bb5b12..c5cacab9f4 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -138,18 +138,24 @@ top_pad="0" left="0"> - - + + - - - - + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml deleted file mode 100644 index d68fa6ca6c..0000000000 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - + width="31"/> + width="31"/> - - + top="31" + right="-1"/> diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml new file mode 100644 index 0000000000..a63a14ca69 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -0,0 +1,62 @@ + + + + + + + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index ceb03d03a9..38a996547c 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -611,6 +611,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M filename="panel_block_list_sidetray.xml" follows="all" label="Blocked Residents & Objects" + layout="topleft" left="0" font="SansSerifBold" top="0" -- cgit v1.2.3 From afc6a7e6baeb9b568feb31cfd8eb978bb485c0c6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 22 Jun 2012 20:05:35 +0300 Subject: CHUI-136 ADDITIONAL FIX (Implement new design for blocked list on the people floater) - If mute item type is LLMute::BY_NAME it means that it's an object and we should show corresponding icon - Also added icon for blocked groups --- indra/newview/llblockedlistitem.cpp | 11 ++++++++++- .../newview/skins/default/xui/en/panel_blocked_list_item.xml | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/indra/newview/llblockedlistitem.cpp b/indra/newview/llblockedlistitem.cpp index 14da35c85a..d9afd2b629 100644 --- a/indra/newview/llblockedlistitem.cpp +++ b/indra/newview/llblockedlistitem.cpp @@ -38,6 +38,7 @@ // newview #include "llavatariconctrl.h" +#include "llgroupiconctrl.h" #include "llinventoryicon.h" #include "llviewerobject.h" @@ -58,14 +59,22 @@ BOOL LLBlockedListItem::postBuild() switch (mMuteType) { case LLMute::AGENT: + case LLMute::EXTERNAL: { LLAvatarIconCtrl* avatar_icon = getChild("avatar_icon"); avatar_icon->setVisible(TRUE); avatar_icon->setValue(mItemID); } break; - + case LLMute::GROUP: + { + LLGroupIconCtrl* group_icon = getChild("group_icon"); + group_icon->setVisible(TRUE); + group_icon->setValue(mItemID); + } + break; case LLMute::OBJECT: + case LLMute::BY_NAME: getChild("object_icon")->setVisible(TRUE); break; diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml index a63a14ca69..84e7e467b1 100644 --- a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -37,6 +37,16 @@ top="2" visible="false" width="20" /> + Date: Fri, 22 Jun 2012 19:28:11 +0100 Subject: CHUI-136 : Fix compilation issue showing up when warning treated as errors --- indra/newview/llblocklist.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index 521add4bdc..cb68f677eb 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -24,8 +24,11 @@ * $/LicenseInfo$ */ -#include "llavataractions.h" +#include "llviewerprecompiledheaders.h" + #include "llblocklist.h" + +#include "llavataractions.h" #include "llblockedlistitem.h" #include "llfloatersidepanelcontainer.h" #include "llviewermenu.h" -- cgit v1.2.3 From cf60f6a1910e8fa82011d6f13aa1bd9c6767fffb Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 22 Jun 2012 17:08:49 -0400 Subject: SH-3172 WIP - debug setting for settings.xml --- indra/newview/app_settings/settings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1911943842..53c7ceaa80 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12302,6 +12302,17 @@ Value 1 + UseServerTextureBaking + + Comment + Update appearance via the ServerTextureBaking cap, if available + Persist + 1 + Type + Boolean + Value + 1 + RenderDelayVBUpdate Comment -- cgit v1.2.3 From 74092930afdc294ef4d204830173d4750a310616 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 22 Jun 2012 14:13:20 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose build fix for gcc added detection of duplicate widget registration --- indra/llui/lluictrlfactory.cpp | 15 ++++++++------- indra/llui/lluictrlfactory.h | 4 ++-- indra/llxuixml/llregistry.h | 4 ++++ indra/newview/llfolderviewmodel.h | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 25e7a31e90..f64f33bc5e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -278,13 +278,13 @@ const LLInitParam::BaseBlock& get_empty_param_block() // adds a widget and its param block to various registries //static -void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag) +void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name) { // associate parameter block type with template .xml file - std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type); - if (existing_tag != NULL) + std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type); + if (existing_name != NULL) { - if(*existing_tag != tag) + if(*existing_name != name) { std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl; // forcing crash here @@ -293,18 +293,19 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st } else { - // widget already registered + // widget already registered this name return; } } - LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag); + + LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, name); //FIXME: comment this in when working on schema generation //LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type); //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block); } //static -const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type) +const std::string* LLUICtrlFactory::getWidgetName(const std::type_info* widget_type) { return LLWidgetNameRegistry::instance().getValue(widget_type); } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d612ad5005..b441cb0c9d 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -105,7 +105,7 @@ private: ParamDefaults() { // look up template file for this param block... - const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK)); + const std::string* param_block_tag = getWidgetName(&typeid(PARAM_BLOCK)); if (param_block_tag) { // ...and if it exists, back fill values using the most specific template first PARAM_BLOCK params; @@ -303,7 +303,7 @@ private: } - static const std::string* getWidgetTag(const std::type_info* widget_type); + static const std::string* getWidgetName(const std::type_info* widget_type); // this exists to get around dependency on llview static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h index 36ce6a97b7..3e8d9267cc 100644 --- a/indra/llxuixml/llregistry.h +++ b/indra/llxuixml/llregistry.h @@ -302,6 +302,10 @@ public: virtual ~StaticRegistrar() {} StaticRegistrar(ref_const_key_t key, ref_const_value_t value) { + if (singleton_t::instance().exists(key)) + { + llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl; + } singleton_t::instance().mStaticScope->add(key, value); } }; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index c3dcfed97c..74c8bb92ef 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -218,7 +218,7 @@ public: virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; protected: - friend LLFolderViewItem; + friend class LLFolderViewItem; void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} LLFolderViewItem* mFolderViewItem; -- cgit v1.2.3 From 9fc77dec8788944f93eda14567f9235f97637097 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Mon, 25 Jun 2012 15:49:49 +0300 Subject: CHUI-175 FIXED (Cannot use scroll bar on chat entry field when multi line chat is added) - This change also fixes: CHUI-176 (Only bottom 2 lines of multi line chat allow for selecting in text chat entry) CHUI-177 (Text entry field in chat only accepts 256 characters) --- .../skins/default/xui/en/floater_im_session.xml | 39 +++++++++------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 0720a4b011..56e591e2bb 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -235,29 +235,22 @@ - - - - + + -- cgit v1.2.3 From c3488d1fc64fb3f2bc5ad3a5a0fd5722eb574a4c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 25 Jun 2012 13:50:39 -0400 Subject: SH-3172 WIP - useServerTextureBaking() func --- indra/newview/llappearancemgr.cpp | 9 +++++++-- indra/newview/llappearancemgr.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) mode change 100644 => 100755 indra/newview/llappearancemgr.h diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index faadfb4b87..5d2ff1b40f 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2581,8 +2581,13 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (inventory_changed) gInventory.notifyObservers(); } - - +// Should be true iff both the appropriate debug setting is enabled +// and the corresponding cap has been found. +bool useServerTextureBaking() +{ + // TODO: add cap check. + return gSavedSettings.getBOOL("UseServerTextureBaking"); +} class LLShowCreatedOutfit: public LLInventoryCallback { diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h old mode 100644 new mode 100755 index c1d561781d..4423486b95 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -182,6 +182,8 @@ public: bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; } + bool useServerTextureBaking(); + protected: LLAppearanceMgr(); ~LLAppearanceMgr(); -- cgit v1.2.3 From 9353a9e6ef071bd980c319d038b1dedb649d2db0 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 25 Jun 2012 23:55:25 +0300 Subject: CHUI-167 FIXED Move onClose() from LLIMFloater to it's basic class (LLIMConversation) for correct using add/remove conversation list items also for LLNearbyChat --- indra/newview/llimconversation.cpp | 14 +++++++ indra/newview/llimconversation.h | 1 + indra/newview/llimfloater.cpp | 84 ++++++++++++++++++-------------------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index cbebf3edd3..f304997abf 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -339,6 +339,20 @@ void LLIMConversation::onOpen(const LLSD& key) updateHeaderAndToolbar(); } +// virtual +void LLIMConversation::onClose(bool app_quitting) +{ + // Always suppress the IM from the conversations list on close if present for any reason + if (LLIMConversation::isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); + if (im_box) + { + im_box->removeConversationListItem(mSessionID); + } + } +} + void LLIMConversation::onTearOffClicked() { onClickTearOff(this); diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index f4b8a38242..47c98d6f8b 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -63,6 +63,7 @@ public: // LLFloater overrides /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); protected: diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 98ebc82f99..37ee7b8a7c 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -105,51 +105,6 @@ void LLIMFloater::onFocusReceived() } } -// virtual -void LLIMFloater::onClose(bool app_quitting) -{ - // Always suppress the IM from the conversations list on close if present for any reason - if (LLIMConversation::isChatMultiTab()) - { - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (im_box) - { - im_box->removeConversationListItem(mSessionID); - } - } - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); - - if (session == NULL) - { - llwarns << "Empty session." << llendl; - return; - } - - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - - setTyping(false); - - // The source of much argument and design thrashing - // Should the window hide or the session close when the X is clicked? - // - // Last change: - // EXT-3516 X Button should end IM session, _ button should hide - gIMMgr->leaveSession(mSessionID); -} /* static */ void LLIMFloater::newIMCallback(const LLSD& data) @@ -611,6 +566,45 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) return conversation; } +void LLIMFloater::onClose(bool app_quitting) +{ + LLIMConversation::onClose(app_quitting); + + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + mSessionID); + + if (session == NULL) + { + llwarns << "Empty session." << llendl; + return; + } + + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + + setTyping(false); + + // The source of much argument and design thrashing + // Should the window hide or the session close when the X is clicked? + // + // Last change: + // EXT-3516 X Button should end IM session, _ button should hide + gIMMgr->leaveSession(mSessionID); + +} + void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state -- cgit v1.2.3 From 7f3b27289da2478381dcb4d7e9f05e082e37eaa2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 25 Jun 2012 21:59:13 +0300 Subject: CHUI-168 FIXED Added call of updateHeaderAndToolbar from postBuild for correct floater's title and standard buttons showing at start --- indra/newview/llimconversation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index f304997abf..d3f3e41a29 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -103,6 +103,7 @@ BOOL LLIMConversation::postBuild() } buildParticipantList(); + updateHeaderAndToolbar(); if (isChatMultiTab()) { -- cgit v1.2.3 From 5b6db72c5b7c5c3c4cfde671480ec1fc56bbd859 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 25 Jun 2012 13:04:09 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose all inventory names are correctly initialized now --- indra/newview/llinventorybridge.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c0670b71d4..70a174a140 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1844,14 +1844,17 @@ void LLFolderBridge::buildDisplayName() const //"Accessories" inventory category has folder type FT_NONE. So, this folder //can not be detected as protected with LLFolderType::lookupIsProtectedType + mDisplayName.assign(getName()); if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) { LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); } - else - { - mDisplayName.assign(getName()); - } + + //if (mDisplayName.empty()) + //{ + // S32 foo; + // foo = 0; + //} } -- cgit v1.2.3 From 41e965c12e29136d2b81a9b67d6b6c9af4fb2092 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 25 Jun 2012 15:20:52 -0700 Subject: CHUI-139 : Hide torn off floaters when hiding conversation list; make nearby chat always present; leave conversation list around when all torn off --- indra/llui/llmultifloater.h | 4 +-- indra/newview/llimconversation.cpp | 6 +++- indra/newview/llimfloatercontainer.cpp | 51 ++++++++++++++++++++++++++++++++-- indra/newview/llimfloatercontainer.h | 6 ++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index f299ae5dd3..44514a6246 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -45,8 +45,8 @@ public: virtual BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); + virtual void draw(); + virtual void setVisible(BOOL visible); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index bbbc9fcffd..cbebf3edd3 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -106,6 +106,10 @@ BOOL LLIMConversation::postBuild() if (isChatMultiTab()) { + if (mIsNearbyChat) + { + setCanClose(FALSE); + } return LLFloater::postBuild(); } else @@ -246,7 +250,7 @@ void LLIMConversation::updateHeaderAndToolbar() mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); - mCloseBtn->setVisible(is_hosted); + mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); enableDisableCallBtn(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index a2a54bf02c..33b96b20f3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -103,14 +103,14 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { - LLMultiFloater::onOpen(key); if (getFloaterCount() == 0) { - // If there's *no* conversation open so far, we force the opening of the nearby chat conversation + // We always force the opening of the nearby chat conversation when we open for the first time // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("chat_bar"); LLFloaterReg::toggleInstanceOrBringToFront(name); } + LLMultiFloater::onOpen(key); /* if (key.isDefined()) { @@ -284,6 +284,44 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +void LLIMFloaterContainer::draw() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } + LLFloater::draw(); +} + +void LLIMFloaterContainer::tabClose() +{ + if (mTabContainer->getTabCount() == 0) + { + // Do not close the container when every conversation is torn off because the user + // still needs the conversation list. Simply collapse the message pane in that case. + collapseMessagesPane(true); + } +} + +void LLIMFloaterContainer::setVisible(BOOL visible) +{ + // We need to show/hide all the associated conversations that have been torn off + // (and therefore, are not longer managed by the multifloater), + // so that they show/hide with the conversations manager. + conversations_items_map::iterator item_it = mConversationsItems.begin(); + for (;item_it != mConversationsItems.end(); ++item_it) + { + LLConversationItem* item = item_it->second; + item->setVisibleIfDetached(visible); + } + + // Now, do the normal multifloater show/hide + LLMultiFloater::setVisible(visible); + +} + void LLIMFloaterContainer::collapseMessagesPane(bool collapse) { if (mMessagesPane->isCollapsed() == collapse) @@ -485,6 +523,15 @@ void LLConversationItem::selectItem(void) mFloater->setFocus(TRUE); } +void LLConversationItem::setVisibleIfDetached(BOOL visible) +{ + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) + if (!mFloater->getHost()) + { + mFloater->setVisible(visible); + } +} + void LLConversationItem::performAction(LLInventoryModel* model, std::string action) { } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 3d1324c2fb..c6e7c6a3d9 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -97,6 +97,8 @@ public: virtual void previewItem( void ); virtual void selectItem(void); virtual void showProperties(void); + + void setVisibleIfDetached(BOOL visible); // This method should be called when a drag begins. // Returns TRUE if the drag can begin, FALSE otherwise. @@ -128,6 +130,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void draw(); + /*virtual*/ void setVisible(BOOL visible); void onCloseFloater(LLUUID& id); /*virtual*/ void addFloater(LLFloater* floaterp, @@ -135,6 +139,8 @@ public: LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); /*virtual*/ void removeFloater(LLFloater* floaterp); + /*virtual*/ void tabClose(); + static LLFloater* getCurrentVoiceFloater(); static LLIMFloaterContainer* findInstance(); -- cgit v1.2.3 From 9c11a6b206f2455e37cf3ba8719bf6b51bc994e8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Tue, 26 Jun 2012 18:58:57 +0300 Subject: CHUI-177 ADDITIONAL FIX (Text entry field in chat only accepts 256 characters) - Limited text entry field to 1024 instead of 1025 characters should take into account zero (0 ... 1023) --- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 56e591e2bb..08bc46a506 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -246,7 +246,7 @@ label="To" layout="bottomleft" name="chat_editor" - max_length="1024" + max_length="1023" tab_group="3" width="240" wrap="true"> -- cgit v1.2.3 From 677c205131e695eb5a3b2a190799330b49d636d8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Tue, 26 Jun 2012 19:08:27 +0300 Subject: CHUI-182 FIXED (Vertical scrollbar flashes on and off when chat entry text area expands) - To avoid unnecessary appearing of scrollbar, first chat entry must be expanded and only then decision should be taken in the base class whether scrollbar should be shown or not. --- indra/llui/llchatentry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index a6ba125406..2a6ccc3dc9 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -57,12 +57,12 @@ LLChatEntry::~LLChatEntry() void LLChatEntry::draw() { - LLTextEditor::draw(); - if(mIsExpandable) { expandText(); } + + LLTextEditor::draw(); } void LLChatEntry::onCommit() -- cgit v1.2.3 From abe106bd9c33fef12dcf4eacca228d5d669d9e34 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Tue, 26 Jun 2012 19:27:19 +0300 Subject: - CHUI-178 (Right click context menu not present in chat entry field) - Set parameter to true to show context menu --- indra/newview/skins/default/xui/en/widgets/chat_editor.xml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 indra/newview/skins/default/xui/en/widgets/chat_editor.xml diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml new file mode 100644 index 0000000000..f9facb593a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml @@ -0,0 +1,4 @@ + + -- cgit v1.2.3 From c233f0c9494d7dddbd8baab0f87b0ad54f42b0f9 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 26 Jun 2012 17:05:16 -0700 Subject: CHUI-164 : Fix crash when closing ad-hoc conversations; insure consistency of the conversation list when adding and removing items from it --- indra/newview/llimfloater.cpp | 9 ++++-- indra/newview/llimfloatercontainer.cpp | 56 +++++++++++++++++++++++++++------- indra/newview/llimfloatercontainer.h | 8 +++-- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 98ebc82f99..f89bafc7ea 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -540,8 +540,10 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } + // Test the existence of the floater before we try to create it bool exist = findInstance(session_id); + // Get the floater: this will create the instance if it didn't exist LLIMFloater* floater = getInstance(session_id); if (!floater) return NULL; @@ -550,18 +552,21 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - // do not add existed floaters to avoid adding torn off instances + // Do not add again existing floaters if (!exist) { // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - if (floater_container) { floater_container->addFloater(floater, TRUE, i_pt); } } + + // Add a conversation list item in the left pane: nothing will be done if already in there + // but relevant clean up will be done to ensure consistency of the conversation list + floater_container->addConversationListItem(floater->getTitle(), session_id, floater); floater->openFloater(floater->getKey()); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 33b96b20f3..f6bcf8bbe9 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -146,7 +146,7 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLUUID session_id = floaterp->getKey(); // Add a conversation list item in the left pane - addConversationListItem(floaterp->getTitle(), session_id, floaterp, this); + addConversationListItem(floaterp->getTitle(), session_id, floaterp); LLView* floater_contents = floaterp->getChild("contents_view"); @@ -408,18 +408,33 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } // CHUI-137 : Temporary implementation of conversations list -void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) +void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { - // Check if the item is not already in the list, exit if it is (nothing to do) + // Check if the item is not already in the list, exit if it is and has the same name and points to the same floater (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance conversations_items_map::iterator item_it = mConversationsItems.find(uuid); if (item_it != mConversationsItems.end()) { - return; + LLConversationItem* item = item_it->second; + // Check if the item has changed + if (item->hasSameValues(name,floaterp)) + { + // If it hasn't, nothing to do -> exit + return; + } + // If it has, remove it: it'll be recreated anew further down + removeConversationListItem(uuid,false); + } + + // Reverse find and clean up: we need to make sure that no other uuid is pointing to that same floater + LLUUID found_id = LLUUID::null; + if (findConversationItem(floaterp,found_id)) + { + removeConversationListItem(found_id,false); } // Create a conversation item - LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, containerp); + LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); mConversationsItems[uuid] = item; // Create a widget from it @@ -439,7 +454,7 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, bool change_focus) { // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting @@ -469,16 +484,35 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id) } // Don't let the focus fall IW, select and refocus on the first conversation in the list - setFocus(TRUE); - conversations_items_map::iterator item_it = mConversationsItems.begin(); - if (item_it != mConversationsItems.end()) + if (change_focus) { - LLConversationItem* item = item_it->second; - item->selectItem(); + setFocus(TRUE); + conversations_items_map::iterator item_it = mConversationsItems.begin(); + if (item_it != mConversationsItems.end()) + { + LLConversationItem* item = item_it->second; + item->selectItem(); + } } return; } +bool LLIMFloaterContainer::findConversationItem(LLFloater* floaterp, LLUUID& uuid) +{ + bool found = false; + for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) + { + LLConversationItem* item = item_it->second; + uuid = item_it->first; + if (item->hasSameValue(floaterp)) + { + found = true; + break; + } + } + return found; +} + LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLFolderViewItem::Params params; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index c6e7c6a3d9..2a8cbf3e1c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -112,6 +112,9 @@ public: EDragAndDropType cargo_type, void* cargo_data, std::string& tooltip_msg) { return FALSE; } + + bool hasSameValues(std::string name, LLFloater* floaterp) { return ((name == mName) && (floaterp == mFloater)); } + bool hasSameValue(LLFloater* floaterp) { return (floaterp == mFloater); } private: std::string mName; const LLUUID mUUID; @@ -183,9 +186,10 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id); + void removeConversationListItem(const LLUUID& session_id, bool change_focus = true); + void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); + bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); private: - void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) -- cgit v1.2.3 From a7831406abfe87e9bd1da8091e008edcd65b402c Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Wed, 27 Jun 2012 18:52:08 +0300 Subject: CHUI-180 FIXED (Started an ad hoc IM spams log with drawtext warning) - Don't draw TextBase context if it's empty and in focus --- indra/llui/lltextbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index c112a7e477..3b3bc64c5b 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -508,7 +508,7 @@ void LLTextBase::drawText() { return; } - else if (text_len <= 0 && !mLabel.empty()) + else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) { text_len = mLabel.length(); } -- cgit v1.2.3 From 0cfea7b406c87bf593d2f7cf6040d92ef99b64cf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 26 Jun 2012 01:38:59 +0300 Subject: CHUI-147 FIX Added updating conference participants in IM floater title - The title is updated with the data from participants list widget in IM floater. - Creating the participants list is fixed for the case of starting the ad hoc session when the session id changes upon initialization (see LLIMConversation::buildParticipantList()). - LLEventTimer replaced with simple LLTimer to avoid crashes in LLEventTimer::tick(). - Moved the build_residents_string() code to LLAvatarActions::buildResidentsString() to use it in LLIMFloater::onParticipantsListChanged(). --- indra/newview/llavataractions.cpp | 35 +++++++------- indra/newview/llavataractions.h | 9 ++++ indra/newview/llimconversation.cpp | 34 +++++++++----- indra/newview/llimconversation.h | 10 ++-- indra/newview/llimfloater.cpp | 93 ++++++++++++++++++++++++++++--------- indra/newview/llimfloater.h | 9 +++- indra/newview/llnearbychat.cpp | 36 ++++++-------- indra/newview/llnearbychat.h | 6 +-- indra/newview/llparticipantlist.cpp | 1 + 9 files changed, 151 insertions(+), 82 deletions(-) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c9031dd26a..21367c224d 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -529,23 +529,6 @@ namespace action_give_inventory return acceptable; } - static void build_residents_string(const std::vector avatar_names, std::string& residents_string) - { - llassert(avatar_names.size() > 0); - - const std::string& separator = LLTrans::getString("words_separator"); - for (std::vector::const_iterator it = avatar_names.begin(); ; ) - { - LLAvatarName av_name = *it; - residents_string.append(av_name.mDisplayName); - if (++it == avatar_names.end()) - { - break; - } - residents_string.append(separator); - } - } - static void build_items_string(const std::set& inventory_selected_uuids , std::string& items_string) { llassert(inventory_selected_uuids.size() > 0); @@ -675,7 +658,7 @@ namespace action_give_inventory } std::string residents; - build_residents_string(avatar_names, residents); + LLAvatarActions::buildResidentsString(avatar_names, residents); std::string items; build_items_string(inventory_selected_uuids, items); @@ -706,7 +689,23 @@ namespace action_give_inventory } } +// static +void LLAvatarActions::buildResidentsString(const std::vector avatar_names, std::string& residents_string) +{ + llassert(avatar_names.size() > 0); + const std::string& separator = LLTrans::getString("words_separator"); + for (std::vector::const_iterator it = avatar_names.begin(); ; ) + { + LLAvatarName av_name = *it; + residents_string.append(av_name.mDisplayName); + if (++it == avatar_names.end()) + { + break; + } + residents_string.append(separator); + } +} //static std::set LLAvatarActions::getInventorySelectedUUIDs() diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 0a69ad86a3..46830eb22c 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -34,6 +34,7 @@ #include #include +class LLAvatarName; class LLInventoryPanel; class LLFloater; @@ -208,6 +209,14 @@ public: */ static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL); + /** + * Builds a string of residents' display names separated by "words_separator" string. + * + * @param avatar_names - a vector of given avatar names from which resulting string is built + * @param residents_string - the resulting string + */ + static void buildResidentsString(const std::vector avatar_names, std::string& residents_string); + static std::set getInventorySelectedUUIDs(); private: diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d3f3e41a29..c734c3edd2 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -42,7 +42,6 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) - , LLEventTimer(REFRESH_INTERVAL) , mIsP2PChat(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) @@ -52,6 +51,7 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) + , mRefreshTimer(new LLTimer()) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); @@ -67,6 +67,10 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable, this, _2)); + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); } LLIMConversation::~LLIMConversation() @@ -76,6 +80,8 @@ LLIMConversation::~LLIMConversation() delete mParticipantList; mParticipantList = NULL; } + + delete mRefreshTimer; } BOOL LLIMConversation::postBuild() @@ -120,19 +126,22 @@ BOOL LLIMConversation::postBuild() } -BOOL LLIMConversation::tick() +void LLIMConversation::draw() { - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) return false; + LLTransientDockableFloater::draw(); - // Need to resort the participant list if it's in sort by recent speaker order. - if (mParticipantList) + if (mRefreshTimer->hasExpired()) { - mParticipantList->update(); - } + if (mParticipantList) + { + mParticipantList->update(); + } - return false; + refresh(); + + // Restart the refresh timer + mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); + } } void LLIMConversation::buildParticipantList() @@ -144,10 +153,11 @@ void LLIMConversation::buildParticipantList() } else { + LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); // for group and ad-hoc chat we need to include agent into list - if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) + if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) { - LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + delete mParticipantList; // remove the old list and create a new one if the session id has changed mParticipantList = new LLParticipantList(speaker_manager, getChild("speakers_list"), true, false); } } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 47c98d6f8b..50663137ac 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -40,7 +40,6 @@ class LLChatHistory; class LLIMConversation : public LLTransientDockableFloater - , public LLEventTimer { public: @@ -65,6 +64,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); protected: @@ -89,8 +89,6 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); - /*virtual*/ BOOL tick(); - bool mIsNearbyChat; bool mIsP2PChat; @@ -103,6 +101,9 @@ protected: LLButton* mCloseBtn; private: + /// Refreshes the floater at a constant rate. + virtual void refresh() = 0; + /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); @@ -113,10 +114,11 @@ private: */ void reshapeChatHistory(); - LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; int mInputEditorTopPad; // padding between input field and chat history + + LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9ea4bec069..6a5bf153d4 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -105,6 +105,18 @@ void LLIMFloater::onFocusReceived() } } +// virtual +void LLIMFloater::refresh() +{ + if (mMeTyping) + { + // Time out if user hasn't typed for a while. + if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) + { + setTyping(false); + } + } +} /* static */ void LLIMFloater::newIMCallback(const LLSD& data) @@ -188,6 +200,7 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { + mParticipantsListRefreshConnection.disconnect(); mVoiceChannelStateChangeConnection.disconnect(); if(LLVoiceClient::instanceExists()) { @@ -225,6 +238,8 @@ void LLIMFloater::initIMFloater() boundVoiceChannel(); + mTypingStart = LLTrans::getString("IM_typing_start_string"); + // Show control panel in torn off floaters only. mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); @@ -246,6 +261,20 @@ void LLIMFloater::initIMFloater() { std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name, session_name); + + // For ad hoc conferences we should update the title with participants names. + if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) + || mDialog == IM_SESSION_CONFERENCE_START) + { + if (mParticipantsListRefreshConnection.connected()) + { + mParticipantsListRefreshConnection.disconnect(); + } + + LLAvatarList* avatar_list = getChild("speakers_list"); + mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( + boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); + } } } @@ -273,8 +302,6 @@ BOOL LLIMFloater::postBuild() setDocked(true); - mTypingStart = LLTrans::getString("IM_typing_start_string"); - LLButton* add_btn = getChild("add_btn"); // Allow to add chat participants depending on the session type @@ -341,7 +368,9 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { - if (*id == mOtherParticipantUUID) + // Skip this check for ad hoc conferences, + // conference participants should be listed in mSession->mInitialTargetIDs. + if (mIsP2PChat && *id == mOtherParticipantUUID) { return false; } @@ -411,11 +440,6 @@ void LLIMFloater::onCallButtonClicked() } } -/*void LLIMFloater::onOpenVoiceControlsClicked() -{ - LLFloaterReg::showInstance("voice_controls"); -}*/ - void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) { if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) @@ -448,28 +472,55 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, mTypingStart.setArg("[NAME]", ui_title); } -// virtual -BOOL LLIMFloater::tick() +void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) { - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) + LLAvatarList* avatar_list = dynamic_cast(ctrl); + if (!avatar_list) { - return false; + return; } - BOOL parents_retcode = LLIMConversation::tick(); + bool all_names_resolved = true; + std::vector participants_uuids; - if ( mMeTyping ) + avatar_list->getValues(participants_uuids); + + // Check whether we have all participants names in LLAvatarNameCache + for (std::vector::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it) { - // Time out if user hasn't typed for a while. - if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) + const LLUUID& id = it->asUUID(); + LLAvatarName av_name; + if (!LLAvatarNameCache::get(id, &av_name)) { - setTyping(false); + all_names_resolved = false; + + // If a name is not found in cache, request it and continue the process recursively + // until all ids are resolved into names. + LLAvatarNameCache::get(id, + boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); + break; } } - return parents_retcode; + if (all_names_resolved) + { + std::vector avatar_names; + std::vector::const_iterator it = participants_uuids.begin(); + for (; it != participants_uuids.end(); ++it) + { + const LLUUID& id = it->asUUID(); + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) + { + avatar_names.push_back(av_name); + } + } + + std::string ui_title; + LLAvatarActions::buildResidentsString(avatar_names, ui_title); + + updateSessionName(ui_title, ui_title); + } } //static @@ -737,8 +788,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) { initIMSession(im_session_id); - boundVoiceChannel(); - buildParticipantList(); } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 6847efedf1..23f9e75e21 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -66,7 +66,6 @@ public: /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); // Check typing timeout timer. - /*virtual*/ BOOL tick(); static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); @@ -131,12 +130,18 @@ private: /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + /*virtual*/ void refresh(); + // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); // For display name lookups for IM window titles void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + /// Updates the list of ad hoc conference participants + /// in an IM floater title. + void onParticipantsListChanged(LLUICtrl* ctrl); + bool dropPerson(LLUUID* person_id, bool drop); BOOL isInviteAllowed() const; @@ -193,6 +198,8 @@ private: // connection to voice channel state change signal boost::signals2::connection mVoiceChannelStateChangeConnection; + + boost::signals2::connection mParticipantsListRefreshConnection; }; #endif // LL_IMFLOATER_H diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 29ab4384cb..369ca699c5 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -186,6 +186,21 @@ BOOL LLNearbyChat::postBuild() return LLIMConversation::postBuild(); } +// virtual +void LLNearbyChat::refresh() +{ + displaySpeakingIndicator(); + updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); + + // *HACK: Update transparency type depending on whether our children have focus. + // This is needed because this floater is chrome and thus cannot accept focus, so + // the transparency type setting code from LLFloater::setFocus() isn't reached. + if (getTransparencyType() != TT_DEFAULT) + { + setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); + } +} + void LLNearbyChat::onNearbySpeakers() { LLSD param; @@ -389,27 +404,6 @@ void LLNearbyChat::showHistory() storeRectControl(); } - -BOOL LLNearbyChat::tick() -{ - // This check is needed until LLFloaterReg::removeInstance() is synchronized with deleting the floater - // via LLMortician::updateClass(), to avoid calling dead instances. See LLFloater::destroy(). - if (isDead()) return false; - - displaySpeakingIndicator(); - updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); - - // *HACK: Update transparency type depending on whether our children have focus. - // This is needed because this floater is chrome and thus cannot accept focus, so - // the transparency type setting code from LLFloater::setFocus() isn't reached. - if (getTransparencyType() != TT_DEFAULT) - { - setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); - } - - return LLIMConversation::tick(); -} - std::string LLNearbyChat::getCurrentChat() { return mChatBox ? mChatBox->getText() : LLStringUtil::null; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index c9aa69a912..db367f0b59 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -73,8 +73,6 @@ public: LLChatEntry* getChatBox() { return mChatBox; } - //virtual void draw(); - std::string getCurrentChat(); virtual BOOL handleKeyHere( KEY key, MASK mask ); @@ -119,8 +117,6 @@ protected: S32 mExpandedHeight; - /*virtual*/ BOOL tick(); - private: void getAllowedRect (LLRect& rect); @@ -128,6 +124,8 @@ private: void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); + /*virtual*/ void refresh(); + LLHandle mPopupMenuHandle; std::vector mMessageArchive; LLChatHistory* mChatHistory; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 59d26edff2..47518a365f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -475,6 +475,7 @@ void LLParticipantList::update() { mSpeakerMgr->update(true); + // Need to resort the participant list if it's in sort by recent speaker order. if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered()) { // Resort avatar list -- cgit v1.2.3 From 99c1c64aa494c0b9085f0766b951fedfb60ce412 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 26 Jun 2012 16:05:03 -0400 Subject: SH-3172 WIP - fix --- indra/newview/llappearancemgr.cpp | 2 +- indra/newview/lldynamictexture.cpp | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/lldynamictexture.cpp diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5d2ff1b40f..02a90c60ec 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2583,7 +2583,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base // Should be true iff both the appropriate debug setting is enabled // and the corresponding cap has been found. -bool useServerTextureBaking() +bool LLAppearanceMgr::useServerTextureBaking() { // TODO: add cap check. return gSavedSettings.getBOOL("UseServerTextureBaking"); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp old mode 100644 new mode 100755 -- cgit v1.2.3 From 3385a6398951bc94b3dc5da6224e285d85e606ab Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 27 Jun 2012 16:11:04 +0300 Subject: CHUI-162 FIXED Opening a nearby chat when text entered --- indra/newview/llnearbychat.cpp | 22 ++++++++++++++++++++++ indra/newview/llnearbychat.h | 1 + 2 files changed, 23 insertions(+) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 369ca699c5..ee7169b1c3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -131,6 +131,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + setIsChrome(TRUE); mKey = LLSD(); mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); @@ -394,6 +395,26 @@ LLNearbyChat* LLNearbyChat::getInstance() return LLFloaterReg::getTypedInstance("chat_bar"); } +void LLNearbyChat::show() +{ + // Get the floater + LLNearbyChat* floater = LLNearbyChat::getInstance(); + if (floater) + { + if(isChatMultiTab()) + { + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + + // Add a conversation list item in the left pane: nothing will be done if already in there + // but relevant clean up will be done to ensure consistency of the conversation list + floater_container->addConversationListItem(floater->getTitle(), LLUUID(), floater); + + floater->openFloater(floater->getKey()); + } + + floater->setVisible(TRUE); + } +} void LLNearbyChat::showHistory() { @@ -773,6 +794,7 @@ void LLNearbyChat::startChat(const char* line) if (cb ) { + cb->show(); cb->setVisible(TRUE); cb->setFocus(TRUE); cb->mChatBox->setFocus(TRUE); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index db367f0b59..61404df942 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -65,6 +65,7 @@ public: static LLNearbyChat* getInstance(); void addToHost(); + void show(); /** @param archive true - to save a message to the chat history log */ void addMessage (const LLChat& message,bool archive = true, const LLSD &args = LLSD()); -- cgit v1.2.3 From 9091986c698af6d008a12f1944724609d649b63e Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 27 Jun 2012 19:33:22 +0300 Subject: CHUI-147 FIX Added check against empty participants names array to pass the assertion in LLAvatarActions::buildResidentsString. --- indra/newview/llimfloater.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 6a5bf153d4..1bbf6cc320 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -516,10 +516,14 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) } } - std::string ui_title; - LLAvatarActions::buildResidentsString(avatar_names, ui_title); - - updateSessionName(ui_title, ui_title); + // We should check whether the vector is not empty to pass the assertion + // that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. + if (!avatar_names.empty()) + { + std::string ui_title; + LLAvatarActions::buildResidentsString(avatar_names, ui_title); + updateSessionName(ui_title, ui_title); + } } } -- cgit v1.2.3 From 0eda1f9a4d909870b15c6d7243e47838540598e8 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 27 Jun 2012 19:33:27 +0300 Subject: CHUI-169 FIX Restored inventory sharing functionality via IM floater drag and drop. --- indra/newview/llimfloater.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1bbf6cc320..b94a4048d4 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -1077,6 +1077,12 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, *accept = ACCEPT_NO; } } + else if (mDialog == IM_NOTHING_SPECIAL) + { + LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, + cargo_type, cargo_data, accept); + } + return TRUE; } -- cgit v1.2.3 From 0e316a1510d5051088a62b86e4b0e05702786d9a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 27 Jun 2012 21:30:05 +0300 Subject: CHUI-125 FIXED Supressed of a commented out code --- indra/newview/llchicletbar.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 0e58008cd2..39f5d0b8f6 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -57,24 +57,11 @@ LLChicletBar::LLChicletBar(const LLSD&) : mChicletPanel(NULL), mToolbarStack(NULL) { - // IM floaters are from now managed by LLIMFloaterContainer. - // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 - -// // Firstly add our self to IMSession observers, so we catch session events -// // before chiclets do that. -// LLIMMgr::getInstance()->addSessionObserver(this); - buildFromFile("panel_chiclet_bar.xml"); } LLChicletBar::~LLChicletBar() { - // IM floaters are from now managed by LLIMFloaterContainer. - // See LLIMFloaterContainer::sessionVoiceOrIMStarted() and CHUI-125 -// if (!LLSingleton::destroyed()) -// { -// LLIMMgr::getInstance()->removeSessionObserver(this); -// } } LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) -- cgit v1.2.3 From 1eb6b4509d9ae79f8313e1e68351028794093a53 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Jun 2012 14:03:16 -0700 Subject: CHUI-139 : Make sure the Nearby Chat shows up in the conversations floater in every situation --- indra/newview/llimfloatercontainer.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f6bcf8bbe9..52bacf15e4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -103,24 +103,7 @@ BOOL LLIMFloaterContainer::postBuild() void LLIMFloaterContainer::onOpen(const LLSD& key) { - if (getFloaterCount() == 0) - { - // We always force the opening of the nearby chat conversation when we open for the first time - // *TODO: find a way to move this to XML as a default panel or something like that - LLSD name("chat_bar"); - LLFloaterReg::toggleInstanceOrBringToFront(name); - } LLMultiFloater::onOpen(key); - /* - if (key.isDefined()) - { - LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); - if (im_floater) - { - im_floater->openFloater(); - } - } - */ } // virtual @@ -307,6 +290,20 @@ void LLIMFloaterContainer::tabClose() void LLIMFloaterContainer::setVisible(BOOL visible) { + if (visible) + { + // Make sure we have the Nearby Chat present when showing the conversation container + LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is null + conversations_items_map::iterator item_it = mConversationsItems.find(nearbychat_uuid); + if (item_it == mConversationsItems.end()) + { + // If not found, force the creation of the nearby chat conversation panel + // *TODO: find a way to move this to XML as a default panel or something like that + LLSD name("chat_bar"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + } + // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. -- cgit v1.2.3 From fbbde138c42dfced9b8805e4ce774ae8605e9d9b Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 27 Jun 2012 17:40:19 -0400 Subject: SH-3231 FIX Process new texture fetch url from login.cgi - Added a new global setting (non-persist) to store the texture request URL - New setting is 'AgentAppearanceServiceURL' --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llstartup.cpp | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 53c7ceaa80..6a0b9559d0 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -71,6 +71,17 @@ Value 0 + AgentAppearanceServiceURL + + Comment + Current Session Agent Appearance Service URL + Persist + 0 + Type + String + Value + + AlertedUnsupportedHardware Comment diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ebde7a55fe..e271653b2d 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3442,6 +3442,14 @@ bool process_login_success_response() } + // set the location of the Agent Appearance service, from which we can request + // avatar baked textures if they are supported by the current region + std::string agent_appearance_url = response["agent_appearance_service"]; + if (!agent_appearance_url.empty()) + { + gSavedSettings.setString("AgentAppearanceServiceURL", agent_appearance_url); + } + // Set the location of the snapshot sharing config endpoint std::string snapshot_config_url = response["snapshot_config_url"]; if(!snapshot_config_url.empty()) -- cgit v1.2.3 From d470632799dfdea723d15d91aa5783bdd1700257 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Jun 2012 15:32:08 -0700 Subject: CHUI-130 : Leave minimized torn off IM untouched when showing hiding the whole set of conversations --- indra/newview/llimfloatercontainer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 52bacf15e4..34a9758c52 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -556,8 +556,9 @@ void LLConversationItem::selectItem(void) void LLConversationItem::setVisibleIfDetached(BOOL visible) { - // Do this only if the conversation floater has been torn off (i.e. no multi floater host) - if (!mFloater->getHost()) + // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized + // Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here + if (!mFloater->getHost() && !mFloater->isMinimized()) { mFloater->setVisible(visible); } -- cgit v1.2.3 From c9da4d0a6dccbdcff228a5841d224463bc45297c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Jun 2012 15:55:09 -0700 Subject: CHUI-162 : Simplified the nearby chat show method following CHUI-139 fixes --- indra/newview/llnearbychat.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index ee7169b1c3..a81d6b4025 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -397,23 +397,11 @@ LLNearbyChat* LLNearbyChat::getInstance() void LLNearbyChat::show() { - // Get the floater - LLNearbyChat* floater = LLNearbyChat::getInstance(); - if (floater) + if (isChatMultiTab()) { - if(isChatMultiTab()) - { - LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); - - // Add a conversation list item in the left pane: nothing will be done if already in there - // but relevant clean up will be done to ensure consistency of the conversation list - floater_container->addConversationListItem(floater->getTitle(), LLUUID(), floater); - - floater->openFloater(floater->getKey()); - } - - floater->setVisible(TRUE); + openFloater(getKey()); } + setVisible(TRUE); } void LLNearbyChat::showHistory() -- cgit v1.2.3 From 7a147c1de99a7d03008d2921f091aa3de03a559f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Jun 2012 17:08:19 -0700 Subject: CHUI-146 : Fixed. Focus goes to first conversation in list when a conversation is dismissed. --- indra/newview/llimfloater.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index b94a4048d4..9d3c0f98ce 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -628,9 +628,6 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) void LLIMFloater::onClose(bool app_quitting) { - LLIMConversation::onClose(app_quitting); - - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( mSessionID); @@ -663,6 +660,8 @@ void LLIMFloater::onClose(bool app_quitting) // EXT-3516 X Button should end IM session, _ button should hide gIMMgr->leaveSession(mSessionID); + // Clean up the conversation *after* the session has been ended + LLIMConversation::onClose(app_quitting); } void LLIMFloater::setDocked(bool docked, bool pop_on_undock) -- cgit v1.2.3 From cbe3c3ae95c0850cd0ecba893ddabe0200bbc0ac Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Jun 2012 17:16:15 -0700 Subject: CHUI-184 : Change default pref LetterKeysFocusChatBar from 1 (chat) to 0 (WASD movements) --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fe6829a712..4a586b02af 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1538,7 +1538,7 @@ Type S32 Value - 1 + 0 ChatBubbleOpacity -- cgit v1.2.3 From cb865a7e1300d4ce0bedae7c856fb210b68a43f8 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 27 Jun 2012 18:56:10 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose moved filtering logic to viewmodel --- indra/llui/llnotifications.cpp | 24 +- indra/newview/llfolderview.cpp | 106 ++--- indra/newview/llfolderview.h | 12 +- indra/newview/llfolderviewitem.cpp | 787 +++++++------------------------ indra/newview/llfolderviewitem.h | 82 +--- indra/newview/llfolderviewmodel.h | 194 ++++---- indra/newview/llinventorybridge.cpp | 20 +- indra/newview/llinventorybridge.h | 3 + indra/newview/llinventoryfilter.cpp | 97 ++-- indra/newview/llinventoryfilter.h | 20 +- indra/newview/llinventoryfunctions.cpp | 10 +- indra/newview/llinventorypanel.cpp | 128 ++++- indra/newview/llinventorypanel.h | 6 + indra/newview/llpanellandmarks.cpp | 2 +- indra/newview/llpanelmaininventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 11 + indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/lltexturectrl.cpp | 10 +- 18 files changed, 557 insertions(+), 959 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 487a2e5fe7..48128e0b40 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1542,34 +1542,32 @@ void LLNotifications::addFromCallback(const LLSD& name) add(name.asString(), LLSD(), LLSD()); } -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload) { LLNotification::Params::Functor functor_p; functor_p.name = name; return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); } -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - const std::string& functor_name) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name) { LLNotification::Params::Functor functor_p; functor_p.name = functor_name; - return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } //virtual -LLNotificationPtr LLNotifications::add(const std::string& name, - const LLSD& substitutions, - const LLSD& payload, - LLNotificationFunctorRegistry::ResponseFunctor functor) +LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor) { LLNotification::Params::Functor functor_p; functor_p.function = functor; - return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p)); + return add(LLNotification::Params().name(name) + .substitutions(substitutions) + .payload(payload) + .functor(functor_p)); } // generalized add function that takes a parameter block object for more complex instantiations diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index ee8c94a2dd..a37fc7714b 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -181,7 +181,6 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoSelect( FALSE ), mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), - mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately mFilter(new LLInventoryFilter(LLInventoryFilter::Params().name(p.title))), mShowSelectionContext(FALSE), @@ -316,7 +315,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); addChild( folder ); - folder->dirtyFilter(); + folder->getViewModelItem()->dirtyFilter(); folder->requestArrange(); return TRUE; } @@ -339,15 +338,14 @@ void LLFolderView::openTopLevelFolders() } // This view grows and shrinks to enclose all of its children items and folders. -// mItemHeight = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; // *width should be 0 // conform show folder state works -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) { mMinWidth = 0; S32 target_height; - LLFolderViewFolder::arrange(&mMinWidth, &target_height, mFilter->getFirstSuccessGeneration()); + LLFolderViewFolder::arrange(&mMinWidth, &target_height); LLRect scroll_rect = mScrollContainer->getContentWindowRect(); reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); @@ -371,15 +369,10 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) + if (getLastFilterGeneration() < filter.getCurrentGeneration()) { - mPassedFilter = FALSE; mMinWidth = 0; - LLFolderViewFolder::filter(filter); - } - else - { - mPassedFilter = TRUE; + getViewModelItem()->filter(filter); } } @@ -548,15 +541,15 @@ void LLFolderView::sanitizeSelection() LLFolderViewItem* item = *item_iter; // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item + BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } // deselect item if any ancestor is closed or didn't pass filter requirements. if (!visible) @@ -606,7 +599,7 @@ void LLFolderView::sanitizeSelection() parent_folder; parent_folder = parent_folder->getParentFolder()) { - if (parent_folder->potentiallyVisible()) + if (parent_folder->getViewModelItem()->potentiallyVisible()) { // give initial selection to first ancestor folder that potentially passes the filter if (!new_selection) @@ -684,16 +677,6 @@ void LLFolderView::commitRename( const LLSD& data ) void LLFolderView::draw() { - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); - if (mDebugFilters) - { - std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter->getCurrentGeneration(), mFilter->getFirstSuccessGeneration(), mFilter->getFirstRequiredGeneration()); - LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, - getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); - } - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); // if cursor has moved off of me during drag and drop @@ -734,17 +717,14 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) + if (!mViewModel->contentsReady() || getLastFilterGeneration() < mFilter->getFirstSuccessGeneration()) { // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else { - if (getFilter()) - { - mStatusText = getFilter()->getEmptyLookupMessage(); - } + mStatusText = getFolderViewModel()->getFilter()->getEmptyLookupMessage(); } mStatusTextBox->setValue(mStatusText); mStatusTextBox->setVisible( TRUE ); @@ -763,7 +743,11 @@ void LLFolderView::draw() // This will indirectly call ::arrange and reshape of the status textbox. // We should call this method to also notify parent about required rect. // See EXT-7564, EXT-7047. - arrangeFromRoot(); + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + LLUI::popMatrix(); LLUI::pushMatrix(); LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); @@ -902,16 +886,16 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } if(parent) { - if (parent->removeItem(item_to_delete)) + if (item_to_delete->remove()) { // change selection on successful delete if (new_selection) { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); } else { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); } } } @@ -937,11 +921,11 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } if (new_selection) { - setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); } else { - setSelectionFromRoot(NULL, mParentPanel->hasFocus()); + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); } for(S32 i = 0; i < count; ++i) @@ -1386,12 +1370,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (next->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + getRoot()->changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == next->getParentFolder()) { // grow selection - changeSelectionFromRoot(next, TRUE); + getRoot()->changeSelection(next, TRUE); } } } @@ -1450,12 +1434,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (prev->isSelected()) { // shrink selection - changeSelectionFromRoot(last_selected, FALSE); + getRoot()->changeSelection(last_selected, FALSE); } else if (last_selected->getParentFolder() == prev->getParentFolder()) { // grow selection - changeSelectionFromRoot(prev, TRUE); + getRoot()->changeSelection(prev, TRUE); } } } @@ -1649,7 +1633,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc } } - const std::string current_item_label(search_item->getSearchableLabel()); + const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); if (!current_item_label.compare(0, search_string_length, upper_case_string)) { @@ -1959,13 +1943,6 @@ void LLFolderView::doIdle() LLFastTimer t2(FTM_INVENTORY); - BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); - if (debug_filters != getDebugFilters()) - { - mDebugFilters = debug_filters; - arrangeAll(); - } - if (mFilter->isModified() && mFilter->isNotDefault()) { mNeedsAutoSelect = TRUE; @@ -1973,7 +1950,7 @@ void LLFolderView::doIdle() mFilter->clearModified(); // filter to determine visibility before arranging - filterFromRoot(); + filter(*(getFolderViewModel()->getFilter())); // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) @@ -1981,7 +1958,7 @@ void LLFolderView::doIdle() LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyHidden())) + if (!mAutoSelectOverride && (!selected_itemp || selected_itemp->passedFilter())) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1991,7 +1968,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mAutoSelectOverride && mFilter->showAllResults()) + if (mFilter->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -2002,7 +1979,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() + BOOL filter_finished = getLastFilterGeneration() >= mFilter->getCurrentGeneration() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) @@ -2073,7 +2050,10 @@ void LLFolderView::doIdle() sanitizeSelection(); if( needsArrange() ) { - arrangeFromRoot(); + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); } } @@ -2278,25 +2258,19 @@ void LLFolderView::onRenamerLost() if( mRenameItem ) { - setSelectionFromRoot( mRenameItem, TRUE ); + setSelection( mRenameItem, TRUE ); mRenameItem = NULL; } } -LLFolderViewFilter* LLFolderView::getFilter() -{ - return mFilter; -} - S32 LLFolderView::getItemHeight() { - S32 debug_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; if(!hasVisibleChildren()) { //We need to display status textbox, let's reserve some place for it - return llmax(debug_height, mStatusTextBox->getTextPixelHeight()); + return llmax(0, mStatusTextBox->getTextPixelHeight()); } - return debug_height; + return 0; } //TODO RN: move to llfolderviewmodel.cpp file diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8b58da9f45..d261a5967d 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -110,9 +110,11 @@ public: virtual BOOL canFocusChildren() const; + virtual const LLFolderView* getRoot() const { return this; } virtual LLFolderView* getRoot() { return this; } LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } void setFilterPermMask(PermissionMask filter_perm_mask); @@ -120,9 +122,6 @@ public: void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - // filter is never null - LLFolderViewFilter* getFilter(); - bool getAllowMultiSelect() { return mAllowMultiSelect; } // Close all folders in the view @@ -133,7 +132,7 @@ public: // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); void arrangeAll() { mArrangeGeneration++; } @@ -147,7 +146,7 @@ public: // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus); + BOOL take_keyboard_focus = TRUE); // This method is used to toggle the selection of an item. Walks // children, and keeps track of selected objects. @@ -244,8 +243,6 @@ public: void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - BOOL getDebugFilters() { return mDebugFilters; } - LLPanel* getParentPanel() { return mParentPanel; } // DEBUG only void dumpSelectionInformation(); @@ -299,7 +296,6 @@ protected: bool mUseLabelSuffix; bool mShowItemLinkOverlays; - BOOL mDebugFilters; U32 mSortOrder; LLDepthStack mAutoOpenItems; LLFolderViewFolder* mAutoOpenCandidate; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 3f0b493986..f65a13be1e 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -114,8 +114,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mHasVisibleChildren(FALSE), mIndentation(0), mItemHeight(p.item_height), - mPassedFilter(FALSE), - mLastFilterGeneration(-1), //TODO RN: create interface for string highlighting //mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), @@ -146,6 +144,10 @@ LLFolderView* LLFolderViewItem::getRoot() return mRoot; } +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) { @@ -207,99 +209,47 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) return itemp; } -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() -{ - return getFiltered() // we've passed the filter - || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet -} - -BOOL LLFolderViewItem::potentiallyHidden() +BOOL LLFolderViewItem::passedFilter(S32 filter_generation) { - return !mPassedFilter // didn't pass the filter - || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet -} - -BOOL LLFolderViewItem::getFiltered() -{ - return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} - -BOOL LLFolderViewItem::getFiltered(S32 filter_generation) -{ - return mPassedFilter && mLastFilterGeneration >= filter_generation; -} - -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ - mPassedFilter = filtered; - mLastFilterGeneration = filter_generation; + return getViewModelItem()->passedFilter(filter_generation); } void LLFolderViewItem::refresh() { - if(!getViewModelItem()) return; + LLFolderViewModelItem& vmi = *getViewModelItem(); - mLabel = getViewModelItem()->getDisplayName(); + mLabel = vmi.getDisplayName(); setToolTip(mLabel); - mIcon = getViewModelItem()->getIcon(); - mIconOpen = getViewModelItem()->getIconOpen(); - mIconOverlay = getViewModelItem()->getIconOverlay(); + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); if (mRoot->useLabelSuffix()) { - mLabelStyle = getViewModelItem()->getLabelStyle(); - mLabelSuffix = getViewModelItem()->getLabelSuffix(); + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); } - std::string searchable_label(mLabel); - searchable_label.append(mLabelSuffix); - LLStringUtil::toUpper(searchable_label); + //TODO RN: make sure this logic still fires + //std::string searchable_label(mLabel); + //searchable_label.append(mLabelSuffix); + //LLStringUtil::toUpper(searchable_label); - if (mSearchableLabel.compare(searchable_label)) - { - mSearchableLabel.assign(searchable_label); - dirtyFilter(); - // some part of label has changed, so overall width has potentially changed, and sort order too - if (mParentFolder) - { - mParentFolder->requestSort(); - mParentFolder->requestArrange(); - } - } + //if (mSearchableLabel.compare(searchable_label)) + //{ + // mSearchableLabel.assign(searchable_label); + // vmi.dirtyFilter(); + // // some part of label has changed, so overall width has potentially changed, and sort order too + // if (mParentFolder) + // { + // mParentFolder->requestSort(); + // mParentFolder->requestArrange(); + // } + //} mLabelWidthDirty = true; - dirtyFilter(); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ - LLFolderViewItem* root = getRoot(); - - root->filter(*((LLFolderView*)root)->getFilter()); -} - -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ - LLFolderViewItem* root = getRoot(); - - S32 height = 0; - S32 width = 0; - S32 total_height = root->arrange( &width, &height, 0 ); - - LLSD params; - params["action"] = "size_changes"; - params["height"] = total_height; - getParent()->notifyParent(params); + vmi.dirtyFilter(); } // Utility function for LLFolderView @@ -313,7 +263,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, } if(set_selection) { - setSelectionFromRoot(this, TRUE, take_keyboard_focus); + getRoot()->setSelection(this, TRUE, take_keyboard_focus); if(root) { root->scrollToShowSelection(); @@ -321,22 +271,6 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, } } -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, - BOOL openitem, - BOOL take_keyboard_focus) -{ - getRoot()->setSelection(selection, openitem, take_keyboard_focus); -} - -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ - getRoot()->changeSelection(selection, selected); -} std::set LLFolderViewItem::getSelectionList() const { @@ -347,18 +281,13 @@ std::set LLFolderViewItem::getSelectionList() const // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - if (!folder) - { - return FALSE; - } - mParentFolder = folder; return folder->addItem(this); } // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewItem::arrange( S32* width, S32* height ) { const Params& p = LLUICtrlFactory::getDefaultParams(); S32 indentation = p.folder_indentation(); @@ -390,41 +319,6 @@ S32 LLFolderViewItem::getItemHeight() return mItemHeight; } -void LLFolderViewItem::filter( LLFolderViewFilter& filter) -{ - const BOOL previous_passed_filter = mPassedFilter; - const BOOL passed_filter = filter.check(this); - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - if (mParentFolder) - { - if (getVisible() != passed_filter - || previous_passed_filter != passed_filter ) - mParentFolder->requestArrange(); - } - - setFiltered(passed_filter, filter.getCurrentGeneration()); - //TODO RN: create interface for string highlighting - //mStringMatchOffset = filter.getStringMatchOffset(this); - filter.decrementFilterCount(); - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - } -} - -void LLFolderViewItem::dirtyFilter() -{ - mLastFilterGeneration = -1; - // bubble up dirty flag all the way to root - if (getParentFolder()) - { - getParentFolder()->setCompletedFilterGeneration(-1, TRUE); - } -} - // *TODO: This can be optimized a lot by simply recording that it is // selected in the appropriate places, and assuming that set selection // means 'deselect' for a leaf item. Do this optimization after @@ -469,45 +363,31 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - if (getViewModelItem()) - { - getViewModelItem()->selectItem(); - } + getViewModelItem()->selectItem(); mIsSelected = TRUE; } } BOOL LLFolderViewItem::isMovable() { - if( getViewModelItem() ) - { - return getViewModelItem()->isItemMovable(); - } - else - { - return TRUE; - } + return getViewModelItem()->isItemMovable(); } BOOL LLFolderViewItem::isRemovable() { - if( getViewModelItem() ) - { - return getViewModelItem()->isItemRemovable(); - } - else - { - return TRUE; - } + return getViewModelItem()->isItemRemovable(); } void LLFolderViewItem::destroyView() { + getRoot()->removeFromSelectionList(this); + if (mParentFolder) { // removeView deletes me - mParentFolder->removeView(this); + mParentFolder->extractItem(this); } + delete this; } // Call through to the viewed object and return true if it can be @@ -519,58 +399,36 @@ BOOL LLFolderViewItem::remove() { return FALSE; } - if(getViewModelItem()) - { - return getViewModelItem()->removeItem(); - } - return TRUE; + return getViewModelItem()->removeItem(); } // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - if(getViewModelItem()) - { - getViewModelItem()->buildContextMenu(menu, flags); - } + getViewModelItem()->buildContextMenu(menu, flags); } void LLFolderViewItem::openItem( void ) { - if( getViewModelItem() ) - { - getViewModelItem()->openItem(); - } + getViewModelItem()->openItem(); } void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) { - if( getViewModelItem() ) - { - getViewModelItem()->renameItem(new_name); + getViewModelItem()->renameItem(new_name); - if(mParentFolder) - { - mParentFolder->requestSort(); - } + if(mParentFolder) + { + mParentFolder->requestSort(); } } } -const std::string& LLFolderViewItem::getSearchableLabel() const -{ - return mSearchableLabel; -} - const std::string& LLFolderViewItem::getName( void ) const { - if(getViewModelItem()) - { - return getViewModelItem()->getName(); - } - return LLStringUtil::null; + return getViewModelItem()->getName(); } // LLView functionality @@ -578,7 +436,7 @@ BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if(!mIsSelected) { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); return TRUE; @@ -599,7 +457,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -607,7 +465,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } make_ui_sound("UISndClick"); } @@ -646,14 +504,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // *TODO: push this into listener and remove // dependency on llagent - if (getViewModelItem()) - { - src = getViewModelItem()->getDragSource(); - } - else - { - src = LLToolDragAndDrop::SOURCE_VIEWER; - } + src = getViewModelItem()->getDragSource(); can_drag = root->startDrag(src); if (can_drag) @@ -695,10 +546,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - if (getViewModelItem()) - { - getViewModelItem()->openItem(); - } + getViewModelItem()->openItem(); return TRUE; } @@ -715,7 +563,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) //...then select if(mask & MASK_CONTROL) { - changeSelectionFromRoot(this, !mIsSelected); + getRoot()->changeSelection(this, !mIsSelected); } else if (mask & MASK_SHIFT) { @@ -723,7 +571,7 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); } } @@ -748,21 +596,17 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = FALSE; BOOL handled = FALSE; - if(getViewModelItem()) + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) { - accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; } if(mParentFolder && !handled) { @@ -781,17 +625,17 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderViewItem::draw() { - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); const Params& default_params = LLUICtrlFactory::getDefaultParams(); const S32 TOP_PAD = default_params.item_top_pad; @@ -929,29 +773,12 @@ void LLFolderViewItem::draw() LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; //TODO RN: implement this in terms of getColor() //if (highlight_link) color = sLinkColor; - //if (getViewModelItem() && gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - //--------------------------------------------------------------------------------// - // Highlight filtered text - // - if (getRoot()->getDebugFilters()) - { - if (!getFiltered() && !getViewModelItem()->hasChildren()) - { - color.mV[VALPHA] *= 0.5f; - } - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? - LLColor4(0.5f, 0.8f, 0.5f, 1.f) : - LLColor4(0.8f, 0.5f, 0.5f, 1.f); - LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; - } //--------------------------------------------------------------------------------// // Draw the actual label text // @@ -997,6 +824,22 @@ void LLFolderViewItem::draw() //} } +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const +{ + return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) +{ + return getRoot()->getFolderViewModel(); +} + +S32 LLFolderViewItem::getLastFilterGeneration() const +{ + return getViewModelItem()->getLastFilterGeneration(); +} + + ///---------------------------------------------------------------------------- /// Class LLFolderViewFolder @@ -1010,10 +853,7 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): mTargetHeight(0.f), mAutoOpenCountdown(0.f), mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0), - mCompletedFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mPassedFolderFilter(FALSE) + mLastCalculatedWidth(0) { } @@ -1025,25 +865,9 @@ LLFolderViewFolder::~LLFolderViewFolder( void ) gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() } -void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) -{ - mPassedFolderFilter = filtered; - mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) -{ - return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} - // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { - if (!folder) - { - return FALSE; - } - mParentFolder = folder; return folder->addFolder(this); } @@ -1051,7 +875,7 @@ static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) +S32 LLFolderViewFolder::arrange( S32* width, S32* height ) { // sort before laying out contents getRoot()->getFolderViewModel()->sort(this); @@ -1060,7 +884,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // evaluate mHasVisibleChildren mHasVisibleChildren = false; - if (hasFilteredDescendants(filter_generation)) + if (getViewModelItem()->descendantsPassedFilter()) { // We have to verify that there's at least one child that's not filtered out bool found = false; @@ -1068,7 +892,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) { LLFolderViewItem* itemp = (*iit); - found = (itemp->getFiltered(filter_generation)); + found = itemp->passedFilter(); if (found) break; } @@ -1078,9 +902,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - found = ( (folderp->getFiltered(filter_generation) - || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation)))); + found = folderp->passedFilter(); if (found) break; } @@ -1090,7 +912,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) } // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height, filter_generation ); + LLFolderViewItem::arrange( width, height ); // clamp existing animated height so as to never get smaller than a single item mCurHeight = llmax((F32)*height, mCurHeight); @@ -1113,16 +935,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - if (getRoot()->getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible( folderp->getFiltered(filter_generation) - || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter - } + folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter if (folderp->getVisible()) { @@ -1130,7 +943,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) S32 child_height = 0; S32 child_top = parent_item_height - llround(running_height); - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); + target_height += folderp->arrange( &child_width, &child_height ); running_height += (F32)child_height; *width = llmax(*width, child_width); @@ -1141,14 +954,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) iit != mItems.end(); ++iit) { LLFolderViewItem* itemp = (*iit); - if (getRoot()->getDebugFilters()) - { - itemp->setVisible(TRUE); - } - else - { - itemp->setVisible(itemp->getFiltered(filter_generation)); - } + itemp->setVisible(itemp->passedFilter()); if (itemp->getVisible()) { @@ -1156,7 +962,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) S32 child_height = 0; S32 child_top = parent_item_height - llround(running_height); - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); + target_height += itemp->arrange( &child_width, &child_height ); // don't change width, as this item is as wide as its parent folder by construction itemp->reshape( itemp->getRect().getWidth(), child_height); @@ -1234,234 +1040,21 @@ void LLFolderViewFolder::requestSort() getViewModelItem()->requestSort(); } -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ - //mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); - mCompletedFilterGeneration = generation; - // only aggregate up if we are a lower (older) value - if (recurse_up - && mParentFolder - && generation < mParentFolder->getCompletedFilterGeneration()) - { - mParentFolder->setCompletedFilterGeneration(generation, TRUE); - } -} +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +// // if this folder is now filtered, but wasn't before +// // (it just passed) +// if (passed && !passedFilter(filter_generation)) +// { +// // reset current height, because last time we drew it +// // it might have had more visible items than now +// mCurHeight = 0.f; +// } +// +// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} -void LLFolderViewFolder::filter( LLFolderViewFilter& filter) -{ - S32 filter_generation = filter.getCurrentGeneration(); - // if failed to pass filter newer than must_pass_generation - // you will automatically fail this time, so we only - // check against items that have passed the filter - S32 must_pass_generation = filter.getFirstRequiredGeneration(); - - bool autoopen_folders = filter.showAllResults(); - - // if we have already been filtered against this generation, skip out - if (getCompletedFilterGeneration() >= filter_generation) - { - return; - } - - // filter folder itself - if (getLastFilterGeneration() < filter_generation) - { - if (getLastFilterGeneration() >= must_pass_generation // folder has been compared to a valid precursor filter - && !mPassedFilter) // and did not pass the filter - { - // go ahead and flag this folder as done - mLastFilterGeneration = filter_generation; - //TODO RN: create interface for string highlighting - //mStringMatchOffset = std::string::npos; - } - else // filter self only on first pass through - { - // filter against folder rules - filterFolder(filter); - // and then item rules - LLFolderViewItem::filter( filter ); - } - } - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - mStatusText += llformat("(%d)", mCompletedFilterGeneration); - mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); - } - - // all descendants have been filtered later than must pass generation - // but none passed - if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) - { - // don't traverse children if we've already filtered them since must_pass_generation - // and came back with nothing - return; - } - - // we entered here with at least one filter iteration left - // check to see if we have any more before continuing on to children - if (filter.getFilterCount() < 0) - { - return; - } - - // now query children - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - LLFolderViewFolder* folder = (*iter); - // have we run out of iterations this frame? - if (filter.getFilterCount() < 0) - { - break; - } - - // mMostFilteredDescendantGeneration might have been reset - // in which case we need to update it even for folders that - // don't need to be filtered anymore - if (folder->getCompletedFilterGeneration() >= filter_generation) - { - // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getFirstSuccessGeneration())) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - // just skip it, it has already been filtered - continue; - } - - // update this folders filter status (and children) - folder->filter( filter ); - - // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - if (getRoot()->needsAutoSelect() && autoopen_folders) - { - folder->setOpenArrangeRecursively(TRUE); - } - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end(); - ++iter) - { - LLFolderViewItem* item = (*iter); - if (filter.getFilterCount() < 0) - { - break; - } - if (item->getLastFilterGeneration() >= filter_generation) - { - if (item->getFiltered()) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - continue; - } - - if (item->getLastFilterGeneration() >= must_pass_generation && - !item->getFiltered(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - item->setFiltered(FALSE, filter_generation); - continue; - } - - item->filter( filter ); - - if (item->getFiltered(filter.getFirstSuccessGeneration())) - { - mMostFilteredDescendantGeneration = filter_generation; - requestArrange(); - } - } - - // if we didn't use all filter iterations - // that means we filtered all of our descendants - // instead of exhausting the filter count for this frame - if (filter.getFilterCount() > 0) - { - // flag this folder as having completed filter pass for all descendants - setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); - } -} - -void LLFolderViewFolder::filterFolder(LLFolderViewFilter& filter) -{ - const BOOL previous_passed_filter = mPassedFolderFilter; - const BOOL passed_filter = filter.checkFolder(this); - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - if (mParentFolder) - { - if (getVisible() != passed_filter - || previous_passed_filter != passed_filter ) - { - mParentFolder->requestArrange(); - } - } - - setFilteredFolder(passed_filter, filter.getCurrentGeneration()); - filter.decrementFilterCount(); - - if (getRoot()->getDebugFilters()) - { - mStatusText = llformat("%d", mLastFilterGeneration); - } -} - -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) -{ - // if this folder is now filtered, but wasn't before - // (it just passed) - if (filtered && !mPassedFilter) - { - // reset current height, because last time we drew it - // it might have had more visible items than now - mCurHeight = 0.f; - } - - LLFolderViewItem::setFiltered(filtered, filter_generation); -} - -void LLFolderViewFolder::dirtyFilter() -{ - // we're a folder, so invalidate our completed generation - setCompletedFilterGeneration(-1, FALSE); - LLFolderViewItem::dirtyFilter(); -} - -BOOL LLFolderViewFolder::getFiltered() -{ - return getFilteredFolder(getRoot()->getFilter()->getFirstSuccessGeneration()) - && LLFolderViewItem::getFiltered(); -} - -BOOL LLFolderViewFolder::getFiltered(S32 filter_generation) -{ - return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation); -} - -BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) -{ - return mMostFilteredDescendantGeneration >= filter_generation; -} - - -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); -} // Passes selection information on to children and record selection // information if necessary. @@ -1824,39 +1417,7 @@ void LLFolderViewFolder::destroyView() folderp->destroyView(); // removes entry from mFolders } - if (mParentFolder) - { - mParentFolder->removeView(this); - } -} - -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ - if(item->remove()) - { - return TRUE; - } - return FALSE; -} - -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ - if (!item || item->getParentFolder() != this) - { - return; - } - // deselect without traversing hierarchy - if (item->isSelected()) - { - item->deselectItem(); - } - getRoot()->removeFromSelectionList(item); - extractItem(item); - delete item; + LLFolderViewItem::destroyView(); } // extractItem() removes the specified item from the folder, but @@ -1882,7 +1443,7 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) mItems.erase(it); } //item has been removed, need to update filter - dirtyFilter(); + getViewModelItem()->dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); removeChild(item); @@ -1890,31 +1451,28 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) BOOL LLFolderViewFolder::isMovable() { - if( getViewModelItem() ) + if( !(getViewModelItem()->isItemMovable()) ) { - if( !(getViewModelItem()->isItemMovable()) ) - { - return FALSE; - } + return FALSE; + } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return FALSE; - } + return FALSE; } + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return FALSE; - } + return FALSE; } } return TRUE; @@ -1923,31 +1481,28 @@ BOOL LLFolderViewFolder::isMovable() BOOL LLFolderViewFolder::isRemovable() { - if( getViewModelItem() ) + if( !(getViewModelItem()->isItemRemovable()) ) { - if( !(getViewModelItem()->isItemRemovable()) ) - { - return FALSE; - } + return FALSE; + } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return FALSE; - } + return FALSE; } + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return FALSE; - } + return FALSE; } } return TRUE; @@ -1956,6 +1511,12 @@ BOOL LLFolderViewFolder::isRemovable() // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) { + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + mItems.push_back(item); item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); @@ -1963,12 +1524,14 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) addChild(item); - item->dirtyFilter(); + item->getViewModelItem()->dirtyFilter(); // Handle sorting requestArrange(); requestSort(); + getViewModelItem()->addChild(item->getViewModelItem()); + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria //// Traverse parent folders and update creation date and resort, if necessary //LLFolderViewFolder* parentp = this; @@ -1989,16 +1552,23 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) { + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; mFolders.push_back(folder); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); addChild( folder ); - folder->dirtyFilter(); + folder->getViewModelItem()->dirtyFilter(); // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(); requestSort(); + getViewModelItem()->addChild(folder->getViewModelItem()); + return TRUE; } @@ -2027,16 +1597,13 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r { BOOL was_open = isOpen(); mIsOpen = openitem; - if (getViewModelItem()) + if(!was_open && openitem) { - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } + getViewModelItem()->openItem(); + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); } if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) @@ -2068,7 +1635,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + BOOL accepted = mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; @@ -2156,7 +1723,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = getViewModelItem() && getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { @@ -2259,7 +1826,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } else { - setSelectionFromRoot(this, FALSE); + getRoot()->setSelection(this, FALSE); toggleOpen(); } handled = TRUE; @@ -2293,16 +1860,6 @@ void LLFolderViewFolder::draw() mExpanderHighlighted = FALSE; } -BOOL LLFolderViewFolder::potentiallyVisible() -{ - // folder should be visible by it's own filter status - return LLFolderViewItem::potentiallyVisible() - // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants() - // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); -} - // this does prefix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index fd2948f34e..7e48969826 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -35,6 +35,7 @@ class LLFolderViewModelItem; class LLFolderViewFolder; class LLFolderViewFunctor; class LLFolderViewFilter; +class LLFolderViewModelInterface; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem @@ -78,8 +79,6 @@ public: static const F32 FOLDER_CLOSE_TIME_CONSTANT; static const F32 FOLDER_OPEN_TIME_CONSTANT; - const std::string& getSearchableLabel() { return mSearchableLabel; } - private: BOOL mIsSelected; @@ -90,7 +89,6 @@ protected: LLFolderViewItem(const Params& p); std::string mLabel; - std::string mSearchableLabel; S32 mLabelWidth; bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; @@ -106,8 +104,7 @@ protected: BOOL mHasVisibleChildren; S32 mIndentation; S32 mItemHeight; - BOOL mPassedFilter; - S32 mLastFilterGeneration; + //TODO RN: create interface for string highlighting //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; @@ -115,9 +112,6 @@ protected: BOOL mDragAndDropTarget; bool mIsMouseOverTitle; - // helper function to change the selection from the root. - void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); - // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } @@ -130,39 +124,20 @@ public: virtual void openItem( void ); - // This function clears the currently selected item, and records - // the specified selected item appropriately for display and use - // in the UI. If open is TRUE, then folders are opened up along - // the way to the selection. - void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // This function is called when the folder view is dirty. It's - // implemented here but called by derived classes when folding the - // views. - void arrangeFromRoot(); - void filterFromRoot( void ); - void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); virtual ~LLFolderViewItem( void ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - // updates filter serial number and optionally propagated value up to root - S32 getLastFilterGeneration() { return mLastFilterGeneration; } - - virtual void dirtyFilter(); + S32 getLastFilterGeneration() const; // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. @@ -213,8 +188,6 @@ public: // viewed. This method will ask the viewed object itself. const std::string& getName( void ) const; - const std::string& getSearchableLabel( void ) const; - // This method returns the label displayed on the view. This // method was primarily added to allow sorting on the folder // contents possible before the entire view has been constructed. @@ -224,12 +197,17 @@ public: LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } + const LLFolderViewModelInterface* getFolderViewModel( void ) const; + LLFolderViewModelInterface* getFolderViewModel( void ); + // just rename the object. void rename(const std::string& new_name); @@ -239,15 +217,11 @@ public: virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); S32 getIndentation() { return mIndentation; } - virtual BOOL potentiallyVisible(); // is the item definitely visible or we haven't made up our minds yet? - virtual BOOL potentiallyHidden(); // did this item not pass the filter or do we not know yet? - - virtual BOOL getFiltered(); - virtual BOOL getFiltered(S32 filter_generation); - virtual void setFiltered(BOOL filtered, S32 filter_generation); + virtual BOOL passedFilter(S32 filter_generation = -1); // refresh information from the object being viewed. virtual void refresh(); @@ -305,7 +279,6 @@ protected: F32 mAutoOpenCountdown; S32 mLastArrangeGeneration; S32 mLastCalculatedWidth; - S32 mCompletedFilterGeneration; S32 mMostFilteredDescendantGeneration; bool mNeedsSort; bool mPassedFolderFilter; @@ -322,8 +295,6 @@ public: virtual ~LLFolderViewFolder( void ); - virtual BOOL potentiallyVisible(); - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); @@ -332,34 +303,17 @@ public: // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 arrange( S32* width, S32* height ); BOOL needsArrange(); - virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); - virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } - - BOOL hasFilteredDescendants(S32 filter_generation); - BOOL hasFilteredDescendants(); - - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - virtual void setFiltered(BOOL filtered, S32 filter_generation); - virtual BOOL getFiltered(); - virtual BOOL getFiltered(S32 filter_generation); - - virtual void dirtyFilter(); - - // folder-specific filtering (filter status propagates top down instead of bottom up) - void filterFolder(LLFolderViewFilter& filter); - void setFilteredFolder(bool filtered, S32 filter_generation); - bool getFilteredFolder(S32 filter_generation); + bool descendantsPassedFilter(S32 filter_generation = -1); // Passes selection information on to children and record // selection information if necessary. // Returns TRUE if this object (or a child) ends up being selected. // If 'openitem' is TRUE then folders are opened up along the way to the selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); // This method is used to change the selection of an item. // Recursively traverse all children; if 'selection' is 'this' then change @@ -385,14 +339,6 @@ public: //virtual BOOL removeRecursively(BOOL single_item); //virtual BOOL remove(); - // remove the specified item (and any children) if - // possible. Return TRUE if the item was deleted. - BOOL removeItem(LLFolderViewItem* item); - - // simply remove the view (and any children) Don't bother telling - // the listeners. - void removeView(LLFolderViewItem* item); - // extractItem() removes the specified item from the folder, but // doesn't delete it. virtual void extractItem( LLFolderViewItem* item ); diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 74c8bb92ef..0216ba2a07 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -72,9 +72,9 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewItem* item) = 0; + virtual bool check(const LLFolderViewModelItem* item) = 0; virtual bool check(const LLInventoryItem* item) = 0; - virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; + virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; virtual bool checkFolder(const LLUUID& folder_id) const = 0; virtual void setEmptyLookupMessage(const std::string& message) = 0; @@ -126,6 +126,8 @@ public: virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; }; class LLFolderViewModelCommon : public LLFolderViewModelInterface @@ -152,20 +154,82 @@ protected: }; +template +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + + //TODO RN: fix this + void filter(LLFolderViewFolder* folder) + { + + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem { public: - LLFolderViewModelItem() - : mFolderViewItem(NULL) - {} - virtual ~LLFolderViewModelItem( void ) {}; virtual void update() {} //called when drawing virtual const std::string& getName() const = 0; virtual const std::string& getDisplayName() const = 0; + virtual const std::string& getSearchableName() const = 0; virtual LLPointer getIcon() const = 0; virtual LLPointer getIconOpen() const { return getIcon(); } @@ -198,12 +262,23 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + + virtual void filter( LLFolderViewFilter& filter) = 0; + virtual bool passedFilter(S32 filter_generation = -1) = 0; + virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; + virtual void dirtyFilter() = 0; + + virtual S32 getLastFilterGeneration() const = 0; + // This method should be called when a drag begins. returns TRUE // if the drag can begin, otherwise FALSE. virtual LLToolDragAndDrop::ESource getDragSource() const = 0; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; virtual bool hasChildren() const = 0; + virtual void addChild(LLFolderViewModelItem* child) = 0; // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is @@ -217,10 +292,12 @@ public: virtual void requestSort() = 0; virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; + virtual void setParent(LLFolderViewModelItem* parent) = 0; + protected: + friend class LLFolderViewItem; - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} - LLFolderViewItem* mFolderViewItem; + virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; }; @@ -228,95 +305,48 @@ class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: LLFolderViewModelItemCommon() - : mSortVersion(-1) + : mSortVersion(-1), + mPassedFilter(false), + mPassedFolderFilter(false), + mFolderViewItem(NULL), + mLastFilterGeneration(-1), + mMostFilteredDescendantGeneration(-1) {} void requestSort() { mSortVersion = -1; } S32 getSortVersion() { return mSortVersion; } void setSortVersion(S32 version) { mSortVersion = version;} -protected: - - S32 mSortVersion; -}; - -template -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - virtual FilterType& getFilter() { return mFilter; } - virtual const FilterType& getFilter() const { return mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - struct ViewModelCompare + S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + void dirtyFilter() { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + mLastFilterGeneration = -1; + // bubble up dirty flag all the way to root + if (mParent) { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + mParent->dirtyFilter(); } + } + virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); child->setParent(this); } - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } +protected: + virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - const SortType& mSorter; - }; + S32 mSortVersion; + bool mPassedFilter; + bool mPassedFolderFilter; - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } + S32 mLastFilterGeneration; + S32 mMostFilteredDescendantGeneration; - //TODO RN: fix this - void filter(LLFolderViewFolder* folder) - { - /*FilterType& filter = getFilter(); - for (std::list::const_iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_item = *it; - child_item->setFiltered(filter.checkFolder(static_cast(child_item->getViewModelItem())), filter.getCurrentGeneration()); - } - for (std::list::const_iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); - it != end_it; - ++it) - { - LLFolderViewItem* child_folder = *it; - child_folder->setFiltered(filter.check(static_cast(child_folder->getViewModelItem())), filter.getCurrentGeneration()); - }*/ - } + typedef std::list child_list_t; + child_list_t mChildren; + LLFolderViewModelItem* mParent; -protected: - SortType mSorter; - FilterType mFilter; + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; }; + #endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 70a174a140..45a2bffa6b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1545,6 +1545,10 @@ void LLItemBridge::buildDisplayName() const { mDisplayName.assign(LLStringUtil::null); } + + mSearchableName.assign(mDisplayName); + mSearchableName.append(getLabelSuffix()); + LLStringUtil::toUpper(mSearchableName); } LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const @@ -1850,11 +1854,9 @@ void LLFolderBridge::buildDisplayName() const LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); } - //if (mDisplayName.empty()) - //{ - // S32 foo; - // foo = 0; - //} + mSearchableName.assign(mDisplayName); + mSearchableName.append(getLabelSuffix()); + LLStringUtil::toUpper(mSearchableName); } @@ -4000,7 +4002,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; - accept = filter->check(fv_item); + accept = filter->check(fv_item->getViewModelItem()); } if (accept && drop) @@ -4222,7 +4224,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; - accept = filter->check(fv_item); + accept = filter->check(fv_item->getViewModelItem()); } if (accept && drop) @@ -4319,7 +4321,7 @@ bool check_item(const LLUUID& item_id, LLFolderViewItem* fv_item = active_panel->getItemByID(item_id); if (!fv_item) return false; - return filter->check(fv_item); + return filter->check(fv_item->getViewModelItem()); } // +=================================================+ @@ -6126,7 +6128,7 @@ void LLLinkFolderBridge::gotoItem() model->fetchDescendentsOf(cat_uuid); } base_folder->setOpen(TRUE); - mRoot->setSelectionFromRoot(base_folder,TRUE); + mRoot->setSelection(base_folder,TRUE); mRoot->scrollToShowSelection(); } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 26789627f7..b0582d003d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -88,6 +88,8 @@ public: //-------------------------------------------------------------------- virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; + const std::string& getSearchableName() const { return mSearchableName; } + virtual PermissionMask getPermissionMask() const; virtual LLFolderType::EType getPreferredType() const; virtual time_t getCreationDate() const; @@ -174,6 +176,7 @@ protected: bool mIsLink; LLTimer mTimeSinceRequestStart; mutable std::string mDisplayName; + mutable std::string mSearchableName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); virtual void buildDisplayName() const {} diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c13bb5123e..c7e0136368 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -71,35 +71,35 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) mFilterOps(p.filter_ops), mOrder(p.sort_order), mFilterSubString(p.substring), - mLastSuccessGeneration(0), - mLastFailGeneration(S32_MAX), + mCurrentGeneration(0), + mFirstRequiredGeneration(0), mFirstSuccessGeneration(0), mFilterCount(0) { - mNextFilterGeneration = mLastSuccessGeneration + 1; + mNextFilterGeneration = mCurrentGeneration + 1; // copy mFilterOps into mDefaultFilterOps markDefault(); } -bool LLInventoryFilter::check(const LLFolderViewItem* item) +bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { + const LLFolderViewModelItemInventory* listener = static_cast(item); // Clipboard cut items are *always* filtered so we need this value upfront - const LLFolderViewModelItemInventory* listener = static_cast(item->getViewModelItem()); const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. - const BOOL is_folder = (dynamic_cast(item) != NULL); + const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { return passed_clipboard; } - std::string::size_type string_offset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; - const BOOL passed_filtertype = checkAgainstFilterType(item); - const BOOL passed_permissions = checkAgainstPermissions(item); - const BOOL passed_filterlink = checkAgainstFilterLinks(item); + const BOOL passed_filtertype = checkAgainstFilterType(listener); + const BOOL passed_permissions = checkAgainstPermissions(listener); + const BOOL passed_filterlink = checkAgainstFilterLinks(listener); const BOOL passed = (passed_filtertype && passed_permissions && passed_filterlink && @@ -117,27 +117,19 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed_permissions = checkAgainstPermissions(item); const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); const bool passed = (passed_filtertype - && passed_permissions - && passed_clipboard - && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); + && passed_permissions + && passed_clipboard + && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const { - if (!folder) - { - llwarns << "The filter can not be checked on an invalid folder." << llendl; - llassert(false); // crash in development builds - return false; - } - - const LLFolderViewModelItemInventory* listener = static_cast(folder->getViewModelItem()); + const LLFolderViewModelItemInventory* listener = static_cast(item); if (!listener) { - llwarns << "Folder view event listener not found." << llendl; - llassert(false); // crash in development builds + llerrs << "Folder view event listener not found." << llendl; return false; } @@ -179,9 +171,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return passed_clipboard; } -bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast(item->getViewModelItem()); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -347,13 +338,12 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const return true; } -bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast(item->getViewModelItem()); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); - const LLInvFVBridge *bridge = dynamic_cast(item->getViewModelItem()); + const LLInvFVBridge *bridge = dynamic_cast(listener); if (bridge && bridge->isLink()) { const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +365,8 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } -bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const { - const LLFolderViewModelItemInventory* listener = static_cast(item->getViewModelItem()); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -740,7 +729,7 @@ void LLInventoryFilter::resetDefault() void LLInventoryFilter::setModified(EFilterModified behavior) { mFilterText.clear(); - mLastSuccessGeneration = mNextFilterGeneration++; + mCurrentGeneration = mNextFilterGeneration++; if (mFilterModified == FILTER_NONE) { @@ -753,33 +742,21 @@ void LLInventoryFilter::setModified(EFilterModified behavior) mFilterModified = FILTER_RESTART; } - if (isNotDefault()) - { - // if not keeping current filter results, update last valid as well - switch(mFilterModified) - { - case FILTER_RESTART: - mLastFailGeneration = mLastSuccessGeneration; - mFirstSuccessGeneration = mLastSuccessGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mLastFailGeneration = mLastSuccessGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mFirstSuccessGeneration = mLastSuccessGeneration; - // must have passed either current filter generation (meaningless, as it hasn't been run yet) - // or some older generation, so keep the value - mLastFailGeneration = llmin(mLastFailGeneration, mLastSuccessGeneration); - break; - default: - llerrs << "Bad filter behavior specified" << llendl; - } - } - else + // if not keeping current filter results, update last valid as well + switch(mFilterModified) { - // shortcut disabled filters to show everything immediately - mLastFailGeneration = 0; - mFirstSuccessGeneration = S32_MAX; + case FILTER_RESTART: + mFirstRequiredGeneration = mCurrentGeneration; + mFirstSuccessGeneration = mCurrentGeneration; + break; + case FILTER_LESS_RESTRICTIVE: + mFirstRequiredGeneration = mCurrentGeneration; + break; + case FILTER_MORE_RESTRICTIVE: + mFirstSuccessGeneration = mCurrentGeneration; + break; + default: + llerrs << "Bad filter behavior specified" << llendl; } } @@ -1101,7 +1078,7 @@ void LLInventoryFilter::decrementFilterCount() S32 LLInventoryFilter::getCurrentGeneration() const { - return mLastSuccessGeneration; + return mCurrentGeneration; } S32 LLInventoryFilter::getFirstSuccessGeneration() const { @@ -1109,7 +1086,7 @@ S32 LLInventoryFilter::getFirstSuccessGeneration() const } S32 LLInventoryFilter::getFirstRequiredGeneration() const { - return mLastFailGeneration; + return mFirstRequiredGeneration; } void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 5b92c21a85..af245a9c3b 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -186,16 +186,10 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - bool check(const LLFolderViewItem* item); + bool check(const LLFolderViewModelItem* listener); bool check(const LLInventoryItem* item); - bool checkFolder(const LLFolderViewFolder* folder) const; + bool checkFolder(const LLFolderViewModelItem* listener) const; bool checkFolder(const LLUUID& folder_id) const; - bool checkAgainstFilterType(const LLFolderViewItem* item) const; - bool checkAgainstFilterType(const LLInventoryItem* item) const; - bool checkAgainstPermissions(const LLFolderViewItem* item) const; - bool checkAgainstPermissions(const LLInventoryItem* item) const; - bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; - bool checkAgainstClipboard(const LLUUID& object_id) const; bool showAllResults() const; @@ -260,6 +254,12 @@ public: private: bool areDateLimitsSet(); + bool checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstFilterType(const LLInventoryItem* item) const; + bool checkAgainstPermissions(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstPermissions(const LLInventoryItem* item) const; + bool checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstClipboard(const LLUUID& object_id) const; U32 mOrder; @@ -270,8 +270,8 @@ private: std::string mFilterSubStringOrig; const std::string mName; - S32 mLastSuccessGeneration; - S32 mLastFailGeneration; + S32 mCurrentGeneration; + S32 mFirstRequiredGeneration; S32 mFirstSuccessGeneration; S32 mNextFilterGeneration; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1e494c3ef1..ff461236a2 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -983,7 +983,7 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) { - if (item->getFiltered()) + if (item->passedFilter()) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } @@ -991,12 +991,12 @@ void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) { - if (folder->getFiltered() && folder->getParentFolder()) + if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder()) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } // if this folder didn't pass the filter, and none of its descendants did - else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) + else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter()) { folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); } @@ -1004,7 +1004,7 @@ void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) { - if (item->getFiltered() && !mItemSelected) + if (item->passedFilter() && !mItemSelected) { item->getRoot()->setSelection(item, FALSE, FALSE); if (item->getParentFolder()) @@ -1017,7 +1017,7 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) { - if (folder->getFiltered() && !mItemSelected) + if (folder->LLFolderViewItem::passedFilter() && !mItemSelected) { folder->getRoot()->setSelection(folder, FALSE, FALSE); if (folder->getParentFolder()) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 74492e0005..aba4c088ab 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -254,18 +254,16 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // Scroller - { - LLRect scroller_view_rect = getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params scroller_params(params.scroll()); - scroller_params.rect(scroller_view_rect); - mScroller = LLUICtrlFactory::create(scroller_params); - addChild(mScroller); - mScroller->addChild(mFolderRoot); - mFolderRoot->setScrollContainer(mScroller); - mFolderRoot->setFollowsAll(); - mFolderRoot->addChild(mFolderRoot->mStatusTextBox); - } + LLRect scroller_view_rect = getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(params.scroll()); + scroller_params.rect(scroller_view_rect); + mScroller = LLUICtrlFactory::create(scroller_params); + addChild(mScroller); + mScroller->addChild(mFolderRoot); + mFolderRoot->setScrollContainer(mScroller); + mFolderRoot->setFollowsAll(); + mFolderRoot->addChild(mFolderRoot->mStatusTextBox); // Set up the callbacks from the inventory we're viewing, and then build everything. mInventoryObserver = new LLInventoryPanelObserver(this); @@ -344,12 +342,12 @@ void LLInventoryPanel::draw() const LLInventoryFilter* LLInventoryPanel::getFilter() const { - return &getFolderViewModel()->getFilter(); + return getFolderViewModel()->getFilter(); } LLInventoryFilter* LLInventoryPanel::getFilter() { - return &getFolderViewModel()->getFilter(); + return getFolderViewModel()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -561,7 +559,6 @@ void LLInventoryPanel::modelChanged(U32 mask) if (new_parent != NULL) { // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. - view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent); addItemID(viewmodel_item->getUUID(), view_item); } @@ -1358,3 +1355,104 @@ void LLFolderViewModelItemInventory::requestSort() mFolderViewItem->getParentFolder()->getViewModelItem()->requestSort(); } } + +bool LLFolderViewModelItemInventory::potentiallyVisible() +{ + return passedFilter() // we've passed the filter + || getLastFilterGeneration() < mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || descendantsPassedFilter(); +} + +bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + return mPassedFolderFilter + && mLastFilterGeneration >= filter_generation + && (mPassedFilter || descendantsPassedFilter(filter_generation)); +} + +bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + return mMostFilteredDescendantGeneration >= filter_generation; +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +{ + mPassedFilter = passed; + mPassedFolderFilter = passed_folder; + mLastFilterGeneration = filter_generation; +} + +void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ + S32 filter_generation = filter.getCurrentGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + // mMostFilteredDescendantGeneration might have been reset + // in which case we need to update it even for folders that + // don't need to be filtered anymore + if (item->getLastFilterGeneration() < filter_generation) + { + if (item->getLastFilterGeneration() >= must_pass_generation && + !item->passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + item->setPassedFilter(false, false, filter_generation); + } + else + { + //TODO RN: + item->filter( filter ); + } + } + + // track latest generation to pass any child items + if (item->passedFilter()) + { + mMostFilteredDescendantGeneration = filter_generation; + //TODO RN: ensure this still happens + //requestArrange(); + } +} + +void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ + if(getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration())) // or at least one descendant has passed the minimum requirement + { + // now query children + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end() && filter.getFilterCount() > 0; + ++iter) + { + filterChildItem((*iter), filter); + } + } + + // if we didn't use all filter iterations + // that means we filtered all of our descendants + // so filter ourselves now + if (filter.getFilterCount() > 0) + { + const BOOL previous_passed_filter = mPassedFilter; + const BOOL passed_filter = filter.check(this); + const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) + ? filter.checkFolder(this) + : true; + + // If our visibility will change as a result of this filter, then + // we need to be rearranged in our parent folder + LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); + if (parent_folder && passed_filter != previous_passed_filter) + { + parent_folder->requestArrange(); + } + + setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); + filter.decrementFilterCount(); + } +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 645e2f6d76..35a3f9b5e1 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -62,6 +62,12 @@ public: virtual EInventorySortGroup getSortGroup() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0; virtual void requestSort(); + virtual bool potentiallyVisible(); + virtual bool passedFilter(S32 filter_generation = -1); + virtual bool descendantsPassedFilter(S32 filter_generation = -1); + virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); + virtual void filter( LLFolderViewFilter& filter); + virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); }; class LLInventorySort diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 901c6379de..0b899d34f4 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) // Counting only folders that pass the filter. // The listener check allow us to avoid counting the folder view // object itself because it has no listener assigned. - if (folder->hasFilteredDescendants() && folder->getViewModelItem()) + if (folder->getViewModelItem()->descendantsPassedFilter()) { if (folder->isOpen()) { diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e3446fdb3a..33581160fd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -227,7 +227,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) } } - LLInventoryFilter* filter = getChild("Recent Items")->getFilter(); + LLInventoryFilter* filter = findChild("Recent Items")->getFilter(); if (filter) { LLSD filterState; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index da82d70f22..6a232a26f7 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -77,6 +77,7 @@ protected: LLUUID mUUID; std::string mName; mutable std::string mDisplayName; + mutable std::string mSearchableName; LLPanelObjectInventory* mPanel; U32 mFlags; LLAssetType::EType mAssetType; @@ -105,6 +106,8 @@ public: // LLFolderViewModelItemInventory functionality virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; + virtual const std::string& getSearchableName() const; + virtual PermissionMask getPermissionMask() const { return PERM_NONE; } /*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } virtual const LLUUID& getUUID() const { return mUUID; } @@ -335,9 +338,17 @@ const std::string& LLTaskInvFVBridge::getDisplayName() const } } + mSearchableName.assign(mDisplayName + getLabelSuffix()); + return mDisplayName; } +const std::string& LLTaskInvFVBridge::getSearchableName() const +{ + return mSearchableName; +} + + // BUG: No creation dates for task inventory time_t LLTaskInvFVBridge::getCreationDate() const { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 194aa7f71b..b143240187 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -271,7 +271,7 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked() if (outfit_folder) { outfit_folder->setOpen(!outfit_folder->isOpen()); - root->setSelectionFromRoot(outfit_folder,TRUE); + root->setSelection(outfit_folder,TRUE); root->scrollToShowSelection(); } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 50d63911ad..654b18614a 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -623,10 +623,9 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = static_cast(folder_view->getFilter()); - if (!filter) return; + LLInventoryFilter* filter = static_cast(folder_view->getFolderViewModel())->getFilter(); - bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && + bool is_filter_active = folder_view->getLastFilterGeneration() < filter->getCurrentGeneration() && filter->isNotDefault(); // After inventory panel filter is applied we have to update @@ -637,8 +636,9 @@ void LLFloaterTexturePicker::draw() if (!is_filter_active && !mSelectedItemPinned) { folder_view->setPinningSelectedItem(mSelectedItemPinned); - folder_view->dirtyFilter(); - folder_view->arrangeFromRoot(); + folder_view->getViewModelItem()->dirtyFilter(); + //TODO RN: test + //folder_view->arrangeFromRoot(); mSelectedItemPinned = TRUE; } -- cgit v1.2.3 From 569c004057ef5da03e05bedf77d39159e5782458 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 27 Jun 2012 19:17:49 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed crash on startup --- indra/newview/llfolderviewmodel.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 0216ba2a07..c5079712f5 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -310,7 +310,8 @@ public: mPassedFolderFilter(false), mFolderViewItem(NULL), mLastFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1) + mMostFilteredDescendantGeneration(-1), + mParent(NULL) {} void requestSort() { mSortVersion = -1; } -- cgit v1.2.3 From e8fa07d6384c9eb2a0fb42b0e06abb6a0d5fdea9 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 28 Jun 2012 16:47:37 -0700 Subject: CHUI-82 : Fixed all icons to use the new Conv_*.png icons; please use those in the new UIs moving forward --- .../textures/icons/Conv_toolbar_add_person.png | Bin 0 -> 322 bytes .../textures/icons/Conv_toolbar_arrow_ne.png | Bin 0 -> 301 bytes .../textures/icons/Conv_toolbar_arrow_sw.png | Bin 0 -> 293 bytes .../textures/icons/Conv_toolbar_call_log.png | Bin 0 -> 546 bytes .../default/textures/icons/Conv_toolbar_close.png | Bin 0 -> 262 bytes .../textures/icons/Conv_toolbar_collapse.png | Bin 0 -> 663 bytes .../default/textures/icons/Conv_toolbar_expand.png | Bin 0 -> 662 bytes .../textures/icons/Conv_toolbar_hang_up.png | Bin 0 -> 460 bytes .../textures/icons/Conv_toolbar_open_call.png | Bin 0 -> 485 bytes .../default/textures/icons/Conv_toolbar_plus.png | Bin 0 -> 195 bytes .../default/textures/icons/Conv_toolbar_sort.png | Bin 0 -> 196 bytes indra/newview/skins/default/textures/textures.xml | 14 ++++++++ .../skins/default/xui/en/floater_im_container.xml | 10 +++--- .../skins/default/xui/en/floater_im_session.xml | 36 ++++++++++----------- .../default/xui/en/panel_block_list_sidetray.xml | 2 +- .../newview/skins/default/xui/en/panel_people.xml | 8 ++--- 16 files changed, 42 insertions(+), 28 deletions(-) create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_close.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png create mode 100755 indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png new file mode 100755 index 0000000000..f024c733f3 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png new file mode 100755 index 0000000000..a19e720d42 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png new file mode 100755 index 0000000000..7f3f42639d Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png new file mode 100755 index 0000000000..2880eb766a Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png new file mode 100755 index 0000000000..25a939d7f5 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png new file mode 100755 index 0000000000..82baabde47 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png new file mode 100755 index 0000000000..7d64abb042 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png new file mode 100755 index 0000000000..f0da962c2d Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png new file mode 100755 index 0000000000..0db001dcdb Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png new file mode 100755 index 0000000000..0cf7edc2d4 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png differ diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png new file mode 100755 index 0000000000..a0c15a6d3e Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index eabcc68916..ce9474d5e5 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -160,7 +160,21 @@ with the same filename but different name + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index ce40f44a64..8e434b5848 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -15,10 +15,10 @@ width="680"> + value="Conv_toolbar_collapse"/> + value="Conv_toolbar_expand"/> - VoicePTT_Off - VoicePTT_On + Conv_toolbar_open_call + Conv_toolbar_hang_up + value="Conv_toolbar_collapse"/> + value="Conv_toolbar_expand"/> + value="Conv_toolbar_arrow_ne"/> + value="Conv_toolbar_arrow_sw"/> Date: Fri, 29 Jun 2012 11:59:14 -0700 Subject: CHUI-164 : Fix crash when removing ad-hoc conversation. Turns out that sessions uuids are not constant so I shouldn't use them as index in the conversation list. More complete fix to follow. --- indra/newview/llimconversation.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 34 ++++++++++++++++++++-------------- indra/newview/llimfloatercontainer.h | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c734c3edd2..d7ef65edb6 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -359,7 +359,7 @@ void LLIMConversation::onClose(bool app_quitting) LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (im_box) { - im_box->removeConversationListItem(mSessionID); + im_box->removeConversationListItem(mSessionID,this); } } } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 34a9758c52..85cc8cf38b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -416,19 +416,14 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Check if the item has changed if (item->hasSameValues(name,floaterp)) { - // If it hasn't, nothing to do -> exit + // If it hasn't changed, nothing to do -> exit return; } - // If it has, remove it: it'll be recreated anew further down - removeConversationListItem(uuid,false); } - // Reverse find and clean up: we need to make sure that no other uuid is pointing to that same floater - LLUUID found_id = LLUUID::null; - if (findConversationItem(floaterp,found_id)) - { - removeConversationListItem(found_id,false); - } + // Remove the conversation item that might exist already: it'll be recreated anew further down anyway + // and nothing wrong will happen removing it if it doesn't exist + removeConversationListItem(uuid,floaterp,false); // Create a conversation item LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); @@ -451,21 +446,32 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, bool change_focus) +void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus) { + // Reverse find : we need to find the item that point to that floater + // Note : the session UUID actually might change so we cannot really use it here + // *TODO : Change the structure so that we use the floaterp and not the uuid as a map index + LLUUID found_id = LLUUID::null; + if (!findConversationItem(floaterp,found_id)) + { + // If the floater wasn't found, we trust the passed id + // Note: in most cases, the id doesn't correspond to any conversation either + found_id = session_id; + } + // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(session_id); + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(found_id); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; delete widget; } - + // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(session_id); - mConversationsWidgets.erase(session_id); + mConversationsItems.erase(found_id); + mConversationsWidgets.erase(found_id); // Reposition the leftover conversation items LLRect panel_rect = mConversationsListPanel->getRect(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2a8cbf3e1c..181aaa38a8 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -186,7 +186,7 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id, bool change_focus = true); + void removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); private: -- cgit v1.2.3 From 5eab95955fec4d3dcb8b2f98c6c084d227e70b8c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 29 Jun 2012 14:29:56 -0700 Subject: CHUI-164 : Fix conversation list index using handle to floater rather than uuid. Simplify the code accordingly (suppress hacks). --- indra/newview/llimconversation.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 48 +++++++++++++--------------------- indra/newview/llimfloatercontainer.h | 12 ++++----- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d7ef65edb6..dc68c5cea1 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -359,7 +359,7 @@ void LLIMConversation::onClose(bool app_quitting) LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); if (im_box) { - im_box->removeConversationListItem(mSessionID,this); + im_box->removeConversationListItem(this); } } } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 85cc8cf38b..261b5f33a2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -293,9 +293,9 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is null - conversations_items_map::iterator item_it = mConversationsItems.find(nearbychat_uuid); - if (item_it == mConversationsItems.end()) + LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is always null + LLFloater* floaterp = findConversationItem(nearbychat_uuid); + if (floaterp == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that @@ -407,14 +407,14 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { - // Check if the item is not already in the list, exit if it is and has the same name and points to the same floater (nothing to do) + // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance - conversations_items_map::iterator item_it = mConversationsItems.find(uuid); + conversations_items_map::iterator item_it = mConversationsItems.find(floaterp); if (item_it != mConversationsItems.end()) { LLConversationItem* item = item_it->second; // Check if the item has changed - if (item->hasSameValues(name,floaterp)) + if (item->hasSameValues(name,uuid)) { // If it hasn't changed, nothing to do -> exit return; @@ -423,15 +423,15 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Remove the conversation item that might exist already: it'll be recreated anew further down anyway // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,floaterp,false); + removeConversationListItem(floaterp,false); // Create a conversation item LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); - mConversationsItems[uuid] = item; + mConversationsItems[floaterp] = item; // Create a widget from it LLFolderViewItem* widget = createConversationItemWidget(item); - mConversationsWidgets[uuid] = widget; + mConversationsWidgets[floaterp] = widget; // Add it to the UI widget->setVisible(TRUE); @@ -446,23 +446,12 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus) +void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool change_focus) { - // Reverse find : we need to find the item that point to that floater - // Note : the session UUID actually might change so we cannot really use it here - // *TODO : Change the structure so that we use the floaterp and not the uuid as a map index - LLUUID found_id = LLUUID::null; - if (!findConversationItem(floaterp,found_id)) - { - // If the floater wasn't found, we trust the passed id - // Note: in most cases, the id doesn't correspond to any conversation either - found_id = session_id; - } - // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener - conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(found_id); + conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(floaterp); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; @@ -470,8 +459,8 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, } // Suppress the conversation items and widgets from their respective maps - mConversationsItems.erase(found_id); - mConversationsWidgets.erase(found_id); + mConversationsItems.erase(floaterp); + mConversationsWidgets.erase(floaterp); // Reposition the leftover conversation items LLRect panel_rect = mConversationsListPanel->getRect(); @@ -500,20 +489,19 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& session_id, return; } -bool LLIMFloaterContainer::findConversationItem(LLFloater* floaterp, LLUUID& uuid) +LLFloater* LLIMFloaterContainer::findConversationItem(LLUUID& uuid) { - bool found = false; + LLFloater* floaterp = NULL; for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) { LLConversationItem* item = item_it->second; - uuid = item_it->first; - if (item->hasSameValue(floaterp)) + if (item->hasSameValue(uuid)) { - found = true; + floaterp = item_it->first; break; } } - return found; + return floaterp; } LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 181aaa38a8..2bbd371e8f 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -48,8 +48,8 @@ class LLIMFloaterContainer; // CHUI-137 : Temporary implementation of conversations list class LLConversationItem; -typedef std::map conversations_items_map; -typedef std::map conversations_widgets_map; +typedef std::map conversations_items_map; +typedef std::map conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. @@ -113,8 +113,8 @@ public: void* cargo_data, std::string& tooltip_msg) { return FALSE; } - bool hasSameValues(std::string name, LLFloater* floaterp) { return ((name == mName) && (floaterp == mFloater)); } - bool hasSameValue(LLFloater* floaterp) { return (floaterp == mFloater); } + bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } private: std::string mName; const LLUUID mUUID; @@ -186,9 +186,9 @@ private: // CHUI-137 : Temporary implementation of conversations list public: - void removeConversationListItem(const LLUUID& session_id, LLFloater* floaterp, bool change_focus = true); + void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); - bool findConversationItem(LLFloater* floaterp, LLUUID& uuid); + LLFloater* findConversationItem(LLUUID& uuid); private: LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data -- cgit v1.2.3 From cd7d499ea779178d49be65d37e852712f82c3c90 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 28 Jun 2012 17:22:00 +0300 Subject: CHUI-168 FIXED, CHUI-183 FIXED Supress of a resizable and dragging and hide a title for the docked floater --- indra/newview/llimconversation.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index dc68c5cea1..acdd7ba46a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -250,14 +250,16 @@ void LLIMConversation::updateHeaderAndToolbar() bool is_expanded = is_hosted || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); - // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); - + // toggle floater's drag handle and title visibility if (mDragHandle) { - // toggle floater's drag handle and title visibility - mDragHandle->setVisible(!is_hosted); + mDragHandle->setTitleVisible(!is_hosted); + setCanDrag(!is_hosted); } + setCanResize(!is_hosted); + + // The button (>>) should be disabled for torn off P2P conversations. + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); @@ -347,6 +349,8 @@ void LLIMConversation::onOpen(const LLSD& key) host_floater->collapseMessagesPane(false); } + setCanResize(TRUE); + updateHeaderAndToolbar(); } -- cgit v1.2.3 From 14fef9f08a3bfb44d94771be6478a57ed9a91540 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Thu, 28 Jun 2012 11:05:32 -0400 Subject: SH-3230 Disable texture readback & upload If we're utilizing server-side texture baking, upload requests are discarded. Note: this breaks viewer in that it will *always* use the baked textures sent by the cache request/ initial login. Without a server-generated update, you will see those textures on your avatar for the entire session, even if you switch outfits. --- indra/newview/llvoavatarself.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0bfd0df769..ee3381a5ad 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -887,7 +887,10 @@ void LLVOAvatarSelf::removeMissingBakedTextures() invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE); } updateMeshTextures(); - requestLayerSetUploads(); + if (!LLAppearanceMgr::instance().useServerTextureBaking()) + { + requestLayerSetUploads(); + } } } @@ -1630,7 +1633,7 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_r layerset->requestUpdate(); layerset->invalidateMorphMasks(); - if( upload_result ) + if( upload_result && !LLAppearanceMgr::instance().useServerTextureBaking()) { llassert(isSelf()); -- cgit v1.2.3 From e4a0dda457039b1a04c74024d9fbcf02e071b13d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 28 Jun 2012 14:24:04 -0400 Subject: SH-3228 WIP - always respond to processAppearance for self, convert baked textures to checkerboards --- indra/llcommon/imageids.cpp | 3 +++ indra/llcommon/imageids.h | 1 + indra/llprimitive/llprimitive.cpp | 17 +++++++++++++---- indra/llprimitive/llprimitive.h | 4 ++-- indra/newview/llvoavatar.cpp | 4 ++-- indra/newview/llvoavatarself.cpp | 2 +- indra/newview/llvovolume.cpp | 2 +- 7 files changed, 23 insertions(+), 10 deletions(-) mode change 100644 => 100755 indra/llcommon/imageids.cpp mode change 100644 => 100755 indra/llcommon/imageids.h mode change 100644 => 100755 indra/llprimitive/llprimitive.h diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp old mode 100644 new mode 100755 index fe11465221..7d647e5c36 --- a/indra/llcommon/imageids.cpp +++ b/indra/llcommon/imageids.cpp @@ -68,3 +68,6 @@ const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); / const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER + +const LLUUID IMG_CHECKERBOARD_RGBA ("2585a0f3-4163-6dd1-0f34-ad48cb909e25"); // dataserver + diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h old mode 100644 new mode 100755 index e0c2683fdc..18c8ecb074 --- a/indra/llcommon/imageids.h +++ b/indra/llcommon/imageids.h @@ -66,4 +66,5 @@ LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL; LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL; +LL_COMMON_API extern const LLUUID IMG_CHECKERBOARD_RGBA; #endif diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 30532247ac..c766d8a43c 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -39,6 +39,7 @@ #include "lldatapacker.h" #include "llsdutil_math.h" #include "llprimtexturelist.h" +#include "imageids.h" /** * exported constants @@ -1227,12 +1228,12 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const return FALSE; } -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name) +S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, bool fake_images) { - return(unpackTEMessage(mesgsys,block_name,-1)); + return(unpackTEMessage(mesgsys,block_name,-1,fake_images)); } -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num) +S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images) { // use a negative block_num to indicate a single-block read (a non-variable block) S32 retval = 0; @@ -1307,7 +1308,15 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam LLColor4U coloru; for (U32 i = 0; i < face_count; i++) { - retval |= setTETexture(i, ((LLUUID*)image_data)[i]); + LLUUID& req_id = ((LLUUID*)image_data)[i]; + if (fake_images & (req_id != IMG_DEFAULT) && (req_id != IMG_DEFAULT_AVATAR) && (req_id != IMG_INVISIBLE)) + { + retval |= setTETexture(i, IMG_CHECKERBOARD_RGBA); + } + else + { + retval |= setTETexture(i, req_id); + } retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h old mode 100644 new mode 100755 index 998016f8f6..1e985221c0 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -360,8 +360,8 @@ public: S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name); - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, bool fake_images = false); + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images = false); // Variable num of blocks BOOL unpackTEMessage(LLDataPacker &dp); #ifdef CHECK_FOR_FINITE diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d2247ed5cb..531d3b4940 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7283,7 +7283,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) if( isSelf() ) { llwarns << avString() << "Received AvatarAppearance for self" << llendl; - if( mFirstTEMessageReceived ) + if( mFirstTEMessageReceived && !LLAppearanceMgr::instance().useServerTextureBaking()) { // llinfos << "processAvatarAppearance end " << mID << llendl; return; @@ -7294,7 +7294,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData); + unpackTEMessage(mesgsys, _PREHASH_ObjectData, LLAppearanceMgr::instance().useServerTextureBaking()); // dumpAvatarTEs( "POST processAvatarAppearance()" ); // prevent the overwriting of valid baked textures with invalid baked textures diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0bfd0df769..585a116acb 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -814,7 +814,7 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, updateMeshTextures(); // unpack the texture UUIDs to the texture slots - retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); // need to trigger a few operations to get the avatar to use the new bakes for (U32 i = 0; i < mBakedTextureDatas.size(); i++) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b5d173346e..4999f680df 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -370,7 +370,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // Unpack texture entry data // - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); if (result & teDirtyBits) { updateTEData(); -- cgit v1.2.3 From ed7173c987cf4a5de2f3c9b9d792e5ac4006e833 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 28 Jun 2012 23:29:58 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose filtering mostly working --- indra/newview/llfolderview.cpp | 124 ++++++++++----------- indra/newview/llfolderviewitem.cpp | 5 +- indra/newview/llinventorybridge.cpp | 47 ++++---- indra/newview/llinventorybridge.h | 3 + indra/newview/llinventorypanel.cpp | 37 ++++-- indra/newview/llinventorypanel.h | 18 ++- indra/newview/llpanelmarketplaceinboxinventory.cpp | 1 + .../newview/llpanelmarketplaceoutboxinventory.cpp | 1 + indra/newview/llplacesinventorybridge.cpp | 5 + indra/newview/llplacesinventorybridge.h | 1 + indra/newview/llplacesinventorypanel.cpp | 1 + 11 files changed, 135 insertions(+), 108 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index a37fc7714b..0f7809d4b4 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -182,7 +182,6 @@ LLFolderView::LLFolderView(const Params& p) mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter(new LLInventoryFilter(LLInventoryFilter::Params().name(p.title))), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -288,9 +287,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - delete mFilter; - mFilter = NULL; - delete mViewModel; mViewModel = NULL; } @@ -302,6 +298,9 @@ BOOL LLFolderView::canFocusChildren() const BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { + LLFolderViewFolder::addFolder(folder); + + mFolders.remove(folder); // enforce sort order of My Inventory followed by Library if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) { @@ -311,12 +310,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->getViewModelItem()->dirtyFilter(); - folder->requestArrange(); + return TRUE; } @@ -717,7 +711,7 @@ void LLFolderView::draw() } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || getLastFilterGeneration() < mFilter->getFirstSuccessGeneration()) + if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) { // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); @@ -952,37 +946,36 @@ void LLFolderView::openSelectedItems( void ) { if(getVisible() && getEnabled()) { - // TODO RN: move to LLFolderViewModelInventory - //if (mSelectedItems.size() == 1) - //{ - // mSelectedItems.front()->openItem(); - //} - //else - //{ - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // (*item_it)->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - //} + if (mSelectedItems.size() == 1) + { + mSelectedItems.front()->openItem(); + } + else + { + LLMultiPreview* multi_previewp = new LLMultiPreview(); + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + // IT_{OBJECT,ATTACHMENT} creates LLProperties + // floaters; others create LLPreviews. Put + // each one in the right type of container. + LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); + bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + if (is_prop) + LLFloater::setFloaterHost(multi_propertiesp); + else + LLFloater::setFloaterHost(multi_previewp); + listener->openItem(); + } + + LLFloater::setFloaterHost(NULL); + // *NOTE: LLMulti* will safely auto-delete when open'd + // without any children. + multi_previewp->openFloater(LLSD()); + multi_propertiesp->openFloater(LLSD()); + } } } @@ -990,28 +983,27 @@ void LLFolderView::propertiesSelectedItems( void ) { if(getVisible() && getEnabled()) { - // TODO RN: move to LLFolderViewModelInventory - //if (mSelectedItems.size() == 1) - //{ - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - //} - //else - //{ - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + if (mSelectedItems.size() == 1) + { + LLFolderViewItem* folder_item = mSelectedItems.front(); + if(!folder_item) return; + folder_item->getViewModelItem()->showProperties(); + } + else + { + LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - // LLFloater::setFloaterHost(multi_propertiesp); + LLFloater::setFloaterHost(multi_propertiesp); - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + (*item_it)->getViewModelItem()->showProperties(); + } - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - //} + LLFloater::setFloaterHost(NULL); + multi_propertiesp->openFloater(LLSD()); + } } } @@ -1943,11 +1935,11 @@ void LLFolderView::doIdle() LLFastTimer t2(FTM_INVENTORY); - if (mFilter->isModified() && mFilter->isNotDefault()) + if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) { mNeedsAutoSelect = TRUE; } - mFilter->clearModified(); + getFolderViewModel()->getFilter()->clearModified(); // filter to determine visibility before arranging filter(*(getFolderViewModel()->getFilter())); @@ -1958,7 +1950,7 @@ void LLFolderView::doIdle() LLFastTimer t3(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || selected_itemp->passedFilter())) + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1968,7 +1960,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mFilter->showAllResults()) + if (getFolderViewModel()->getFilter()->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -1979,7 +1971,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = getLastFilterGeneration() >= mFilter->getCurrentGeneration() + BOOL filter_finished = getLastFilterGeneration() >= getFolderViewModel()->getFilter()->getCurrentGeneration() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f65a13be1e..685a4cbf49 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -123,7 +123,10 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mListener(p.listener), mIsMouseOverTitle(false) { - mListener->setFolderViewItem(this); + if (mListener) + { + mListener->setFolderViewItem(this); + } } BOOL LLFolderViewItem::postBuild() diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 45a2bffa6b..002278601a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1026,6 +1026,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags) @@ -1151,12 +1152,13 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, default: llinfos << "Unhandled asset type (llassetstorage.h): " << (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << llendl; - break; + break; } if (new_listener) { new_listener->mInvType = inv_type; + new_listener->setRootViewModel(view_model); } return new_listener; @@ -1332,6 +1334,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags /* = 0x00 */) const @@ -1340,6 +1343,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); @@ -6472,41 +6476,30 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags /*= 0x00*/ ) const { LLInvFVBridge* new_listener = NULL; - switch(asset_type) + if (asset_type == LLAssetType::AT_CATEGORY + && actual_asset_type != LLAssetType::AT_LINK_FOLDER) { - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - break; - } new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - break; - default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); + new_listener->setRootViewModel(view_model); + } + else + { + new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + view_model, + root, + uuid, + flags); } return new_listener; - } // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b0582d003d..e235d9cf5f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -66,6 +66,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00); @@ -196,6 +197,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; @@ -645,6 +647,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index aba4c088ab..73e20fc684 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -234,6 +234,7 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); @@ -672,7 +673,7 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.parent_panel = this; p.tool_tip = p.name; p.listener = bridge; - p.view_model = new LLFolderViewModelInventory(); + p.view_model = &mInventoryViewModel; p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; @@ -736,6 +737,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) objectp->getType(), LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, mFolderRoot, objectp->getUUID()); if (new_listener) @@ -751,6 +753,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) item->getActualType(), item->getInventoryType(), this, + &mInventoryViewModel, mFolderRoot, item->getUUID(), item->getFlags()); @@ -1130,7 +1133,6 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) if (!floater_inventory) { llwarns << "Could not find My Inventory floater" << llendl; - return FALSE; } @@ -1347,25 +1349,27 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); - //TODO RN: need better way to get to root viewmodel, also consider reflecting hierarchy in viewmodel space as well - if (static_cast(mFolderViewItem->getRoot()->getFolderViewModel())->getSorter().isByDate()) + if (mRootViewModel->getSorter().isByDate()) { // sort by date potentially affects parent folders which use a date // derived from newest item in them - mFolderViewItem->getParentFolder()->getViewModelItem()->requestSort(); + if (mParent) + { + mParent->requestSort(); + } } } bool LLFolderViewModelItemInventory::potentiallyVisible() { return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet || descendantsPassedFilter(); } bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter && mLastFilterGeneration >= filter_generation && (mPassedFilter || descendantsPassedFilter(filter_generation)); @@ -1373,7 +1377,7 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mFolderViewItem->getRoot()->getFolderViewModel()->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); return mMostFilteredDescendantGeneration >= filter_generation; } @@ -1419,8 +1423,9 @@ void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { - if(getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration())) // or at least one descendant has passed the minimum requirement + if(!mChildren.empty() + && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement { // now query children for (child_list_t::iterator iter = mChildren.begin(); @@ -1456,3 +1461,15 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) filter.decrementFilterCount(); } } + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ + return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ + return &mInventoryViewModel; +} + diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 35a3f9b5e1..55edf386d5 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -42,11 +42,19 @@ class LLInvFVBridge; class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; +class LLFolderViewModelInventory; class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon { public: + LLFolderViewModelItemInventory() + : mRootViewModel(NULL) + {} + void setRootViewModel(LLFolderViewModelInventory* root_view_model) + { + mRootViewModel = root_view_model; + } virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual void setCreationDate(time_t creation_date_utc) = 0; @@ -68,6 +76,8 @@ public: virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); virtual void filter( LLFolderViewFilter& filter); virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); +protected: + LLFolderViewModelInventory* mRootViewModel; }; class LLInventorySort @@ -243,8 +253,8 @@ public: void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - LLFolderViewModelInventory* getFolderViewModel() { return &mViewModel; } - const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } + LLFolderViewModelInventory* getFolderViewModel(); + const LLFolderViewModelInventory* getFolderViewModel() const; protected: void openStartFolderOrMyInventory(); // open the first level of inventory @@ -262,8 +272,8 @@ protected: LLFolderView* mFolderRoot; LLScrollContainer* mScroller; - LLFolderViewModelInventory mViewModel; - + LLFolderViewModelInventory mInventoryViewModel; + std::map mItemMap; /** * Pointer to LLInventoryFVBridgeBuilder. diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index f3096e862d..6e5a522297 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -111,6 +111,7 @@ void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& para LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index 783eeb11b8..2885dd6266 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -77,6 +77,7 @@ void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 97c5d531d2..af29ab7ea9 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -151,6 +151,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags/* = 0x00*/) const @@ -164,6 +165,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; } new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, root, uuid, flags); + new_listener->setRootViewModel(view_model); break; case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -174,12 +176,14 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); break; } new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); + new_listener->setRootViewModel(view_model); break; default: new_listener = LLInventoryFVBridgeBuilder::createBridge( @@ -187,6 +191,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( actual_asset_type, inv_type, inventory, + view_model, root, uuid, flags); diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 52beacef9c..791502990b 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -89,6 +89,7 @@ public: LLAssetType::EType actual_asset_type, LLInventoryType::EType inv_type, LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, LLFolderView* root, const LLUUID& uuid, U32 flags = 0x00) const; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 1c2d75d88c..d95d5eac19 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -87,6 +87,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, + &mInventoryViewModel, NULL, root_id); p.parent_panel = this; -- cgit v1.2.3 From 604bbb22783d2460384e340592ca1781908f6dd8 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 28 Jun 2012 23:30:36 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose cleaned up ownership of viewmodel more filtering fixes --- indra/newview/llfolderview.h | 1 - indra/newview/llfolderviewitem.h | 1 - indra/newview/llinventoryfilter.cpp | 17 +++++++---------- indra/newview/llpanelmaininventory.cpp | 24 ++++++++++++------------ indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llpanelobjectinventory.h | 2 ++ 6 files changed, 22 insertions(+), 25 deletions(-) diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index d261a5967d..8a0317f840 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -302,7 +302,6 @@ protected: LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; std::string mSearchString; - LLFolderViewFilter* mFilter; BOOL mShowSelectionContext; BOOL mShowSingleSelection; LLFrameTimer mMultiSelectionFadeTimer; diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 7e48969826..a3c92a55e8 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -281,7 +281,6 @@ protected: S32 mLastCalculatedWidth; S32 mMostFilteredDescendantGeneration; bool mNeedsSort; - bool mPassedFolderFilter; public: typedef enum e_recurse_type diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c7e0136368..08f1e541b5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -95,16 +95,13 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) return passed_clipboard; } - std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : 0; - const BOOL passed_filtertype = checkAgainstFilterType(listener); - const BOOL passed_permissions = checkAgainstPermissions(listener); - const BOOL passed_filterlink = checkAgainstFilterLinks(listener); - const BOOL passed = (passed_filtertype && - passed_permissions && - passed_filterlink && - passed_clipboard && - (mFilterSubString.size() == 0 || string_offset != std::string::npos)); + BOOL passed = string_offset != std::string::npos; + passed = passed && checkAgainstFilterType(listener); + passed = passed && checkAgainstPermissions(listener); + passed = passed && checkAgainstFilterLinks(listener); + passed = passed && passed_clipboard; return passed; } @@ -595,7 +592,7 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) { - static LLCachedControl s_last_logoff(gSavedSettings, "LastLogoff", 0); + static LLCachedControl s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0); if (sl && !isSinceLogoff()) { setDateRange(s_last_logoff(), time_max()); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 33581160fd..6cef1f877b 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -222,21 +222,21 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) if (p.validateBlock(false)) { LLParamSDParser().writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; + filterRoot[filter->getName()] = filterState; + } } } - } - LLInventoryFilter* filter = findChild("Recent Items")->getFilter(); - if (filter) - { - LLSD filterState; - LLInventoryFilter::Params p; - filter->toParams(p); - LLParamSDParser parser; - parser.writeSD(filterState, p); - filterRoot[filter->getName()] = filterState; - } + LLInventoryFilter* filter = findChild("Recent Items")->getFilter(); + if (filter) + { + LLSD filterState; + LLInventoryFilter::Params p; + filter->toParams(p); + LLParamSDParser parser; + parser.writeSD(filterState, p); + filterRoot[filter->getName()] = filterState; + } std::ostringstream filterSaveName; filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 6a232a26f7..d0b9072ade 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1562,7 +1562,7 @@ void LLPanelObjectInventory::reset() p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); p.folder_indentation = -14; // subtract space normally reserved for folder expanders - p.view_model = new LLFolderViewModelInventory(); + p.view_model = &mInventoryViewModel; mFolders = LLUICtrlFactory::create(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 607b705f7f..7e857f8b31 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -29,6 +29,7 @@ #include "llvoinventorylistener.h" #include "llpanel.h" +#include "llinventorypanel.h" // for LLFolderViewModelInventory #include "llinventory.h" @@ -94,6 +95,7 @@ private: BOOL mHaveInventory; BOOL mIsInventoryEmpty; BOOL mInventoryNeedsUpdate; + LLFolderViewModelInventory mInventoryViewModel; }; #endif // LL_LLPANELOBJECTINVENTORY_H -- cgit v1.2.3 From 07afce2ac86c4c66e8b094ecf977ee5ec5566671 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 29 Jun 2012 09:44:22 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed build --- indra/newview/llfolderview.cpp | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 0f7809d4b4..e007c58497 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -981,30 +981,30 @@ void LLFolderView::openSelectedItems( void ) void LLFolderView::propertiesSelectedItems( void ) { - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - LLFolderViewItem* folder_item = mSelectedItems.front(); - if(!folder_item) return; - folder_item->getViewModelItem()->showProperties(); - } - else - { - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - LLFloater::setFloaterHost(multi_propertiesp); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - (*item_it)->getViewModelItem()->showProperties(); - } - - LLFloater::setFloaterHost(NULL); - multi_propertiesp->openFloater(LLSD()); - } - } + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + // } + // else + // { + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // LLFloater::setFloaterHost(multi_propertiesp); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } + + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + // } + //} } void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -- cgit v1.2.3 From fe01e64f9756641756d18d7aab7079bfee21c089 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 29 Jun 2012 13:08:00 -0400 Subject: SH-3226 WIP - request appearance update request, connects to UpdateAgentAppearance cap, in updateAppearanceFromCOF() --- indra/newview/llappearancemgr.cpp | 30 ++++++++++++++++++++++++++++++ indra/newview/llappearancemgr.h | 2 ++ indra/newview/llviewerregion.cpp | 1 + 3 files changed, 33 insertions(+) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 02a90c60ec..d6cb910b4e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1730,6 +1730,12 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) // the saved outfit stored as a folder link updateIsDirty(); + // Send server request for appearance update + if (useServerTextureBaking()) + { + requestServerAppearanceUpdate(); + } + //dumpCat(getCOF(),"COF, start"); bool follow_folder_links = true; @@ -2589,6 +2595,30 @@ bool LLAppearanceMgr::useServerTextureBaking() return gSavedSettings.getBOOL("UseServerTextureBaking"); } +class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder +{ +public: + RequestAgentUpdateAppearanceResponder() {} + /*virtual*/ void error(U32 status, const std::string& reason) + { + llwarns << "appearance update request failed, reason: " << reason << llendl; + } +}; + +void LLAppearanceMgr::requestServerAppearanceUpdate() +{ + std::string url = gAgent.getRegion()->getCapability("UpdateAgentAppearance"); + if (!url.empty()) + { + LLSD body; + LLHTTPClient::post(url, body, new RequestAgentUpdateAppearanceResponder); + } + else + { + llwarns << "no cap for UpdateAgentAppearance" << llendl; + } +} + class LLShowCreatedOutfit: public LLInventoryCallback { public: diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 4423486b95..46457f1dce 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -184,6 +184,8 @@ public: bool useServerTextureBaking(); + void requestServerAppearanceUpdate(); + protected: LLAppearanceMgr(); ~LLAppearanceMgr(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e3cb985ddb..912dd7d0c9 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1545,6 +1545,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateAgentAppearance"); capabilityNames.append("UpdateGestureAgentInventory"); capabilityNames.append("UpdateNotecardAgentInventory"); capabilityNames.append("UpdateScriptAgent"); -- cgit v1.2.3 From 062cae9a4880f7672df7f6189e01b2bff15f42f1 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 29 Jun 2012 15:44:08 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose cleaned up some stale TODOs worked on getting initial inventory display to work consistently --- indra/newview/llfolderview.cpp | 2 +- indra/newview/llfolderviewmodel.h | 13 +++--------- indra/newview/llinventoryfilter.cpp | 3 +-- indra/newview/llinventorypanel.cpp | 34 ++++++++++++++++++++++++-------- indra/newview/llinventorypanel.h | 4 ++-- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/lltexturectrl.cpp | 2 +- 7 files changed, 35 insertions(+), 25 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index e007c58497..5844c58e09 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -713,7 +713,6 @@ void LLFolderView::draw() { if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) { - // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else @@ -981,6 +980,7 @@ void LLFolderView::openSelectedItems( void ) void LLFolderView::propertiesSelectedItems( void ) { + //TODO RN: get working again //if(getVisible() && getEnabled()) //{ // if (mSelectedItems.size() == 1) diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index c5079712f5..5304613219 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -122,7 +122,6 @@ public: virtual void requestSortAll() = 0; virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter(class LLFolderViewFolder*) = 0; virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; @@ -208,12 +207,6 @@ public: } } - //TODO RN: fix this - void filter(LLFolderViewFolder* folder) - { - - } - protected: SortType mSorter; FilterType mFilter; @@ -264,7 +257,7 @@ public: virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - virtual void filter( LLFolderViewFilter& filter) = 0; + virtual bool filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; @@ -306,8 +299,8 @@ class LLFolderViewModelItemCommon : public LLFolderViewModelItem public: LLFolderViewModelItemCommon() : mSortVersion(-1), - mPassedFilter(false), - mPassedFolderFilter(false), + mPassedFilter(true), + mPassedFolderFilter(true), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 08f1e541b5..6a33130322 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -159,7 +159,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const // (e.g. versus in-world object contents). const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); if (!cat) - return false; + return folder_id.isNull(); LLFolderType::EType cat_type = cat->getPreferredType(); if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0)) return false; @@ -1091,7 +1091,6 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) mEmptyLookupMessage = message; } -// TODO RN: turn this into a param and move to llfolderviewmodelinterface std::string LLInventoryFilter::getEmptyLookupMessage() const { LLStringUtil::format_map_t args; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 73e20fc684..e4cabcc988 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1388,10 +1388,12 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_fo mLastFilterGeneration = filter_generation; } -void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { + bool passed_filter_before = item->passedFilter(); S32 filter_generation = filter.getCurrentGeneration(); S32 must_pass_generation = filter.getFirstRequiredGeneration(); + bool changed = false; // mMostFilteredDescendantGeneration might have been reset // in which case we need to update it even for folders that @@ -1407,22 +1409,37 @@ void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite } else { - //TODO RN: - item->filter( filter ); + changed |= item->filter( filter ); } } // track latest generation to pass any child items if (item->passedFilter()) { - mMostFilteredDescendantGeneration = filter_generation; - //TODO RN: ensure this still happens - //requestArrange(); + LLFolderViewModelItemInventory* view_model = this; + + while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) + { + view_model->mMostFilteredDescendantGeneration = filter_generation; + view_model = static_cast(view_model->mParent); + } + } + + changed |= (item->passedFilter() != passed_filter_before); + if (changed) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* parent = mFolderViewItem->getParentFolder(); + if (parent) parent->requestArrange(); } + + return changed; } -void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { + bool changed = false; + if(!mChildren.empty() && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement @@ -1432,7 +1449,7 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) iter != mChildren.end() && filter.getFilterCount() > 0; ++iter) { - filterChildItem((*iter), filter); + changed |= filterChildItem((*iter), filter); } } @@ -1460,6 +1477,7 @@ void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) //mStringMatchOffset = filter.getStringMatchOffset(this); filter.decrementFilterCount(); } + return changed; } LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 55edf386d5..3195d9a369 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -74,8 +74,8 @@ public: virtual bool passedFilter(S32 filter_generation = -1); virtual bool descendantsPassedFilter(S32 filter_generation = -1); virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual void filter( LLFolderViewFilter& filter); - virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + virtual bool filter( LLFolderViewFilter& filter); + virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); protected: LLFolderViewModelInventory* mRootViewModel; }; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index d0b9072ade..450e1f7ed0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1566,7 +1566,7 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly - //mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + static_cast(mFolders->getFolderViewModel()->getFilter())->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 654b18614a..61a0331b72 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -637,7 +637,7 @@ void LLFloaterTexturePicker::draw() { folder_view->setPinningSelectedItem(mSelectedItemPinned); folder_view->getViewModelItem()->dirtyFilter(); - //TODO RN: test + //TODO RN: test..still works without this? //folder_view->arrangeFromRoot(); mSelectedItemPinned = TRUE; -- cgit v1.2.3 From 3f931ad1e3558a847ba93099a0336782f9f5dbdc Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Fri, 29 Jun 2012 19:18:33 -0400 Subject: SH-3229 FIX suppress baked texture cache requests and generated agentAppearance messages If you're using the new pipeline, then we should not be requesting cached baked textures from the simulator. Nor should we be sending agentAppearance messages to the simulator (note: this may change in the future on region arrive) --- indra/newview/llagent.cpp | 3 ++- indra/newview/llagentwearables.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3367604753..f99065aa08 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -35,6 +35,7 @@ #include "llagentlistener.h" #include "llagentwearables.h" #include "llagentui.h" +#include "llappearancemgr.h" #include "llanimationstates.h" #include "llcallingcard.h" #include "llcapabilitylistener.h" @@ -3771,7 +3772,7 @@ void LLAgent::requestLeaveGodMode() //----------------------------------------------------------------------------- void LLAgent::sendAgentSetAppearance() { - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid() || LLAppearanceMgr::instance().useServerTextureBaking()) return; if (gAgentQueryManager.mNumPendingQueries > 0 && (isAgentAvatarValid() && gAgentAvatarp->isUsingBakedTextures())) { diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e441f21f90..0a721312f3 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1597,7 +1597,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n void LLAgentWearables::queryWearableCache() { - if (!areWearablesLoaded()) + if (!areWearablesLoaded() || LLAppearanceMgr::instance().useServerTextureBaking()) { return; } -- cgit v1.2.3 From 38eb726ca8ecbc52f9afe2181474074a8bc59211 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 2 Jul 2012 15:27:19 +0300 Subject: CHUI-103 FIXED (Implement changes to compact chat view) Change coloration --- indra/newview/llchathistory.cpp | 47 ++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index dcd6d25888..80be753d9e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -734,17 +734,23 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); + LLColor4 name_color(txt_color); + LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); std::string font_name = LLFontGL::nameFromFont(fontp); std::string font_size = LLFontGL::sizeFromFont(fontp); - LLStyle::Params style_params; - style_params.color(txt_color); - style_params.readonly_color(txt_color); - style_params.font.name(font_name); - style_params.font.size(font_size); - style_params.font.style(input_append_params.font.style); + LLStyle::Params body_message_params; + body_message_params.color(txt_color); + body_message_params.readonly_color(txt_color); + body_message_params.font.name(font_name); + body_message_params.font.size(font_size); + body_message_params.font.style(input_append_params.font.style); + + LLStyle::Params name_params(body_message_params); + name_params.color(name_color); + name_params.readonly_color(name_color); std::string prefix = chat.mText.substr(0, 4); @@ -767,7 +773,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) { delimiter = LLStringUtil::null; - style_params.font.style = "ITALIC"; + name_params.font.style = "ITALIC"; } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; @@ -775,18 +781,20 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (message_from_log) { txt_color = LLColor4::grey; - style_params.color(txt_color); - style_params.readonly_color(txt_color); + body_message_params.color(txt_color); + body_message_params.readonly_color(txt_color); + name_params.color(txt_color); + name_params.readonly_color(txt_color); } bool prependNewLineState = mEditor->getText().size() != 0; - // show timestamps and names in the compact mode + // compact mode: show a timestamp and name if (use_plain_text_chat_history) { square_brackets = chat.mFromName == SYSTEM_FROM; - LLStyle::Params timestamp_style(style_params); + LLStyle::Params timestamp_style(body_message_params); // out of the timestamp if (args["show_time"].asBoolean()) @@ -804,7 +812,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // out the opening square bracket (if need) if (square_brackets) { - mEditor->appendText("[", prependNewLineState, style_params); + mEditor->appendText("[", prependNewLineState, body_message_params); prependNewLineState = false; } @@ -819,7 +827,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // set the link for the object name to be the objectim SLapp // (don't let object names with hyperlinks override our objectim Url) - LLStyle::Params link_params(style_params); + LLStyle::Params link_params(body_message_params); LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); link_params.color = link_color; link_params.readonly_color = link_color; @@ -831,7 +839,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { - LLStyle::Params link_params(style_params); + LLStyle::Params link_params(body_message_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); if (from_me) @@ -852,7 +860,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL else { mEditor->appendText("" + chat.mFromName + "" + delimiter, - prependNewLineState, style_params); + prependNewLineState, body_message_params); prependNewLineState = false; } } @@ -880,7 +888,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else { - view = getHeader(chat, style_params, args); + view = getHeader(chat, name_params, args); if (mEditor->getText().size() == 0) p.top_pad = 0; else @@ -909,6 +917,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mIsLastMessageFromLog = message_from_log; } + // body of the message processing + + // notify processing if (chat.mNotifId.notNull()) { LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); @@ -932,6 +943,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->appendWidget(params, "\n", false); } } + + // usual messages showing else { std::string message = irc_me ? chat.mText.substr(3) : chat.mText; @@ -959,7 +972,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL message += "]"; } - mEditor->appendText(message, prependNewLineState, style_params); + mEditor->appendText(message, prependNewLineState, body_message_params); prependNewLineState = false; } -- cgit v1.2.3 From f22e5df8b6890aab659916361d42479ca3825be9 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Mon, 2 Jul 2012 17:46:34 +0300 Subject: CHUI-172 WIP Fixed drawing the nearby chat toast contents. Fixed warnings when creating a nearby chat toast. --- indra/newview/llchatitemscontainerctrl.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 477bdb3967..61772b4bb7 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -96,8 +96,15 @@ void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_p { LLPanel::reshape(width, height,called_from_parent); - LLUICtrl* msg_text = getChild("msg_text", false); - LLUICtrl* icon = getChild("avatar_icon", false); + // reshape() may be called from LLView::initFromParams() before the children are created. + // We call findChild() instead of getChild() here to avoid creating dummy controls. + LLUICtrl* msg_text = findChild("msg_text", false); + LLUICtrl* icon = findChild("avatar_icon", false); + + if (!msg_text || !icon) + { + return; + } LLRect msg_text_rect = msg_text->getRect(); LLRect avatar_rect = icon->getRect(); @@ -355,6 +362,8 @@ BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) } void LLNearbyChatToastPanel::draw() { + LLPanel::draw(); + if(mIsDirty) { LLAvatarIconCtrl* icon = getChild("avatar_icon", false); -- cgit v1.2.3 From 4718ffebc1942ea1d94c8e8d2eca071d0d834bc2 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 2 Jul 2012 18:17:56 -0400 Subject: FIX: renamed UpdateAgentAppearance to UpdateAvatarAppearance --- indra/newview/llappearancemgr.cpp | 4 ++-- indra/newview/llviewerregion.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d6cb910b4e..480a8e0d73 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2607,7 +2607,7 @@ public: void LLAppearanceMgr::requestServerAppearanceUpdate() { - std::string url = gAgent.getRegion()->getCapability("UpdateAgentAppearance"); + std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); if (!url.empty()) { LLSD body; @@ -2615,7 +2615,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() } else { - llwarns << "no cap for UpdateAgentAppearance" << llendl; + llwarns << "no cap for UpdateAvatarAppearance" << llendl; } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 912dd7d0c9..777475fe61 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1545,7 +1545,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); - capabilityNames.append("UpdateAgentAppearance"); + capabilityNames.append("UpdateAvatarAppearance"); capabilityNames.append("UpdateGestureAgentInventory"); capabilityNames.append("UpdateNotecardAgentInventory"); capabilityNames.append("UpdateScriptAgent"); -- cgit v1.2.3 From 1bd52dfbdc3607bbd9ea86c715ce63b17d5a557f Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 2 Jul 2012 17:57:29 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose refactored source files, moving logic into llfolderviewmodel*.cpp filter logic tweaks purging and moving inventory now properly cleans up view model --- indra/newview/CMakeLists.txt | 3 + indra/newview/llfolderview.cpp | 27 +--- indra/newview/llfolderviewitem.cpp | 19 +-- indra/newview/llfolderviewitem.h | 10 +- indra/newview/llfolderviewmodel.cpp | 54 +++++++ indra/newview/llfolderviewmodel.h | 25 ++- indra/newview/llfolderviewmodelinventory.cpp | 225 +++++++++++++++++++++++++++ indra/newview/llfolderviewmodelinventory.h | 107 +++++++++++++ indra/newview/llinventoryfilter.cpp | 24 --- indra/newview/llinventorypanel.cpp | 201 +----------------------- indra/newview/llinventorypanel.h | 78 +--------- indra/newview/lltexturectrl.cpp | 4 +- 12 files changed, 429 insertions(+), 348 deletions(-) create mode 100644 indra/newview/llfolderviewmodel.cpp create mode 100644 indra/newview/llfolderviewmodelinventory.cpp create mode 100644 indra/newview/llfolderviewmodelinventory.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4f447fd35b..dee37bd5e8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -253,6 +253,8 @@ set(viewer_SOURCE_FILES llfloaterworldmap.cpp llfolderview.cpp llfolderviewitem.cpp + llfolderviewmodel.cpp + llfolderviewmodelinventory.cpp llfollowcam.cpp llfriendcard.cpp llgesturelistener.cpp @@ -809,6 +811,7 @@ set(viewer_HEADER_FILES llfloaterworldmap.h llfolderview.h llfolderviewmodel.h + llfolderviewmodelinventory.h llfolderviewitem.h llfollowcam.h llfriendcard.h diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 5844c58e09..90c78d98b0 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -259,7 +259,7 @@ LLFolderView::LLFolderView(const Params& p) menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); mPopupMenuHandle = menu->getHandle(); - mListener->openItem(); + mViewModelItem->openItem(); } // Destroys the object @@ -363,11 +363,7 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - if (getLastFilterGeneration() < filter.getCurrentGeneration()) - { - mMinWidth = 0; - getViewModelItem()->filter(filter); - } + getViewModelItem()->filter(filter); } void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -706,20 +702,11 @@ void LLFolderView::draw() if (hasVisibleChildren()) { - mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); } else if (mShowEmptyMessage) { - if (!mViewModel->contentsReady() || getLastFilterGeneration() < getFolderViewModel()->getFilter()->getFirstSuccessGeneration()) - { - mStatusText = LLTrans::getString("Searching"); - } - else - { - mStatusText = getFolderViewModel()->getFilter()->getEmptyLookupMessage(); - } - mStatusTextBox->setValue(mStatusText); + mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); mStatusTextBox->setVisible( TRUE ); // firstly reshape message textbox with current size. This is necessary to @@ -1971,7 +1958,7 @@ void LLFolderView::doIdle() scrollToShowSelection(); } - BOOL filter_finished = getLastFilterGeneration() >= getFolderViewModel()->getFilter()->getCurrentGeneration() + BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) @@ -2264,9 +2251,3 @@ S32 LLFolderView::getItemHeight() } return 0; } - -//TODO RN: move to llfolderviewmodel.cpp file -bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) -{ - return item->getSortVersion() < mTargetSortVersion; -} diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 685a4cbf49..ac389c9189 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -120,12 +120,12 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mDragAndDropTarget(FALSE), mLabel(p.name), mRoot(p.root), - mListener(p.listener), + mViewModelItem(p.listener), mIsMouseOverTitle(false) { - if (mListener) + if (mViewModelItem) { - mListener->setFolderViewItem(this); + mViewModelItem->setFolderViewItem(this); } } @@ -138,8 +138,8 @@ BOOL LLFolderViewItem::postBuild() // Destroys the object LLFolderViewItem::~LLFolderViewItem( void ) { - delete mListener; - mListener = NULL; + delete mViewModelItem; + mViewModelItem = NULL; } LLFolderView* LLFolderViewItem::getRoot() @@ -837,12 +837,6 @@ LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) return getRoot()->getFolderViewModel(); } -S32 LLFolderViewItem::getLastFilterGeneration() const -{ - return getViewModelItem()->getLastFilterGeneration(); -} - - ///---------------------------------------------------------------------------- /// Class LLFolderViewFolder @@ -1446,6 +1440,7 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) mItems.erase(it); } //item has been removed, need to update filter + getViewModelItem()->removeChild(item->getViewModelItem()); getViewModelItem()->dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); @@ -1638,7 +1633,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index a3c92a55e8..581ec7239e 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -92,13 +92,12 @@ protected: S32 mLabelWidth; bool mLabelWidthDirty; LLFolderViewFolder* mParentFolder; - LLFolderViewModelItem* mListener; + LLFolderViewModelItem* mViewModelItem; BOOL mIsCurSelection; BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; LLUIImagePtr mIcon; - std::string mStatusText; LLUIImagePtr mIconOpen; LLUIImagePtr mIconOverlay; BOOL mHasVisibleChildren; @@ -136,9 +135,6 @@ public: virtual S32 arrange( S32* width, S32* height ); virtual S32 getItemHeight(); - // updates filter serial number and optionally propagated value up to root - S32 getLastFilterGeneration() const; - // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -202,8 +198,8 @@ public: LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } - LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } + const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } + LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } const LLFolderViewModelInterface* getFolderViewModel( void ) const; LLFolderViewModelInterface* getFolderViewModel( void ); diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp new file mode 100644 index 0000000000..92db84156e --- /dev/null +++ b/indra/newview/llfolderviewmodel.cpp @@ -0,0 +1,54 @@ +/** + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfolderviewmodel.h" +#include "lltrans.h" +#include "llviewercontrol.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) + { + return LLTrans::getString("Searching"); + } + else + { + return getFilter()->getEmptyLookupMessage(); + } +} + +void LLFolderViewModelCommon::filter() +{ + getFilter()->setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + mFolderView->getViewModelItem()->filter(*getFilter()); +} diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 5304613219..8a16ec3eff 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -28,6 +28,7 @@ #include "lldarray.h" // *TODO: convert to std::vector #include "llfoldertype.h" #include "llfontgl.h" // just for StyleFlags enum +#include "llfolderview.h" #include "llfolderviewitem.h" #include "llinventorytype.h" #include "llpermissionsflags.h" @@ -122,11 +123,13 @@ public: virtual void requestSortAll() = 0; virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; virtual bool contentsReady() = 0; virtual void setFolderView(LLFolderView* folder_view) = 0; virtual LLFolderViewFilter* getFilter() = 0; virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; }; class LLFolderViewModelCommon : public LLFolderViewModelInterface @@ -142,6 +145,8 @@ public: // sort everything mTargetSortVersion++; } + virtual std::string getStatusText(); + virtual void filter(); void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} @@ -177,6 +182,7 @@ public: // add getStatusText and isFiltering() virtual bool contentsReady() { return true; } + struct ViewModelCompare { ViewModelCompare(const SortType& sorter) @@ -272,6 +278,7 @@ public: virtual bool hasChildren() const = 0; virtual void addChild(LLFolderViewModelItem* child) = 0; + virtual void removeChild(LLFolderViewModelItem* child) = 0; // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is @@ -305,7 +312,9 @@ public: mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), mParent(NULL) - {} + { + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + } void requestSort() { mSortVersion = -1; } S32 getSortVersion() { return mSortVersion; } @@ -315,13 +324,23 @@ public: void dirtyFilter() { mLastFilterGeneration = -1; + // bubble up dirty flag all the way to root if (mParent) { mParent->dirtyFilter(); - } + } + } + virtual void addChild(LLFolderViewModelItem* child) + { + mChildren.push_back(child); + child->setParent(this); + } + virtual void removeChild(LLFolderViewModelItem* child) + { + mChildren.remove(child); + child->setParent(NULL); } - virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); child->setParent(this); } protected: virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp new file mode 100644 index 0000000000..7ee1a10b15 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -0,0 +1,225 @@ +/* + * @file llfolderviewmodelinventory.cpp + * @brief Implementation of the inventory-specific view model + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfolderviewmodelinventory.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" + +// +// class LLFolderViewModelInventory +// +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ + LLFastTimer _(FTM_INVENTORY_SORT); + + if (!needsSort(folder->getViewModelItem())) return; + + LLFolderViewModelItemInventory* modelp = static_cast(folder->getViewModelItem()); + if (modelp->getUUID().isNull()) return; + + for (std::list::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewFolder* child_folderp = *it; + sort(child_folderp); + + if (child_folderp->getFoldersCount() > 0) + { + time_t most_recent_folder_time = + static_cast((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); + LLFolderViewModelItemInventory* modelp = static_cast(child_folderp->getViewModelItem()); + if (most_recent_folder_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_folder_time); + } + } + if (child_folderp->getItemsCount() > 0) + { + time_t most_recent_item_time = + static_cast((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + + LLFolderViewModelItemInventory* modelp = static_cast(child_folderp->getViewModelItem()); + if (most_recent_item_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_item_time); + } + } + } + base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ + return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + +void LLFolderViewModelItemInventory::requestSort() +{ + LLFolderViewModelItemCommon::requestSort(); + if (mRootViewModel->getSorter().isByDate()) + { + // sort by date potentially affects parent folders which use a date + // derived from newest item in them + if (mParent) + { + mParent->requestSort(); + } + } +} + +bool LLFolderViewModelItemInventory::potentiallyVisible() +{ + return passedFilter() // we've passed the filter + || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || descendantsPassedFilter(); +} + +bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) +{ + if (filter_generation < 0 && mRootViewModel) + filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + + return mPassedFolderFilter + && mLastFilterGeneration >= filter_generation + && (mPassedFilter || descendantsPassedFilter(filter_generation)); +} + +bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) +{ + if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + return mMostFilteredDescendantGeneration >= filter_generation; +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) +{ + mPassedFilter = passed; + mPassedFolderFilter = passed_folder; + mLastFilterGeneration = filter_generation; +} + +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ + bool passed_filter_before = item->passedFilter(); + S32 filter_generation = filter.getCurrentGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + if (item->getLastFilterGeneration() < filter_generation) + { + if (item->getLastFilterGeneration() >= must_pass_generation + && !item->passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + item->filter(filter); + if (item->passedFilter()) + { + llerrs << "Invalid shortcut in inventory filtering!" << llendl; + } + item->setPassedFilter(false, false, filter_generation); + } + else + { + item->filter( filter ); + } + } + + // track latest generation to pass any child items, for each folder up to root + if (item->passedFilter()) + { + LLFolderViewModelItemInventory* view_model = this; + + while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) + { + view_model->mMostFilteredDescendantGeneration = filter_generation; + view_model = static_cast(view_model->mParent); + } + + return !passed_filter_before; + } + else // !item->passedfilter() + { + return passed_filter_before; + } +} + +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ + bool changed = false; + + if(!mChildren.empty() + && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement + { + // now query children + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end() && filter.getFilterCount() > 0; + ++iter) + { + changed |= filterChildItem((*iter), filter); + } + } + + if (changed) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* folder = static_cast(mFolderViewItem); + folder->requestArrange(); + } + + // if we didn't use all filter iterations + // that means we filtered all of our descendants + // so filter ourselves now + if (filter.getFilterCount() > 0) + { + filter.decrementFilterCount(); + + const BOOL passed_filter = filter.check(this); + const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) + ? filter.checkFolder(this) + : true; + + setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); + } + return changed; +} + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ + return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ + return &mInventoryViewModel; +} + diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h new file mode 100644 index 0000000000..a8fe3f57ea --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.h @@ -0,0 +1,107 @@ +/** + * @file llfolderviewmodelinventory.h + * @brief view model implementation specific to inventory + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFOLDERVIEWMODELINVENTORY_H +#define LL_LLFOLDERVIEWMODELINVENTORY_H + +#include "llinventoryfilter.h" + +class LLFolderViewModelItemInventory + : public LLFolderViewModelItemCommon +{ +public: + LLFolderViewModelItemInventory() + : mRootViewModel(NULL) + {} + void setRootViewModel(class LLFolderViewModelInventory* root_view_model) + { + mRootViewModel = root_view_model; + } + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual void setCreationDate(time_t creation_date_utc) = 0; + virtual PermissionMask getPermissionMask() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isUpToDate() const = 0; + virtual bool hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual EInventorySortGroup getSortGroup() const = 0; + virtual LLInventoryObject* getInventoryObject() const = 0; + virtual void requestSort(); + virtual bool potentiallyVisible(); + virtual bool passedFilter(S32 filter_generation = -1); + virtual bool descendantsPassedFilter(S32 filter_generation = -1); + virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); + virtual bool filter( LLFolderViewFilter& filter); + virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); +protected: + class LLFolderViewModelInventory* mRootViewModel; +}; + +class LLInventorySort +{ +public: + LLInventorySort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) + { + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + +class LLFolderViewModelInventory + : public LLFolderViewModel +{ +public: + typedef LLFolderViewModel base_t; + + virtual ~LLFolderViewModelInventory() {} + + void sort(LLFolderViewFolder* folder); + + bool contentsReady(); + +}; +#endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 6a33130322..3f38d80a39 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -779,14 +779,12 @@ const std::string& LLInventoryFilter::getFilterText() if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) { - //filtered_types += " Animations,"; filtered_types += LLTrans::getString("Animations"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Animations,"; not_filtered_types += LLTrans::getString("Animations"); filtered_by_all_types = FALSE; @@ -794,140 +792,120 @@ const std::string& LLInventoryFilter::getFilterText() if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD)) { - //filtered_types += " Calling Cards,"; filtered_types += LLTrans::getString("Calling Cards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Calling Cards,"; not_filtered_types += LLTrans::getString("Calling Cards"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE)) { - //filtered_types += " Clothing,"; filtered_types += LLTrans::getString("Clothing"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Clothing,"; not_filtered_types += LLTrans::getString("Clothing"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE)) { - //filtered_types += " Gestures,"; filtered_types += LLTrans::getString("Gestures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Gestures,"; not_filtered_types += LLTrans::getString("Gestures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK)) { - //filtered_types += " Landmarks,"; filtered_types += LLTrans::getString("Landmarks"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Landmarks,"; not_filtered_types += LLTrans::getString("Landmarks"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD)) { - //filtered_types += " Notecards,"; filtered_types += LLTrans::getString("Notecards"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Notecards,"; not_filtered_types += LLTrans::getString("Notecards"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT)) { - //filtered_types += " Objects,"; filtered_types += LLTrans::getString("Objects"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Objects,"; not_filtered_types += LLTrans::getString("Objects"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_LSL)) { - //filtered_types += " Scripts,"; filtered_types += LLTrans::getString("Scripts"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Scripts,"; not_filtered_types += LLTrans::getString("Scripts"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND)) { - //filtered_types += " Sounds,"; filtered_types += LLTrans::getString("Sounds"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Sounds,"; not_filtered_types += LLTrans::getString("Sounds"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE)) { - //filtered_types += " Textures,"; filtered_types += LLTrans::getString("Textures"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Textures,"; not_filtered_types += LLTrans::getString("Textures"); filtered_by_all_types = FALSE; } if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT)) { - //filtered_types += " Snapshots,"; filtered_types += LLTrans::getString("Snapshots"); filtered_by_type = TRUE; num_filter_types++; } else { - //not_filtered_types += " Snapshots,"; not_filtered_types += LLTrans::getString("Snapshots"); filtered_by_all_types = FALSE; } @@ -943,7 +921,6 @@ const std::string& LLInventoryFilter::getFilterText() } else { - //mFilterText += "No "; mFilterText += LLTrans::getString("No Filters"); mFilterText += not_filtered_types; } @@ -953,7 +930,6 @@ const std::string& LLInventoryFilter::getFilterText() if (isSinceLogoff()) { - //mFilterText += " - Since Logoff"; mFilterText += LLTrans::getString("Since Logoff"); } return mFilterText; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e4cabcc988..b5fcf364dd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -56,58 +56,6 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; -// -// class LLFolderViewModelInventory -// -static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); - -void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) -{ - LLFastTimer _(FTM_INVENTORY_SORT); - - if (!needsSort(folder->getViewModelItem())) return; - - LLFolderViewModelItemInventory* modelp = static_cast(folder->getViewModelItem()); - if (modelp->getUUID().isNull()) return; - - for (std::list::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); - it != end_it; - ++it) - { - LLFolderViewFolder* child_folderp = *it; - sort(child_folderp); - - if (child_folderp->getFoldersCount() > 0) - { - time_t most_recent_folder_time = - static_cast((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); - LLFolderViewModelItemInventory* modelp = static_cast(child_folderp->getViewModelItem()); - if (most_recent_folder_time > modelp->getCreationDate()) - { - modelp->setCreationDate(most_recent_folder_time); - } - } - if (child_folderp->getItemsCount() > 0) - { - time_t most_recent_item_time = - static_cast((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); - - LLFolderViewModelItemInventory* modelp = static_cast(child_folderp->getViewModelItem()); - if (most_recent_item_time > modelp->getCreationDate()) - { - modelp->setCreationDate(most_recent_item_time); - } - } - } - base_t::sort(folder); -} - -bool LLFolderViewModelInventory::contentsReady() -{ - return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); -} - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -580,8 +528,8 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (!model_item && view_item) { // Remove the item's UI. - view_item->destroyView(); removeItemID(viewmodel_item->getUUID()); + view_item->destroyView(); } } } @@ -1344,150 +1292,3 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) // replace bridge builder to have necessary View bridges. mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } - - -void LLFolderViewModelItemInventory::requestSort() -{ - LLFolderViewModelItemCommon::requestSort(); - if (mRootViewModel->getSorter().isByDate()) - { - // sort by date potentially affects parent folders which use a date - // derived from newest item in them - if (mParent) - { - mParent->requestSort(); - } - } -} - -bool LLFolderViewModelItemInventory::potentiallyVisible() -{ - return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet - || descendantsPassedFilter(); -} - -bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) -{ - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); - return mPassedFolderFilter - && mLastFilterGeneration >= filter_generation - && (mPassedFilter || descendantsPassedFilter(filter_generation)); -} - -bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) -{ - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); - return mMostFilteredDescendantGeneration >= filter_generation; -} - -void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) -{ - mPassedFilter = passed; - mPassedFolderFilter = passed_folder; - mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) -{ - bool passed_filter_before = item->passedFilter(); - S32 filter_generation = filter.getCurrentGeneration(); - S32 must_pass_generation = filter.getFirstRequiredGeneration(); - bool changed = false; - - // mMostFilteredDescendantGeneration might have been reset - // in which case we need to update it even for folders that - // don't need to be filtered anymore - if (item->getLastFilterGeneration() < filter_generation) - { - if (item->getLastFilterGeneration() >= must_pass_generation && - !item->passedFilter(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - item->setPassedFilter(false, false, filter_generation); - } - else - { - changed |= item->filter( filter ); - } - } - - // track latest generation to pass any child items - if (item->passedFilter()) - { - LLFolderViewModelItemInventory* view_model = this; - - while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) - { - view_model->mMostFilteredDescendantGeneration = filter_generation; - view_model = static_cast(view_model->mParent); - } - } - - changed |= (item->passedFilter() != passed_filter_before); - if (changed) - { - //TODO RN: ensure this still happens, but without dependency on folderview - LLFolderViewFolder* parent = mFolderViewItem->getParentFolder(); - if (parent) parent->requestArrange(); - } - - return changed; -} - -bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) -{ - bool changed = false; - - if(!mChildren.empty() - && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement - { - // now query children - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end() && filter.getFilterCount() > 0; - ++iter) - { - changed |= filterChildItem((*iter), filter); - } - } - - // if we didn't use all filter iterations - // that means we filtered all of our descendants - // so filter ourselves now - if (filter.getFilterCount() > 0) - { - const BOOL previous_passed_filter = mPassedFilter; - const BOOL passed_filter = filter.check(this); - const BOOL passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) - ? filter.checkFolder(this) - : true; - - // If our visibility will change as a result of this filter, then - // we need to be rearranged in our parent folder - LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); - if (parent_folder && passed_filter != previous_passed_filter) - { - parent_folder->requestArrange(); - } - - setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); - //TODO RN: create interface for string highlighting - //mStringMatchOffset = filter.getStringMatchOffset(this); - filter.decrementFilterCount(); - } - return changed; -} - -LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() -{ - return &mInventoryViewModel; -} - - -const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const -{ - return &mInventoryViewModel; -} - diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 3195d9a369..a62b97aa7d 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -31,6 +31,7 @@ #include "llassetstorage.h" #include "lldarray.h" #include "llfolderviewitem.h" +#include "llfolderviewmodelinventory.h" #include "llfloater.h" #include "llinventory.h" #include "llinventoryfilter.h" @@ -42,83 +43,6 @@ class LLInvFVBridge; class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; -class LLFolderViewModelInventory; - -class LLFolderViewModelItemInventory - : public LLFolderViewModelItemCommon -{ -public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) - {} - void setRootViewModel(LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual void setCreationDate(time_t creation_date_utc) = 0; - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL isUpToDate() const = 0; - virtual bool hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const = 0; - virtual LLInventoryObject* getInventoryObject() const = 0; - virtual void requestSort(); - virtual bool potentiallyVisible(); - virtual bool passedFilter(S32 filter_generation = -1); - virtual bool descendantsPassedFilter(S32 filter_generation = -1); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); -protected: - LLFolderViewModelInventory* mRootViewModel; -}; - -class LLInventorySort -{ -public: - LLInventorySort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) - { - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - } - - bool isByDate() const { return mByDate; } - U32 getSortOrder() const { return mSortOrder; } - - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - -class LLFolderViewModelInventory - : public LLFolderViewModel -{ -public: - typedef LLFolderViewModel base_t; - - virtual ~LLFolderViewModelInventory() {} - - void sort(LLFolderViewFolder* folder); - - bool contentsReady(); - -}; - class LLInventoryPanel : public LLPanel { diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 61a0331b72..4a9e106687 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -623,9 +623,9 @@ void LLFloaterTexturePicker::draw() LLFolderView* folder_view = mInventoryPanel->getRootFolder(); if (!folder_view) return; - LLInventoryFilter* filter = static_cast(folder_view->getFolderViewModel())->getFilter(); + LLFolderViewFilter* filter = static_cast(folder_view->getFolderViewModel())->getFilter(); - bool is_filter_active = folder_view->getLastFilterGeneration() < filter->getCurrentGeneration() && + bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter->getCurrentGeneration() && filter->isNotDefault(); // After inventory panel filter is applied we have to update -- cgit v1.2.3 From 5904976435873b0b3c4f39a2514aef38bee22a39 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 3 Jul 2012 01:06:04 +0000 Subject: Added more rendering-code early-exits when in headless mode. --- indra/newview/llviewerwindow.cpp | 1 + indra/newview/pipeline.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 7afb135470..ed970b84a7 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1712,6 +1712,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) void LLViewerWindow::initGLDefaults() { + if (gHeadlessClient) return; gGL.setSceneBlendType(LLRender::BT_ALPHA); if (!LLGLSLShader::sNoFixedFunction) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 49c4f37871..de72d79043 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1105,6 +1105,7 @@ void LLPipeline::releaseScreenBuffers() void LLPipeline::createGLBuffers() { + if (gHeadlessClient) return; stop_glerror(); LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS); assertInitialized(); -- cgit v1.2.3 From 7b4f24850b94aba41ee93c6f2901b012de2b7d30 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 2 Jul 2012 19:37:11 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose fixed build post merge --- indra/newview/llimfloatercontainer.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2bbd371e8f..9615f3f44d 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -37,7 +37,7 @@ #include "llgroupmgr.h" #include "llfolderviewitem.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" class LLButton; class LLLayoutPanel; @@ -53,7 +53,7 @@ typedef std::map conversations_widgets_map; // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. -class LLConversationItem : public LLFolderViewEventListener +class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); @@ -62,6 +62,7 @@ public: // Stub those things we won't really be using in this conversation context virtual const std::string& getName() const { return mName; } virtual const std::string& getDisplayName() const { return mName; } + virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } virtual PermissionMask getPermissionMask() const { return PERM_ALL; } @@ -76,8 +77,8 @@ public: virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } virtual BOOL removeItem() { return FALSE; } - virtual void removeBatch(LLDynamicArray& batch) { } - virtual void move( LLFolderViewEventListener* parent_listener ) { } + virtual void removeBatch(std::vector& batch) { } + virtual void move( LLFolderViewModelItem* parent_listener ) { } virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const { return FALSE; } virtual BOOL cutToClipboard() const { return FALSE; } @@ -86,10 +87,16 @@ public: virtual void pasteLinkFromClipboard() { } virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } - virtual BOOL hasChildren() const { return FALSE; } + virtual bool hasChildren() const { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + virtual bool potentiallyVisible() { return true; } + virtual bool filter( LLFolderViewFilter& filter) { return true; } + virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { } + virtual bool passedFilter(S32 filter_generation = -1) { return true; } + // The action callbacks virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem( void ); @@ -102,6 +109,7 @@ public: // This method should be called when a drag begins. // Returns TRUE if the drag can begin, FALSE otherwise. + virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_PEOPLE; } virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } // This method will be called to determine if a drop can be -- cgit v1.2.3 From 7d0150f12d8edcbd078ef570f7c64e44194e4335 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 2 Jul 2012 19:37:28 -0700 Subject: CHUI-101 WIP Make LLFolderView general purpose started to remove newview dependencies from llfolder* --- indra/newview/llfolderview.cpp | 196 +++++++-------------------- indra/newview/llfolderview.h | 12 +- indra/newview/llfolderviewitem.cpp | 96 +------------ indra/newview/llfolderviewitem.h | 1 - indra/newview/llfolderviewmodel.h | 13 +- indra/newview/llfolderviewmodelinventory.cpp | 81 +++++++++++ indra/newview/llinventoryfunctions.cpp | 88 +++++++++++- indra/newview/llinventoryfunctions.h | 7 + indra/newview/llinventorypanel.cpp | 13 +- indra/newview/llinventorypanel.h | 2 +- indra/newview/llpanellandmarks.cpp | 4 +- indra/newview/llpanelmaininventory.cpp | 4 +- indra/newview/llpanelobjectinventory.cpp | 2 +- 13 files changed, 245 insertions(+), 274 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 90c78d98b0..6bc89cdbca 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -26,34 +26,25 @@ #include "llviewerprecompiledheaders.h" -#include "llfolderview.h" #include "llfolderview.h" -#include "llcallbacklist.h" -#include "llinventorybridge.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventorypanel.h" -#include "llfoldertype.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" #include "llpanel.h" -#include "llpreview.h" #include "llscrollcontainer.h" // hack to allow scrolling -#include "lltooldraganddrop.h" #include "lltrans.h" #include "llui.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewerjointattachment.h" -#include "llviewermenu.h" #include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerfoldertype.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llfloaterproperties.h" -#include "llnotificationsutil.h" + +// TODO RN: kill these +// newview includes +#include "llcallbacklist.h" // per-frame on-idle +#include "llfloaterproperties.h" // showProperties +#include "llviewerwindow.h" // renamer popup handling +#include "llpreview.h" // openSelectedItems +#include "llinventorypanel.h" // idle loop for filtering, sort order declarations, etc. // Linden library includes #include "lldbstrings.h" @@ -251,7 +242,7 @@ LLFolderView::LLFolderView(const Params& p) // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); if (!menu) { menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); @@ -361,7 +352,7 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { LLFastTimer t2(FTM_FILTER); - filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); getViewModelItem()->filter(filter); } @@ -631,7 +622,7 @@ void LLFolderView::clearSelection() } std::set LLFolderView::getSelectionList() const - { +{ std::set selection; std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); return selection; @@ -695,7 +686,7 @@ void LLFolderView::draw() } - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) { mSearchString.clear(); } @@ -767,14 +758,6 @@ void LLFolderView::closeRenamer( void ) } } -void LLFolderView::removeSelectedItems( void ) -{ - if (mSelectedItems.empty()) return; - LLSD args; - args["QUESTION"] = LLTrans::getString(mSelectedItems.size() > 1 ? "DeleteItems" : "DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLFolderView::onItemsRemovalConfirmation, this, _1, _2)); -} - bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector& selectedItems) { LLFolderViewItem* item_parent = dynamic_cast(item->getParent()); @@ -820,11 +803,8 @@ void LLFolderView::removeCutItems() } } -void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) +void LLFolderView::removeSelectedItems() { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled - if(getVisible() && getEnabled()) { // just in case we're removing the renaming item. @@ -927,42 +907,44 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } } +// TODO RN: abstract // open the selected item. void LLFolderView::openSelectedItems( void ) { - if(getVisible() && getEnabled()) - { - if (mSelectedItems.size() == 1) - { - mSelectedItems.front()->openItem(); - } - else - { - LLMultiPreview* multi_previewp = new LLMultiPreview(); - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // mSelectedItems.front()->openItem(); + // } + // else + // { + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - // IT_{OBJECT,ATTACHMENT} creates LLProperties - // floaters; others create LLPreviews. Put - // each one in the right type of container. - LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); - bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - if (is_prop) - LLFloater::setFloaterHost(multi_propertiesp); - else - LLFloater::setFloaterHost(multi_previewp); - listener->openItem(); - } + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // listener->openItem(); + // } - LLFloater::setFloaterHost(NULL); - // *NOTE: LLMulti* will safely auto-delete when open'd - // without any children. - multi_previewp->openFloater(LLSD()); - multi_propertiesp->openFloater(LLSD()); - } - } + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + // } + //} } void LLFolderView::propertiesSelectedItems( void ) @@ -994,15 +976,6 @@ void LLFolderView::propertiesSelectedItems( void ) //} } -void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -{ - LLFolderBridge *folder_bridge = LLFolderBridge::sSelf.get(); - - if (!folder_bridge) return; - LLViewerInventoryCategory *cat = folder_bridge->getCategory(); - if (!cat) return; - cat->changeType(new_folder_type); -} void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { @@ -1521,7 +1494,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) } //do text search - if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) { mSearchString.clear(); } @@ -1831,81 +1804,6 @@ void LLFolderView::setShowSingleSelection(BOOL show) } } -bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) -{ - std::string action = userdata.asString(); - - if ("rename" == action) - { - startRenamingSelectedItem(); - return true; - } - if ("delete" == action) - { - removeSelectedItems(); - return true; - } - if (("copy" == action) || ("cut" == action)) - { - // Clear the clipboard before we start adding things on it - LLClipboard::instance().reset(); - } - - static const std::string change_folder_string = "change_folder_type_"; - if (action.length() > change_folder_string.length() && - (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) - { - LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); - changeType(model, new_folder_type); - return true; - } - - - std::set selected_items = getSelectionList(); - - LLMultiPreview* multi_previewp = NULL; - LLMultiProperties* multi_propertiesp = NULL; - - if (("task_open" == action || "open" == action) && selected_items.size() > 1) - { - multi_previewp = new LLMultiPreview(); - gFloaterView->addChild(multi_previewp); - - LLFloater::setFloaterHost(multi_previewp); - - } - else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) - { - multi_propertiesp = new LLMultiProperties(); - gFloaterView->addChild(multi_propertiesp); - - LLFloater::setFloaterHost(multi_propertiesp); - } - - std::set::iterator set_iter; - - for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) - { - LLFolderViewItem* folder_item = *set_iter; - if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); - if(!bridge) continue; - bridge->performAction(model, action); - } - - LLFloater::setFloaterHost(NULL); - if (multi_previewp) - { - multi_previewp->openFloater(LLSD()); - } - else if (multi_propertiesp) - { - multi_propertiesp->openFloater(LLSD()); - } - - return true; -} - static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8a0317f840..e098119293 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -39,20 +39,17 @@ #include "lluictrl.h" #include "v4color.h" -#include "lldarray.h" #include "stdenums.h" #include "lldepthstack.h" #include "lleditmenuhandler.h" #include "llfontgl.h" #include "llscrollcontainer.h" #include "lltooldraganddrop.h" -#include "llviewertexture.h" class LLFolderViewModelInterface; class LLFolderViewFolder; class LLFolderViewItem; class LLFolderViewFilter; -class LLInventoryModel; class LLPanel; class LLLineEditor; class LLMenuGL; @@ -153,8 +150,9 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set getSelectionList() const; + S32 getNumSelectedItems() { return mSelectedItems.size(); } - // Make sure if ancestor is selected, descendents are not + // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); virtual void clearSelection(); void addToSelectionList(LLFolderViewItem* item); @@ -173,9 +171,6 @@ public: void openSelectedItems( void ); void propertiesSelectedItems( void ); - // Change the folder type - void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); - void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); @@ -228,8 +223,6 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - bool doToSelected(LLInventoryModel* model, const LLSD& userdata); - void doIdle(); // Real idle routine static void idle(void* user_data); // static glue to doIdle() @@ -270,7 +263,6 @@ protected: BOOL addNoOptions(LLMenuGL* menu) const; - void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); protected: LLHandle mPopupMenuHandle; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 80893c3037..e84c765ac8 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -28,16 +28,9 @@ #include "llfolderviewitem.h" // viewer includes -#include "llfolderview.h" // Items depend extensively on LLFolderViews #include "llfolderview.h" #include "llfolderviewmodel.h" -#include "llviewerfoldertype.h" -#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" #include "llpanel.h" -#include "llviewercontrol.h" // gSavedSettings -#include "llviewerwindow.h" // Argh, only for setCursor() // linden library includes #include "llclipboard.h" @@ -529,11 +522,11 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) if (can_drag) { - gViewerWindow->setCursor(UI_CURSOR_ARROW); + getWindow()->setCursor(UI_CURSOR_ARROW); } else { - gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); + getWindow()->setCursor(UI_CURSOR_NOLOCKED); } return TRUE; } @@ -541,9 +534,9 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { if (getRoot()) { - getRoot()->setShowSelectionContext(FALSE); + getRoot()->setShowSelectionContext(FALSE); } - gViewerWindow->setCursor(UI_CURSOR_ARROW); + getWindow()->setCursor(UI_CURSOR_ARROW); // let parent handle this then... return FALSE; } @@ -2075,84 +2068,3 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it return result; } -bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const -{ - // ignore sort order for landmarks in the Favorites folder. - // they should be always sorted as in Favorites bar. See EXT-719 - //TODO RN: fix sorting in favorites folder - //if (a->getSortGroup() == SG_ITEM - // && b->getSortGroup() == SG_ITEM - // && a->getInventoryType() == LLInventoryType::IT_LANDMARK - // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) - //{ - - // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - // LLUUID a_uuid = a->getParentFolder()->getUUID(); - // LLUUID b_uuid = b->getParentFolder()->getUUID(); - - // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - // { - // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // // or to LLInvFVBridge - // LLViewerInventoryItem* aitem = (static_cast(a))->getItem(); - // LLViewerInventoryItem* bitem = (static_cast(b))->getItem(); - // if (!aitem || !bitem) - // return false; - // S32 a_sort = aitem->getSortField(); - // S32 b_sort = bitem->getSortField(); - // return a_sort < b_sort; - // } - //} - - // We sort by name if we aren't sorting by date - // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); - - if (a->getSortGroup() != b->getSortGroup()) - { - if (mSystemToTop) - { - // Group order is System Folders, Trash, Normal Folders, Items - return (a->getSortGroup() < b->getSortGroup()); - } - else if (mByDate) - { - // Trash needs to go to the bottom if we are sorting by date - if ( (a->getSortGroup() == SG_TRASH_FOLDER) - || (b->getSortGroup() == SG_TRASH_FOLDER)) - { - return (b->getSortGroup() == SG_TRASH_FOLDER); - } - } - } - - if (by_name) - { - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - if (0 == compare) - { - return (a->getCreationDate() > b->getCreationDate()); - } - else - { - return (compare < 0); - } - } - else - { - time_t first_create = a->getCreationDate(); - time_t second_create = b->getCreationDate(); - if (first_create == second_create) - { - return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); - } - else - { - return (first_create > second_create); - } - } -} - diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 581ec7239e..92923e82da 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -27,7 +27,6 @@ #define LLFOLDERVIEWITEM_H #include "llview.h" -#include "lldarray.h" // *TODO: Eliminate, forward declare #include "lluiimage.h" class LLFolderView; diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 8a16ec3eff..98b7255137 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -22,18 +22,11 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H +#ifndef LLFOLDERVIEWMODEL_H +#define LLFOLDERVIEWMODEL_H -#include "lldarray.h" // *TODO: convert to std::vector -#include "llfoldertype.h" #include "llfontgl.h" // just for StyleFlags enum #include "llfolderview.h" -#include "llfolderviewitem.h" -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" #include "lltooldraganddrop.h" // These are grouping of inventory types. @@ -362,4 +355,4 @@ protected: }; -#endif +#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 7ee1a10b15..99831c61bf 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -223,3 +223,84 @@ const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const return &mInventoryViewModel; } +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const +{ + // ignore sort order for landmarks in the Favorites folder. + // they should be always sorted as in Favorites bar. See EXT-719 + //TODO RN: fix sorting in favorites folder + //if (a->getSortGroup() == SG_ITEM + // && b->getSortGroup() == SG_ITEM + // && a->getInventoryType() == LLInventoryType::IT_LANDMARK + // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + //{ + + // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + + // LLUUID a_uuid = a->getParentFolder()->getUUID(); + // LLUUID b_uuid = b->getParentFolder()->getUUID(); + + // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) + // { + // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem + // // or to LLInvFVBridge + // LLViewerInventoryItem* aitem = (static_cast(a))->getItem(); + // LLViewerInventoryItem* bitem = (static_cast(b))->getItem(); + // if (!aitem || !bitem) + // return false; + // S32 a_sort = aitem->getSortField(); + // S32 b_sort = bitem->getSortField(); + // return a_sort < b_sort; + // } + //} + + // We sort by name if we aren't sorting by date + // OR if these are folders and we are sorting folders by name. + bool by_name = (!mByDate + || (mFoldersByName + && (a->getSortGroup() != SG_ITEM))); + + if (a->getSortGroup() != b->getSortGroup()) + { + if (mSystemToTop) + { + // Group order is System Folders, Trash, Normal Folders, Items + return (a->getSortGroup() < b->getSortGroup()); + } + else if (mByDate) + { + // Trash needs to go to the bottom if we are sorting by date + if ( (a->getSortGroup() == SG_TRASH_FOLDER) + || (b->getSortGroup() == SG_TRASH_FOLDER)) + { + return (b->getSortGroup() == SG_TRASH_FOLDER); + } + } + } + + if (by_name) + { + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + if (0 == compare) + { + return (a->getCreationDate() > b->getCreationDate()); + } + else + { + return (compare < 0); + } + } + else + { + time_t first_create = a->getCreationDate(); + time_t second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); + } + else + { + return (first_create > second_create); + } + } +} + diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ff461236a2..07f3dd8ffb 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -45,7 +45,7 @@ // newview includes #include "llappearancemgr.h" #include "llappviewer.h" -//#include "llfirstuse.h" +#include "llclipboard.h" #include "llfloaterinventory.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" @@ -74,8 +74,10 @@ #include "llsidepanelinventory.h" #include "lltabcontainer.h" #include "lltooldraganddrop.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llviewermessage.h" +#include "llviewerfoldertype.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -1044,3 +1046,87 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) } } +void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action) +{ + if ("rename" == action) + { + root->startRenamingSelectedItem(); + return; + } + if ("delete" == action) + { + LLSD args; + args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" : "DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); + return; + } + if (("copy" == action) || ("cut" == action)) + { + // Clear the clipboard before we start adding things on it + LLClipboard::instance().reset(); + } + + static const std::string change_folder_string = "change_folder_type_"; + if (action.length() > change_folder_string.length() && + (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) + { + LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); + LLFolderViewModelItemInventory* inventory_item = static_cast(root->getViewModelItem()); + LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID()); + if (!cat) return; + cat->changeType(new_folder_type); + return; + } + + + std::set selected_items = root->getSelectionList(); + + LLMultiPreview* multi_previewp = NULL; + LLMultiProperties* multi_propertiesp = NULL; + + if (("task_open" == action || "open" == action) && selected_items.size() > 1) + { + multi_previewp = new LLMultiPreview(); + gFloaterView->addChild(multi_previewp); + + LLFloater::setFloaterHost(multi_previewp); + + } + else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) + { + multi_propertiesp = new LLMultiProperties(); + gFloaterView->addChild(multi_propertiesp); + + LLFloater::setFloaterHost(multi_propertiesp); + } + + std::set::iterator set_iter; + + for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) + { + LLFolderViewItem* folder_item = *set_iter; + if(!folder_item) continue; + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); + if(!bridge) continue; + bridge->performAction(model, action); + } + + LLFloater::setFloaterHost(NULL); + if (multi_previewp) + { + multi_previewp->openFloater(LLSD()); + } + else if (multi_propertiesp) + { + multi_propertiesp->openFloater(LLSD()); + } +} + +void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + root->removeSelectedItems(); + } +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index c6b1da0417..d8d3d9bbbb 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -427,6 +427,13 @@ public: static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction }; +struct LLInventoryAction +{ + static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); + + static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root); +}; + #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index b5fcf364dd..ef8c5dc1cf 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -44,6 +44,7 @@ #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" +#include "llpreview.h" #include "llsidepanelinventory.h" #include "llviewerattachmenu.h" #include "llviewerfoldertype.h" @@ -926,11 +927,6 @@ void LLInventoryPanel::onSelectionChange(const std::deque& it } } -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ - mFolderRoot->doToSelected(&gInventory, userdata); -} - void LLInventoryPanel::doCreate(const LLSD& userdata) { menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata); @@ -1260,6 +1256,13 @@ void LLInventoryPanel::updateSelection() } } +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ + LLInventoryAction::doToSelected(mInventory, mFolderRoot, userdata.asString()); + + return; +} + /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a62b97aa7d..58c1201e54 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -176,7 +176,7 @@ public: LLFolderViewFolder* getFolderByID(const LLUUID& id); void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); void updateSelection(); - + LLFolderViewModelInventory* getFolderViewModel(); const LLFolderViewModelInventory* getFolderViewModel() const; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 0b899d34f4..faef923338 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -851,7 +851,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const } else { - mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name); + mCurrentSelectedList->doToSelected(command_name); } } @@ -896,7 +896,7 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) { if(mCurrentSelectedList) { - mCurrentSelectedList->getRootFolder()->doToSelected(&gInventory, userdata); + mCurrentSelectedList->doToSelected(userdata); } } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 6cef1f877b..fea27b37d3 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -294,7 +294,7 @@ BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) void LLPanelMainInventory::doToSelected(const LLSD& userdata) { - getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); + getPanel()->doToSelected(userdata); } void LLPanelMainInventory::closeAllFolders() @@ -970,7 +970,7 @@ void LLPanelMainInventory::onTrashButtonClick() void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); - getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); + getActivePanel()->doToSelected(command_name); } void LLPanelMainInventory::saveTexture(const LLSD& userdata) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 450e1f7ed0..002c0c1113 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1522,7 +1522,7 @@ BOOL LLPanelObjectInventory::postBuild() void LLPanelObjectInventory::doToSelected(const LLSD& userdata) { - mFolders->doToSelected(&gInventory, userdata); + LLInventoryAction::doToSelected(&gInventory, mFolders, userdata.asString()); } void LLPanelObjectInventory::clearContents() -- cgit v1.2.3 From ad1f2eb5106a9ba0217ff1080d029f912ecc25e5 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 3 Jul 2012 22:31:58 +0300 Subject: CHUI-186 CHUI-187 FIX Removing a P2P convrsation from converstaion widget in the upper right corner when a new participant is added. End call prompt removed when adding a new participant to a P2P voice call. After adding a participant to a P2P voice conversation the resulting conference call is restarted voice invites to all participants. --- indra/newview/llavataractions.cpp | 4 +- indra/newview/llavataractions.h | 4 +- indra/newview/llimfloater.cpp | 73 ++++++++++++++++++++---------------- indra/newview/llimfloater.h | 2 +- indra/newview/llpanelpeoplemenus.cpp | 2 +- 5 files changed, 46 insertions(+), 39 deletions(-) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 21367c224d..56c9533e11 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -235,7 +235,7 @@ void LLAvatarActions::startCall(const LLUUID& id) } // static -void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) +void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id) { if (ids.size() == 0) { @@ -252,7 +252,7 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) // create the new ad hoc voice session const std::string title = LLTrans::getString("conference-title"); LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, - ids[0], id_array, true); + ids[0], id_array, true, floater_id); if (session_id == LLUUID::null) { return; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 46830eb22c..259e87c336 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -82,9 +82,9 @@ public: static void startCall(const LLUUID& id); /** - * Start an ad-hoc conference voice call with multiple users + * Start an ad-hoc conference voice call with multiple users in a specific IM floater. */ - static void startAdhocCall(const uuid_vec_t& ids); + static void startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); /** * Start conference chat with the given avatars in a specific IM floater. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9d3c0f98ce..536d0b9a23 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -322,7 +322,7 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::onAvatarPicked, this, _1, _2), TRUE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); if (!picker) { return; @@ -337,25 +337,6 @@ void LLIMFloater::onAddButtonClicked() } } -void LLIMFloater::onAvatarPicked(const uuid_vec_t& ids, const std::vector names) -{ - if (mIsP2PChat) - { - mStartConferenceInSameFloater = true; - onClose(false); - - uuid_vec_t temp_ids; - temp_ids.push_back(mOtherParticipantUUID); - temp_ids.insert(temp_ids.end(), ids.begin(), ids.end()); - - LLAvatarActions::startConference(temp_ids, mSessionID); - } - else - { - inviteToSession(ids); - } -} - bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) { if (!mSession @@ -388,6 +369,44 @@ bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) return true; } +void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) +{ + if (mIsP2PChat) + { + mStartConferenceInSameFloater = true; + + uuid_vec_t temp_ids; + + // Add the initial participant of a P2P session + temp_ids.push_back(mOtherParticipantUUID); + temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + // first check whether this is a voice session + bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + + // then we can close the current session + gIMMgr->leaveSession(mSessionID); + LLIMConversation::onClose(false); + + // Start a new ad hoc voice call if we invite new participants to a P2P call, + // or start a text chat otherwise. + if (is_voice_call) + { + LLAvatarActions::startAdhocCall(temp_ids, mSessionID); + } + else + { + LLAvatarActions::startConference(temp_ids, mSessionID); + } + } + else + { + inviteToSession(uuids); + } +} + void LLIMFloater::boundVoiceChannel() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); @@ -1096,19 +1115,7 @@ bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop) res = canAddSelectedToChat(ids); if(res && drop) { - if (mIsP2PChat) - { - mStartConferenceInSameFloater = true; - onClose(false); - - ids.push_back(mOtherParticipantUUID); - - LLAvatarActions::startConference(ids, mSessionID); - } - else - { - inviteToSession(ids); - } + addSessionParticipants(ids); } } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 23f9e75e21..2e8fc84746 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -152,7 +152,7 @@ private: static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); void setTyping(bool typing); void onAddButtonClicked(); - void onAvatarPicked(const uuid_vec_t& ids, const std::vector names); + void addSessionParticipants(const uuid_vec_t& uuids); bool canAddSelectedToChat(const uuid_vec_t& uuids); void onCallButtonClicked(); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index ac2109dda4..c9eebe24d3 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -82,7 +82,7 @@ LLContextMenu* NearbyMenu::createMenu() // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null)); - registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs)); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null)); registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs)); // registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented -- cgit v1.2.3 From ac0243a006fa28e872e4ee88f7c1588eaefeaecf Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 3 Jul 2012 22:32:21 +0300 Subject: CHUI-188 FIX for crash in adding chat participants. Modified the duplicated participants check procedure LLIMFloater::canAddSelectedToChat() to use the list, updated by LLSpeakerMgr instead of LLIMSession::mInitialTargetIDs list, which is initialized at session start and not updated afterwards. --- indra/newview/llimfloater.cpp | 72 +++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 536d0b9a23..a506f0f9f3 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -339,34 +339,54 @@ void LLIMFloater::onAddButtonClicked() bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) { - if (!mSession - || mDialog == IM_SESSION_GROUP_START - || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) - { - return false; - } + if (!mSession + || mDialog == IM_SESSION_GROUP_START + || mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) + { + return false; + } - for (uuid_vec_t::const_iterator id = uuids.begin(); - id != uuids.end(); ++id) - { - // Skip this check for ad hoc conferences, - // conference participants should be listed in mSession->mInitialTargetIDs. - if (mIsP2PChat && *id == mOtherParticipantUUID) - { - return false; - } - - for (uuid_vec_t::const_iterator target_id = mSession->mInitialTargetIDs.begin(); - target_id != mSession->mInitialTargetIDs.end(); ++target_id) - { - if (*id == *target_id) - { - return false; - } - } - } + if (mIsP2PChat) + { + // For a P2P session just check if we are not adding the other participant. + + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + if (*id == mOtherParticipantUUID) + { + return false; + } + } + } + else + { + // For a conference session we need to check against the list from LLSpeakerMgr, + // because this list may change when participants join or leave the session. + + LLSpeakerMgr::speaker_list_t speaker_list; + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->getSpeakerList(&speaker_list, true); + } - return true; + for (uuid_vec_t::const_iterator id = uuids.begin(); + id != uuids.end(); ++id) + { + for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); + it != speaker_list.end(); ++it) + { + const LLPointer& speaker = *it; + if (*id == speaker->mID) + { + return false; + } + } + } + } + + return true; } void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) -- cgit v1.2.3 From a8defa513c3b2b83f476a1de115fd0332566b483 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 3 Jul 2012 17:05:28 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose removed viewer dependencies from folderview code --- indra/newview/llfolderview.cpp | 84 +++++++++---------------------------- indra/newview/llfolderview.h | 5 +-- indra/newview/llfolderviewitem.cpp | 10 ----- indra/newview/llfolderviewmodel.cpp | 3 +- indra/newview/llfolderviewmodel.h | 1 - indra/newview/llinventorybridge.cpp | 6 +-- indra/newview/llinventorypanel.cpp | 11 +++++ indra/newview/llinventorypanel.h | 79 +--------------------------------- 8 files changed, 36 insertions(+), 163 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6bc89cdbca..10677db094 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -27,25 +27,18 @@ #include "llviewerprecompiledheaders.h" #include "llfolderview.h" - +#include "llfolderviewmodel.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" #include "llpanel.h" #include "llscrollcontainer.h" // hack to allow scrolling +#include "lltextbox.h" #include "lltrans.h" #include "llui.h" #include "lluictrlfactory.h" -// TODO RN: kill these -// newview includes -#include "llcallbacklist.h" // per-frame on-idle -#include "llfloaterproperties.h" // showProperties -#include "llviewerwindow.h" // renamer popup handling -#include "llpreview.h" // openSelectedItems -#include "llinventorypanel.h" // idle loop for filtering, sort order declarations, etc. - // Linden library includes #include "lldbstrings.h" #include "llfocusmgr.h" @@ -172,7 +165,6 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoSelect( FALSE ), mAutoSelectOverride(FALSE), mNeedsAutoRename(FALSE), - mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -199,7 +191,6 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; mIndentation = p.folder_indentation; - gIdleCallbacks.addFunction(idle, this); //clear label // go ahead and render root folder as usual @@ -269,7 +260,6 @@ LLFolderView::~LLFolderView( void ) mStatusTextBox = NULL; mAutoOpenItems.removeAllNodes(); - gIdleCallbacks.deleteFunction(idle, this); if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); @@ -291,16 +281,16 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { LLFolderViewFolder::addFolder(folder); - mFolders.remove(folder); - // enforce sort order of My Inventory followed by Library - if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - { - mFolders.push_back(folder); - } - else - { - mFolders.insert(mFolders.begin(), folder); - } + // TODO RN: enforce sort order of My Inventory followed by Library + //mFolders.remove(folder); + //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) + //{ + // mFolders.push_back(folder); + //} + //else + //{ + // mFolders.insert(mFolders.begin(), folder); + //} return TRUE; } @@ -754,7 +744,7 @@ void LLFolderView::closeRenamer( void ) if (mRenamer && mRenamer->getVisible()) { // Triggers onRenamerLost() that actually closes the renamer. - gViewerWindow->removePopup(mRenamer); + LLUI::removePopup(mRenamer); } } @@ -785,24 +775,6 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector exit - if (!LLClipboard::instance().isCutMode()) - return; - - // Get the list of clipboard item uuids and iterate through them - LLDynamicArray objects; - LLClipboard::instance().pasteFromClipboard(objects); - for (LLDynamicArray::const_iterator iter = objects.begin(); - iter != objects.end(); - ++iter) - { - gInventory.removeObject(*iter); - } -} - void LLFolderView::removeSelectedItems() { if(getVisible() && getEnabled()) @@ -1126,9 +1098,9 @@ void LLFolderView::cut() if(listener) { listener->cutToClipboard(); + listener->removeItem(); } } - LLFolderView::removeCutItems(); } mSearchString.clear(); } @@ -1222,7 +1194,7 @@ void LLFolderView::startRenamingSelectedItem( void ) // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - gViewerWindow->addPopup(mRenamer); + LLUI::addPopup(mRenamer); } } @@ -1808,16 +1780,10 @@ static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); // Main idle routine -void LLFolderView::doIdle() +void LLFolderView::update() { // If this is associated with the user's inventory, don't do anything // until that inventory is loaded up. - const LLInventoryPanel *inventory_panel = dynamic_cast(mParentPanel); - if (inventory_panel && !inventory_panel->getIsViewsInitialized()) - { - return; - } - LLFastTimer t2(FTM_INVENTORY); if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) @@ -1859,8 +1825,8 @@ void LLFolderView::doIdle() BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished - || gFocusMgr.childHasKeyboardFocus(inventory_panel) - || gFocusMgr.childHasMouseCapture(inventory_panel)) + || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container + || gFocusMgr.childHasMouseCapture(getParent())) { // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process mNeedsAutoSelect = FALSE; @@ -1919,7 +1885,6 @@ void LLFolderView::doIdle() constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } - BOOL is_visible = isInVisibleChain(); if ( is_visible ) @@ -1954,17 +1919,6 @@ void LLFolderView::doIdle() mSignalSelectCallback = FALSE; } - -//static -void LLFolderView::idle(void* user_data) -{ - LLFolderView* self = (LLFolderView*)user_data; - if ( self ) - { // Do the real idle - self->doIdle(); - } -} - void LLFolderView::dumpSelectionInformation() { llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; @@ -1988,7 +1942,7 @@ void LLFolderView::updateRenamerPosition() screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0); + LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); if (mScrollContainer) { scroller_rect = mScrollContainer->getContentWindowRect(); diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index e098119293..78f1d8aff2 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -165,7 +165,6 @@ public: // Deletion functionality void removeSelectedItems(); - static void removeCutItems(); // Open the selected item void openSelectedItems( void ); @@ -223,8 +222,7 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - void doIdle(); // Real idle routine - static void idle(void* user_data); // static glue to doIdle() + void update(); // needs to be called periodically (e.g. once per frame) BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } BOOL needsAutoRename() { return mNeedsAutoRename; } @@ -288,7 +286,6 @@ protected: bool mUseLabelSuffix; bool mShowItemLinkOverlays; - U32 mSortOrder; LLDepthStack mAutoOpenItems; LLFolderViewFolder* mAutoOpenCandidate; LLFrameTimer mAutoOpenTimer; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 3937d4332b..dee3fe7218 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -1798,16 +1798,6 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { - /* Disable outfit double click to wear - const LLUUID &cat_uuid = getViewModelItem()->getUUID(); - const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); - if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) - { - getViewModelItem()->performAction(NULL, NULL,"replaceoutfit"); - return TRUE; - } - */ - BOOL handled = FALSE; if( isOpen() ) { diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp index 92db84156e..ca6225aca7 100644 --- a/indra/newview/llfolderviewmodel.cpp +++ b/indra/newview/llfolderviewmodel.cpp @@ -28,7 +28,6 @@ #include "llfolderviewmodel.h" #include "lltrans.h" -#include "llviewercontrol.h" bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) { @@ -49,6 +48,6 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - getFilter()->setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); + getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); mFolderView->getViewModelItem()->filter(*getFilter()); } diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h index 98b7255137..079409c2a4 100644 --- a/indra/newview/llfolderviewmodel.h +++ b/indra/newview/llfolderviewmodel.h @@ -27,7 +27,6 @@ #include "llfontgl.h" // just for StyleFlags enum #include "llfolderview.h" -#include "lltooldraganddrop.h" // These are grouping of inventory types. // Order matters when sorting system folders to the top. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 002278601a..d17c25d9f3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1400,7 +1400,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); + gInventory.removeObject(mUUID); return; } else if ("copy" == action) @@ -1680,14 +1680,12 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) return FALSE; } - BOOL LLItemBridge::removeItem() { if(!isItemRemovable()) { return FALSE; } - // move it to the trash LLPreview::hide(mUUID, TRUE); @@ -2870,7 +2868,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) else if ("cut" == action) { cutToClipboard(); - LLFolderView::removeCutItems(); + gInventory.removeObject(mUUID); return; } else if ("copy" == action) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index c1ffe89184..fed9893158 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -258,6 +258,8 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { + gIdleCallbacks.deleteFunction(idle, this); + U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); if (mSortOrderSetting != INHERIT_SORT_ORDER) { @@ -566,12 +568,21 @@ void LLInventoryPanel::onIdle(void *userdata) } } +void LLInventoryPanel::idle(void* user_data) +{ + LLInventoryPanel* panel = (LLInventoryPanel*)user_data; + panel->mFolderRoot->doIdle(); +} + + void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; rebuildViewsFor(gInventory.getRootFolderID()); + gIdleCallbacks.addFunction(idle, this); + mViewsInitialized = true; openStartFolderOrMyInventory(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 1061f12575..465ccdd582 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -45,82 +45,6 @@ class LLInventoryFVBridgeBuilder; class LLInvPanelComplObserver; class LLFolderViewModelInventory; -class LLFolderViewModelItemInventory - : public LLFolderViewModelItemCommon -{ -public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) - {} - void setRootViewModel(LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual void setCreationDate(time_t creation_date_utc) = 0; - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL isUpToDate() const = 0; - virtual bool hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - virtual EInventorySortGroup getSortGroup() const = 0; - virtual LLInventoryObject* getInventoryObject() const = 0; - virtual void requestSort(); - virtual bool potentiallyVisible(); - virtual bool passedFilter(S32 filter_generation = -1); - virtual bool descendantsPassedFilter(S32 filter_generation = -1); - virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); -protected: - LLFolderViewModelInventory* mRootViewModel; -}; - -class LLInventorySort -{ -public: - LLInventorySort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) - { - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - } - - bool isByDate() const { return mByDate; } - U32 getSortOrder() const { return mSortOrder; } - - bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; - -class LLFolderViewModelInventory - : public LLFolderViewModel -{ -public: - typedef LLFolderViewModel base_t; - - virtual ~LLFolderViewModelInventory() {} - - void sort(LLFolderViewFolder* folder); - - bool contentsReady(); - -}; - - class LLInventoryPanel : public LLPanel { //-------------------------------------------------------------------- @@ -232,7 +156,8 @@ public: void doCreate(const LLSD& userdata); bool beginIMSession(); bool attachObject(const LLSD& userdata); - + static void idle(void* user_data); + // DEBUG ONLY: static void dumpSelectionInformation(void* user_data); -- cgit v1.2.3 From 52bf9e20454181d8acb0ac419a882cc1a0e3af9e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 3 Jul 2012 18:11:14 -0700 Subject: CHUI-174 : Fixed crash in forced response to notifications. Use an empty form in that case and allow the notification to not be in the notifications list. --- indra/newview/llviewermessage.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dd78bbd491..7e1f186769 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1481,7 +1481,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& } LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - llassert(notification_ptr != NULL); // For muting, we need to add the mute, then decline the offer. // This must be done here because: @@ -1504,7 +1503,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& bool busy = gAgent.getBusy(); - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); switch(button) { @@ -1550,7 +1549,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& break; } - modified_form->setElementEnabled("Show", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Show", false); + } break; // end switch (mIM) @@ -1567,7 +1569,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& break; case IOR_MUTE: - modified_form->setElementEnabled("Mute", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Mute", false); + } // MUTE falls through to decline case IOR_DECLINE: { @@ -1604,8 +1609,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& busy_message(gMessageSystem, mFromID); } - modified_form->setElementEnabled("Show", false); - modified_form->setElementEnabled("Discard", false); + if (modified_form != NULL) + { + modified_form->setElementEnabled("Show", false); + modified_form->setElementEnabled("Discard", false); + } break; } @@ -1627,8 +1635,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& delete this; } - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + if (notification_ptr != NULL) + { + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + } return false; } -- cgit v1.2.3 From 189f9be7bb20bbe43c9c3060fe36cc9d867af01d Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 4 Jul 2012 01:30:55 +0000 Subject: Adding initial debian packaging configuration --- debian/changelog | 18 ++++++++++ debian/compat | 1 + debian/control | 16 +++++++++ debian/copyright | 7 ++++ debian/postinst | 43 ++++++++++++++++++++++ debian/postrm | 41 +++++++++++++++++++++ debian/preinst | 39 ++++++++++++++++++++ debian/prerm | 42 ++++++++++++++++++++++ debian/rules | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 314 insertions(+) create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/postinst create mode 100644 debian/postrm create mode 100644 debian/preinst create mode 100644 debian/prerm create mode 100755 debian/rules diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000000..ce54b54c6f --- /dev/null +++ b/debian/changelog @@ -0,0 +1,18 @@ +secondlife-viewer (0.3) unstable; urgency=low + + * Initial debian configuration + + -- Don Kjer Wed, 04 Jul 2012 00:43:03 +0000 + +secondlife-viewer (0.2) unstable; urgency=low + + * Adding default LSB headers for squeeze + + -- Tyler Kohler Thu, 24 Mar 2011 09:43:36 -0700 + +secondlife-viewer (0.1) unstable; urgency=low + + * Cloned from debian package skeleton. + + -- Lex Linden Mon, 20 Sep 2010 08:01:59 -0700 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000000..7ed6ff82de --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000..50b9ed9a26 --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: secondlife-viewer +Section: unknown +Priority: extra +Maintainer: Don Linden +Build-Depends: debhelper (>= 5) +Homepage: http://secondlife.com +Standards-Version: 3.7.2 + +Package: secondlife-viewer +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + ia32-libs, + ia32-libs-gtk +Description: Second Life Viewer + Second Life is an online virtual world developed by Linden Lab. + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000000..ecfceb3927 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,7 @@ +Copyright: 2012 Linden Research, Inc. + +License: + +No license to distribute, copy, modify, or make derivitave works of this +software is granted unless specifically granted in writing by Linden Research, +Inc. diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000000..2c4f8ea858 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,43 @@ +#!/bin/sh +# postinst script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000000..a575936ab0 --- /dev/null +++ b/debian/postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000000..f62243440f --- /dev/null +++ b/debian/preinst @@ -0,0 +1,39 @@ +#!/bin/sh +# preinst script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/prerm b/debian/prerm new file mode 100644 index 0000000000..405b8f9c87 --- /dev/null +++ b/debian/prerm @@ -0,0 +1,42 @@ +#!/bin/sh +# prerm script for secondlife-viewer +# +# Delete this file if you don't need it. +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. Don't delete this! + +#DEBHELPER# + +exit 0 + + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000000..eedeeef879 --- /dev/null +++ b/debian/rules @@ -0,0 +1,107 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +SRCDIR=build-linux-i686/newview/packaged +DESTDIR=$(CURDIR)/debian/secondlife-viewer +INSTALLDIR=opt/linden/viewer + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + #$(MAKE) + #docbook-to-man debian/secondlife-viewer.sgml > secondlife-viewer.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + #-$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/secondlife-viewer. + #$(MAKE) DESTDIR=$(CURDIR)/debian/secondlife-viewer install + for file in $$(find $(SRCDIR) -type f | sed 's~$(SRCDIR)/~~'); do \ + # create containing directory \ + install -v -m 755 -o root -g root -d "$$(dirname "$(DESTDIR)/$(INSTALLDIR)/$$file")"; \ + PERM=644; \ + if [ -x "$(SRCDIR)/$$file" ]; then \ + PERM=755; \ + fi; \ + install -v -m $$PERM -o root -g root "$(SRCDIR)/$$file" "$(DESTDIR)/$(INSTALLDIR)/$$file"; \ + done + dh_link /$(INSTALLDIR)/secondlife /usr/bin/secondlife + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python + +# To add an init script, uncomment this line and edit debian/init.d and +# customize debian/secondlife-viewer.default to suit your needs. +# dh_installinit + +# To add cron jobs, uncomment this line and make a crontab file named +# debian/cron.d, and it will be installed in /etc/cron.d/ +# dh_installcron + +# dh_installinfo + dh_installman + dh_link +# dh_strip + dh_compress +# dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb +# dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure -- cgit v1.2.3 From cea3c37dcb09eb30cb986ecac4d29a4ff1cc0898 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 3 Jul 2012 19:58:49 -0700 Subject: CHUI-164 : Fix crash when closing conversations using the conversation widget. Populated the sessionRemoved() method with code to close the floater and clean up the list. --- indra/newview/llimfloatercontainer.cpp | 11 +++++++++-- indra/newview/llimfloatercontainer.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 261b5f33a2..08ace601a3 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -73,8 +73,15 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::show(session_id); -}; + LLIMFloater::show(session_id); +} + +void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) +{ + LLIMFloater* floaterp = LLIMFloater::findInstance(session_id); + LLFloater::onClickClose(floaterp); + removeConversationListItem(floaterp); +} BOOL LLIMFloaterContainer::postBuild() { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2bbd371e8f..c062127bee 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -158,7 +158,7 @@ public: // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); - /*virtual*/ void sessionRemoved(const LLUUID& session_id) {}; + /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; private: -- cgit v1.2.3 From 1494a1058f41c5aa00a8ed08fe71123f63e92e81 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 3 Jul 2012 23:55:39 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose move llfolderview* into LLUI! --- indra/llui/CMakeLists.txt | 6 + indra/llui/llfolderview.cpp | 2078 +++++++++++++++++++++++++ indra/llui/llfolderview.h | 388 +++++ indra/llui/llfolderviewitem.cpp | 2032 +++++++++++++++++++++++++ indra/llui/llfolderviewitem.h | 420 +++++ indra/llui/llfolderviewmodel.cpp | 53 + indra/llui/llfolderviewmodel.h | 353 +++++ indra/newview/CMakeLists.txt | 6 - indra/newview/llfolderview.cpp | 2105 -------------------------- indra/newview/llfolderview.h | 393 ----- indra/newview/llfolderviewitem.cpp | 2060 ------------------------- indra/newview/llfolderviewitem.h | 418 ----- indra/newview/llfolderviewmodel.cpp | 53 - indra/newview/llfolderviewmodel.h | 357 ----- indra/newview/llfolderviewmodelinventory.cpp | 26 + indra/newview/llfolderviewmodelinventory.h | 13 +- indra/newview/llimfloatercontainer.h | 9 - indra/newview/llinventorybridge.h | 3 +- indra/newview/llinventorypanel.cpp | 19 +- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/lltexturectrl.cpp | 1 + 21 files changed, 5389 insertions(+), 5406 deletions(-) create mode 100644 indra/llui/llfolderview.cpp create mode 100644 indra/llui/llfolderview.h create mode 100644 indra/llui/llfolderviewitem.cpp create mode 100644 indra/llui/llfolderviewitem.h create mode 100644 indra/llui/llfolderviewmodel.cpp create mode 100644 indra/llui/llfolderviewmodel.h delete mode 100644 indra/newview/llfolderview.cpp delete mode 100644 indra/newview/llfolderview.h delete mode 100644 indra/newview/llfolderviewitem.cpp delete mode 100644 indra/newview/llfolderviewitem.h delete mode 100644 indra/newview/llfolderviewmodel.cpp delete mode 100644 indra/newview/llfolderviewmodel.h diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index b50ed2342d..a9ad0a3c0b 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -54,6 +54,9 @@ set(llui_SOURCE_FILES llfloaterreglistener.cpp llflyoutbutton.cpp llfocusmgr.cpp + llfolderview.cpp + llfolderviewitem.cpp + llfolderviewmodel.cpp llfunctorregistry.cpp lliconctrl.cpp llkeywords.cpp @@ -154,6 +157,9 @@ set(llui_HEADER_FILES llfloaterreglistener.h llflyoutbutton.h llfocusmgr.h + llfolderview.h + llfolderviewitem.h + llfolderviewmodel.h llfunctorregistry.h llhandle.h llhelp.h diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp new file mode 100644 index 0000000000..0d3bc44ae4 --- /dev/null +++ b/indra/llui/llfolderview.cpp @@ -0,0 +1,2078 @@ +/** + * @file llfolderview.cpp + * @brief Implementation of the folder view collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llclipboard.h" // *TODO: remove this once hack below gone. +#include "llkeyboard.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpanel.h" +#include "llscrollcontainer.h" // hack to allow scrolling +#include "lltextbox.h" +#include "lltrans.h" +#include "llui.h" +#include "lluictrlfactory.h" + +// Linden library includes +#include "lldbstrings.h" +#include "llfocusmgr.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llrender.h" + +// Third-party library includes +#include + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +const S32 RENAME_WIDTH_PAD = 4; +const S32 RENAME_HEIGHT_PAD = 1; +const S32 AUTO_OPEN_STACK_DEPTH = 16; +const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + + LLFolderViewItem::ICON_PAD + + LLFolderViewItem::ARROW_SIZE + + LLFolderViewItem::TEXT_PAD + + /*first few characters*/ 40; +const S32 MINIMUM_RENAMER_WIDTH = 80; + +// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. +const S32 STATUS_TEXT_HPAD = 6; +const S32 STATUS_TEXT_VPAD = 8; + +enum { + SIGNAL_NO_KEYBOARD_FOCUS = 1, + SIGNAL_KEYBOARD_FOCUS = 2 +}; + +F32 LLFolderView::sAutoOpenTime = 1.f; + +//--------------------------------------------------------------------------- + +// Tells all folders in a folderview to close themselves +// For efficiency, calls setOpenArrangeRecursively(). +// The calling function must then call: +// LLFolderView* root = getRoot(); +// if( root ) +// { +// root->arrange( NULL, NULL ); +// root->scrollToShowSelection(); +// } +// to patch things up. +class LLCloseAllFoldersFunctor : public LLFolderViewFunctor +{ +public: + LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } + virtual ~LLCloseAllFoldersFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + + BOOL mOpen; +}; + + +void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) +{ + folder->setOpenArrangeRecursively(mOpen); +} + +// Do nothing. +void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) +{ } + +///---------------------------------------------------------------------------- +/// Class LLFolderViewScrollContainer +///---------------------------------------------------------------------------- + +// virtual +const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const +{ + LLRect rect = LLRect::null; + if (mScrolledView) + { + LLFolderView* folder_view = dynamic_cast(mScrolledView); + if (folder_view) + { + S32 height = folder_view->getRect().getHeight(); + + rect = mScrolledView->getRect(); + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); + } + } + + return rect; +} + +LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) +: LLScrollContainer(p) +{} + +///---------------------------------------------------------------------------- +/// Class LLFolderView +///---------------------------------------------------------------------------- +LLFolderView::Params::Params() +: title("title"), + use_label_suffix("use_label_suffix"), + allow_multiselect("allow_multiselect", true), + show_empty_message("show_empty_message", true), + use_ellipses("use_ellipses", false) +{ + folder_indentation = -4; +} + + +// Default constructor +LLFolderView::LLFolderView(const Params& p) +: LLFolderViewFolder(p), + mScrollContainer( NULL ), + mPopupMenuHandle(), + mAllowMultiSelect(p.allow_multiselect), + mShowEmptyMessage(p.show_empty_message), + mShowFolderHierarchy(FALSE), + mRenameItem( NULL ), + mNeedsScroll( FALSE ), + mUseLabelSuffix(p.use_label_suffix), + mPinningSelectedItem(FALSE), + mNeedsAutoSelect( FALSE ), + mAutoSelectOverride(FALSE), + mNeedsAutoRename(FALSE), + mShowSelectionContext(FALSE), + mShowSingleSelection(FALSE), + mArrangeGeneration(0), + mSignalSelectCallback(0), + mMinWidth(0), + mDragAndDropThisFrame(FALSE), + mCallbackRegistrar(NULL), + mParentPanel(p.parent_panel), + mUseEllipses(p.use_ellipses), + mDraggingOverItem(NULL), + mStatusTextBox(NULL), + mShowItemLinkOverlays(p.show_item_link_overlays), + mViewModel(p.view_model) +{ + mViewModel->setFolderView(this); + mRoot = this; + + LLRect rect = p.rect; + LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); + setRect( rect ); + reshape(rect.getWidth(), rect.getHeight()); + mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); + mKeyboardSelection = FALSE; + mIndentation = p.folder_indentation; + + //clear label + // go ahead and render root folder as usual + // just make sure the label ("Inventory Folder") never shows up + mLabel = LLStringUtil::null; + + // Escape is handled by reverting the rename, not commiting it (default behavior) + LLLineEditor::Params params; + params.name("ren"); + params.rect(rect); + params.font(getLabelFontForStyle(LLFontGL::NORMAL)); + params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); + params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); + params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); + params.commit_on_focus_lost(true); + params.visible(false); + mRenamer = LLUICtrlFactory::create (params); + addChild(mRenamer); + + // Textbox + LLTextBox::Params text_p; + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + LLRect new_r = LLRect(rect.mLeft + ICON_PAD, + rect.mTop - TEXT_PAD, + rect.mRight, + rect.mTop - TEXT_PAD - font->getLineHeight()); + text_p.rect(new_r); + text_p.name(std::string(p.name)); + text_p.font(font); + text_p.visible(false); + text_p.parse_urls(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); + mStatusTextBox = LLUICtrlFactory::create (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + //addChild(mStatusTextBox); + + + // make the popup menu available + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + + mViewModelItem->openItem(); +} + +// Destroys the object +LLFolderView::~LLFolderView( void ) +{ + closeRenamer(); + + // The release focus call can potentially call the + // scrollcontainer, which can potentially be called with a partly + // destroyed scollcontainer. Just null it out here, and no worries + // about calling into the invalid scroll container. + // Same with the renamer. + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + mAutoOpenItems.removeAllNodes(); + + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + + mAutoOpenItems.removeAllNodes(); + clearSelection(); + mItems.clear(); + mFolders.clear(); + + delete mViewModel; + mViewModel = NULL; +} + +BOOL LLFolderView::canFocusChildren() const +{ + return FALSE; +} + +BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) +{ + LLFolderViewFolder::addFolder(folder); + + // TODO RN: enforce sort order of My Inventory followed by Library + //mFolders.remove(folder); + //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) + //{ + // mFolders.push_back(folder); + //} + //else + //{ + // mFolders.insert(mFolders.begin(), folder); + //} + + return TRUE; +} + +void LLFolderView::closeAllFolders() +{ + // Close all the folders + setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + arrangeAll(); +} + +void LLFolderView::openTopLevelFolders() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpen(TRUE); + } +} + +// This view grows and shrinks to enclose all of its children items and folders. +// *width should be 0 +// conform show folder state works +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) +{ + mMinWidth = 0; + S32 target_height; + + LLFolderViewFolder::arrange(&mMinWidth, &target_height); + + LLRect scroll_rect = mScrollContainer->getContentWindowRect(); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); + + LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); + if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) + { + reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); + } + + // move item renamer text field to item's new position + updateRenamerPosition(); + + return llround(mTargetHeight); +} + +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); + +void LLFolderView::filter( LLFolderViewFilter& filter ) +{ + LLFastTimer t2(FTM_FILTER); + filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); + + getViewModelItem()->filter(filter); +} + +void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLRect scroll_rect; + if (mScrollContainer) + { + LLView::reshape(width, height, called_from_parent); + scroll_rect = mScrollContainer->getContentWindowRect(); + } + width = llmax(mMinWidth, scroll_rect.getWidth()); + height = llmax(llround(mCurHeight), scroll_rect.getHeight()); + + // Restrict width within scroll container's width + if (mUseEllipses && mScrollContainer) + { + width = scroll_rect.getWidth(); + } + + LLView::reshape(width, height, called_from_parent); + mReshapeSignal(mSelectedItems, FALSE); +} + +void LLFolderView::addToSelectionList(LLFolderViewItem* item) +{ + if (item->isSelected()) + { + removeFromSelectionList(item); + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + item->setIsCurSelection(TRUE); + mSelectedItems.push_back(item); +} + +void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) +{ + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(FALSE); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) + { + if (*item_iter == item) + { + item_iter = mSelectedItems.erase(item_iter); + } + else + { + ++item_iter; + } + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(TRUE); + } +} + +LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) +{ + if(mSelectedItems.size()) + { + LLFolderViewItem* itemp = mSelectedItems.back(); + llassert(itemp->getIsCurSelection()); + return itemp; + } + return NULL; +} + + +// Record the selected item and pass it down the hierachy. +BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + + if( selection == this ) + { + return FALSE; + } + + if( selection && take_keyboard_focus) + { + mParentPanel->setFocus(TRUE); + } + + // clear selection down here because change of keyboard focus can potentially + // affect selection + clearSelection(); + + if(selection) + { + addToSelectionList(selection); + } + + BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + if(openitem && selection) + { + selection->getParentFolder()->requestArrange(); + } + + llassert(mSelectedItems.size() <= 1); + + return rv; +} + +BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + + // can't select root folder + if(!selection || selection == this) + { + return FALSE; + } + + if (!mAllowMultiSelect) + { + clearSelection(); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + if (*item_iter == selection) + { + break; + } + } + + BOOL on_list = (item_iter != mSelectedItems.end()); + + if(selected && !on_list) + { + addToSelectionList(selection); + } + if(!selected && on_list) + { + removeFromSelectionList(selection); + } + + rv = LLFolderViewFolder::changeSelection(selection, selected); + + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + + return rv; +} + +static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); +void LLFolderView::sanitizeSelection() +{ + LLFastTimer _(FTM_SANITIZE_SELECTION); + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + + std::vector items_to_remove; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewItem* item = *item_iter; + + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + // modify with parent open and filters states + LLFolderViewFolder* parent_folder = item->getParentFolder(); + // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) + { + items_to_remove.push_back(item); + } + + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder == item) + { + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; + } + } + } + + // Don't allow invisible items (such as root folders) to be selected. + if (item == getRoot()) + { + items_to_remove.push_back(item); + } + } + + std::vector::iterator item_it; + for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) + { + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->getViewModelItem()->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + new_selection = NULL; + } + + if (new_selection) + { + setSelection(new_selection, FALSE, FALSE); + } + } +} + +void LLFolderView::clearSelection() +{ + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) + { + (*item_it)->setUnselected(); + } + + mSelectedItems.clear(); +} + +std::set LLFolderView::getSelectionList() const +{ + std::set selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); + return selection; +} + +bool LLFolderView::startDrag() +{ + std::vector selected_items; + selected_items_t::iterator item_it; + + if (!mSelectedItems.empty()) + { + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + selected_items.push_back((*item_it)->getViewModelItem()); + } + + return getFolderViewModel()->startDrag(selected_items); + } + return false; +} + +void LLFolderView::commitRename( const LLSD& data ) +{ + finishRenamingItem(); +} + +void LLFolderView::draw() +{ + //LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + // if cursor has moved off of me during drag and drop + // close all auto opened folders + if (!mDragAndDropThisFrame) + { + closeAutoOpenedFolders(); + } + + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) + { + mSearchString.clear(); + } + + if (hasVisibleChildren()) + { + mStatusTextBox->setVisible( FALSE ); + } + else if (mShowEmptyMessage) + { + mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); + mStatusTextBox->setVisible( TRUE ); + + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = local_rect.getHeight() != pixel_height; + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); + } + } + + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, + // and arrow for the root folder + LLView::draw(); + + mDragAndDropThisFrame = FALSE; +} + +void LLFolderView::finishRenamingItem( void ) +{ + if(!mRenamer) + { + return; + } + if( mRenameItem ) + { + mRenameItem->rename( mRenamer->getText() ); + } + + closeRenamer(); + + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. + scrollToShowSelection(); +} + +void LLFolderView::closeRenamer( void ) +{ + if (mRenamer && mRenamer->getVisible()) + { + // Triggers onRenamerLost() that actually closes the renamer. + LLUI::removePopup(mRenamer); + } +} + +bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector& selectedItems) +{ + LLFolderViewItem* item_parent = dynamic_cast(item->getParent()); + + if (item_parent) + { + for(std::vector::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + const LLFolderViewItem* const selected_item = (*it); + + LLFolderViewItem* parent = item_parent; + + while (parent) + { + if (selected_item == parent) + { + return true; + } + + parent = dynamic_cast(parent->getParent()); + } + } + } + + return false; +} + +void LLFolderView::removeSelectedItems() +{ + if(getVisible() && getEnabled()) + { + // just in case we're removing the renaming item. + mRenameItem = NULL; + + // create a temporary structure which we will use to remove + // items, since the removal will futz with internal data + // structures. + std::vector items; + S32 count = mSelectedItems.size(); + if(count == 0) return; + LLFolderViewItem* item = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + item = *item_it; + if (item && item->isRemovable()) + { + items.push_back(item); + } + else + { + llinfos << "Cannot delete " << item->getName() << llendl; + return; + } + } + + // iterate through the new container. + count = items.size(); + LLUUID new_selection_id; + if(count == 1) + { + LLFolderViewItem* item_to_delete = items[0]; + LLFolderViewFolder* parent = item_to_delete->getParentFolder(); + LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); + if (!new_selection) + { + new_selection = item_to_delete->getPreviousOpenNode(FALSE); + } + if(parent) + { + if (item_to_delete->remove()) + { + // change selection on successful delete + if (new_selection) + { + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); + } + } + } + arrangeAll(); + } + else if (count > 1) + { + LLDynamicArray listeners; + LLFolderViewModelItem* listener; + LLFolderViewItem* last_item = items[count - 1]; + LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(FALSE); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(FALSE); + while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) + { + new_selection = new_selection->getPreviousOpenNode(FALSE); + } + } + if (new_selection) + { + getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); + } + else + { + getRoot()->setSelection(NULL, mParentPanel->hasFocus()); + } + + for(S32 i = 0; i < count; ++i) + { + listener = items[i]->getViewModelItem(); + if(listener && (listeners.find(listener) == LLDynamicArray::FAIL)) + { + listeners.put(listener); + } + } + listener = static_cast(listeners.get(0)); + if(listener) + { + listener->removeBatch(listeners); + } + } + arrangeAll(); + scrollToShowSelection(); + } +} + +// TODO RN: abstract +// open the selected item. +void LLFolderView::openSelectedItems( void ) +{ + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // mSelectedItems.front()->openItem(); + // } + // else + // { + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // listener->openItem(); + // } + + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + // } + //} +} + +void LLFolderView::propertiesSelectedItems( void ) +{ + //TODO RN: get working again + //if(getVisible() && getEnabled()) + //{ + // if (mSelectedItems.size() == 1) + // { + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + // } + // else + // { + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // LLFloater::setFloaterHost(multi_propertiesp); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } + + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + // } + //} +} + + +void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) +{ + if ((mAutoOpenItems.check() == item) || + (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || + item->isOpen()) + { + return; + } + + // close auto-opened folders + LLFolderViewFolder* close_item = mAutoOpenItems.check(); + while (close_item && close_item != item->getParentFolder()) + { + mAutoOpenItems.pop(); + close_item->setOpenArrangeRecursively(FALSE); + close_item = mAutoOpenItems.check(); + } + + item->requestArrange(); + + mAutoOpenItems.push(item); + + item->setOpen(TRUE); + LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); + scrollToShowItem(item, constraint_rect); +} + +void LLFolderView::closeAutoOpenedFolders() +{ + while (mAutoOpenItems.check()) + { + LLFolderViewFolder* close_item = mAutoOpenItems.pop(); + close_item->setOpen(FALSE); + } + + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); +} + +BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) +{ + if (folder && mAutoOpenCandidate == folder) + { + if (mAutoOpenTimer.getStarted()) + { + if (!mAutoOpenCandidate->isOpen()) + { + mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); + } + if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) + { + autoOpenItem(folder); + mAutoOpenTimer.stop(); + return TRUE; + } + } + return FALSE; + } + + // otherwise new candidate, restart timer + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = folder; + mAutoOpenTimer.start(); + return FALSE; +} + +BOOL LLFolderView::canCopy() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + if (!item->getViewModelItem()->isItemCopyable()) + { + return FALSE; + } + } + return TRUE; +} + +// copy selected item +void LLFolderView::copy() +{ + // *NOTE: total hack to clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->copyToClipboard(); + } + } + } + mSearchString.clear(); +} + +BOOL LLFolderView::canCut() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return FALSE; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + const LLFolderViewModelItem* listener = item->getViewModelItem(); + + if (!listener || !listener->isItemRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +void LLFolderView::cut() +{ + // clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->cutToClipboard(); + listener->removeItem(); + } + } + } + mSearchString.clear(); +} + +BOOL LLFolderView::canPaste() const +{ + if (mSelectedItems.empty()) + { + return FALSE; + } + + if(getVisible() && getEnabled()) + { + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); ++item_it) + { + // *TODO: only check folders and parent folders of items + const LLFolderViewItem* item = (*item_it); + const LLFolderViewModelItem* listener = item->getViewModelItem(); + if(!listener || !listener->isClipboardPasteable()) + { + const LLFolderViewFolder* folderp = item->getParentFolder(); + listener = folderp->getViewModelItem(); + if (!listener || !listener->isClipboardPasteable()) + { + return FALSE; + } + } + } + return TRUE; + } + return FALSE; +} + +// paste selected item +void LLFolderView::paste() +{ + if(getVisible() && getEnabled()) + { + // find set of unique folders to paste into + std::set folder_set; + + selected_items_t::iterator selected_it; + for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + LLFolderViewItem* item = *selected_it; + LLFolderViewFolder* folder = dynamic_cast(item); + if (folder == NULL) + { + item = item->getParentFolder(); + } + folder_set.insert(folder); + } + + std::set::iterator set_iter; + for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) + { + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); + if(listener && listener->isClipboardPasteable()) + { + listener->pasteFromClipboard(); + } + } + } + mSearchString.clear(); +} + +// public rename functionality - can only start the process +void LLFolderView::startRenamingSelectedItem( void ) +{ + // make sure selection is visible + scrollToShowSelection(); + + S32 count = mSelectedItems.size(); + LLFolderViewItem* item = NULL; + if(count > 0) + { + item = mSelectedItems.front(); + } + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) + { + mRenameItem = item; + + updateRenamerPosition(); + + + mRenamer->setText(item->getName()); + mRenamer->selectAll(); + mRenamer->setVisible( TRUE ); + // set focus will fail unless item is visible + mRenamer->setFocus( TRUE ); + mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + LLUI::addPopup(mRenamer); + } +} + +BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + LLView *item = NULL; + if (getChildCount() > 0) + { + item = *(getChildList()->begin()); + } + + switch( key ) + { + case KEY_F2: + mSearchString.clear(); + startRenamingSelectedItem(); + handled = TRUE; + break; + + case KEY_RETURN: + if (mask == MASK_NONE) + { + if( mRenameItem && mRenamer->getVisible() ) + { + finishRenamingItem(); + mSearchString.clear(); + handled = TRUE; + } + else + { + LLFolderView::openSelectedItems(); + handled = TRUE; + } + } + break; + + case KEY_ESCAPE: + if( mRenameItem && mRenamer->getVisible() ) + { + closeRenamer(); + handled = TRUE; + } + mSearchString.clear(); + break; + + case KEY_PAGE_UP: + mSearchString.clear(); + mScrollContainer->pageUp(30); + handled = TRUE; + break; + + case KEY_PAGE_DOWN: + mSearchString.clear(); + mScrollContainer->pageDown(30); + handled = TRUE; + break; + + case KEY_HOME: + mSearchString.clear(); + mScrollContainer->goToTop(); + handled = TRUE; + break; + + case KEY_END: + mSearchString.clear(); + mScrollContainer->goToBottom(); + break; + + case KEY_DOWN: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + + if (!mKeyboardSelection) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + LLFolderViewItem* next = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + next = last_selected->getNextOpenNode(FALSE); + if (next) + { + if (next->isSelected()) + { + // shrink selection + getRoot()->changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == next->getParentFolder()) + { + // grow selection + getRoot()->changeSelection(next, TRUE); + } + } + } + else + { + next = last_selected->getNextOpenNode(); + if( next ) + { + if (next == last_selected) + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + setSelection( next, FALSE, TRUE ); + } + else + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } + } + scrollToShowSelection(); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_UP: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = mSelectedItems.back(); + + if (!mKeyboardSelection) + { + setSelection(last_selected, FALSE, TRUE); + mKeyboardSelection = TRUE; + } + + LLFolderViewItem* prev = NULL; + if (mask & MASK_SHIFT) + { + // don't shift select down to children of folders (they are implicitly selected through parent) + prev = last_selected->getPreviousOpenNode(FALSE); + if (prev) + { + if (prev->isSelected()) + { + // shrink selection + getRoot()->changeSelection(last_selected, FALSE); + } + else if (last_selected->getParentFolder() == prev->getParentFolder()) + { + // grow selection + getRoot()->changeSelection(prev, TRUE); + } + } + } + else + { + prev = last_selected->getPreviousOpenNode(); + if( prev ) + { + if (prev == this) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + + return FALSE; + } + setSelection( prev, FALSE, TRUE ); + } + } + scrollToShowSelection(); + mSearchString.clear(); + + handled = TRUE; + } + break; + + case KEY_RIGHT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + last_selected->setOpen( TRUE ); + mSearchString.clear(); + handled = TRUE; + } + break; + + case KEY_LEFT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + LLFolderViewItem* parent_folder = last_selected->getParentFolder(); + if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) + { + setSelection(parent_folder, FALSE, TRUE); + } + else + { + last_selected->setOpen( FALSE ); + } + mSearchString.clear(); + scrollToShowSelection(); + handled = TRUE; + } + break; + } + + if (!handled && mParentPanel->hasFocus()) + { + if (key == KEY_BACKSPACE) + { + mSearchTimer.reset(); + if (mSearchString.size()) + { + mSearchString.erase(mSearchString.size() - 1, 1); + } + search(getCurSelectedItem(), mSearchString, FALSE); + handled = TRUE; + } + } + + return handled; +} + + +BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) +{ + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL + { + return FALSE; + } + + if (uni_char > 0x7f) + { + llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; + return FALSE; + } + + BOOL handled = FALSE; + if (mParentPanel->hasFocus()) + { + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + //do text search + if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) + { + mSearchString.clear(); + } + mSearchTimer.reset(); + if (mSearchString.size() < 128) + { + mSearchString += uni_char; + } + search(getCurSelectedItem(), mSearchString, FALSE); + + handled = TRUE; + } + + return handled; +} + + +BOOL LLFolderView::canDoDelete() const +{ + if (mSelectedItems.size() == 0) return FALSE; + + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + if (!(*item_it)->getViewModelItem()->isItemRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +void LLFolderView::doDelete() +{ + if(mSelectedItems.size() > 0) + { + removeSelectedItems(); + } +} + + +BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + mKeyboardSelection = FALSE; + mSearchString.clear(); + + mParentPanel->setFocus(TRUE); + + LLEditMenuHandler::gEditMenuHandler = this; + + return LLView::handleMouseDown( x, y, mask ); +} + +BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) +{ + // get first selected item + LLFolderViewItem* search_item = first_item; + + // make sure search string is upper case + std::string upper_case_string = search_string; + LLStringUtil::toUpper(upper_case_string); + + // if nothing selected, select first item in folder + if (!search_item) + { + // start from first item + search_item = getNextFromChild(NULL); + } + + // search over all open nodes for first substring match (with wrapping) + BOOL found = FALSE; + LLFolderViewItem* original_search_item = search_item; + do + { + // wrap at end + if (!search_item) + { + if (backward) + { + search_item = getPreviousFromChild(NULL); + } + else + { + search_item = getNextFromChild(NULL); + } + if (!search_item || search_item == original_search_item) + { + break; + } + } + + const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); + S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + if (!current_item_label.compare(0, search_string_length, upper_case_string)) + { + found = TRUE; + break; + } + if (backward) + { + search_item = search_item->getPreviousOpenNode(); + } + else + { + search_item = search_item->getNextOpenNode(); + } + + } while(search_item != original_search_item); + + + if (found) + { + setSelection(search_item, FALSE, TRUE); + scrollToShowSelection(); + } + + return found; +} + +BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + // skip LLFolderViewFolder::handleDoubleClick() + return LLView::handleDoubleClick( x, y, mask ); +} + +BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + // all user operations move keyboard focus to inventory + // this way, we know when to stop auto-updating a search + mParentPanel->setFocus(TRUE); + + BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + S32 count = mSelectedItems.size(); + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if ( handled + && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible + && menu ) + { + if (mCallbackRegistrar) + mCallbackRegistrar->pushScope(); + + updateMenuOptions(menu); + + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + if (mCallbackRegistrar) + mCallbackRegistrar->popScope(); + } + else + { + if (menu && menu->getVisible()) + { + menu->setVisible(FALSE); + } + setSelection(NULL, FALSE, TRUE); + } + return handled; +} + +// Add "--no options--" if the menu is completely blank. +BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const +{ + const std::string nooptions_str = "--no options--"; + LLView *nooptions_item = NULL; + + const LLView::child_list_t *list = menu->getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + if (menu_item->getVisible()) + { + return FALSE; + } + std::string name = menu_item->getName(); + if (menu_item->getName() == nooptions_str) + { + nooptions_item = menu_item; + } + } + if (nooptions_item) + { + nooptions_item->setVisible(TRUE); + nooptions_item->setEnabled(FALSE); + return TRUE; + } + return FALSE; +} + +BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) +{ + return LLView::handleHover( x, y, mask ); +} + +BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + mDragAndDropThisFrame = TRUE; + // have children handle it first + BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + // when drop is not handled by child, it should be handled + // by the folder which is the hierarchy root. + if (!handled) + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + +void LLFolderView::deleteAllChildren() +{ + closeRenamer(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle = LLHandle(); + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + clearSelection(); + LLView::deleteAllChildren(); +} + +void LLFolderView::scrollToShowSelection() +{ + if ( mSelectedItems.size() ) + { + mNeedsScroll = TRUE; + } +} + +// If the parent is scroll container, scroll it to make the selection +// is maximally visible. +void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) +{ + if (!mScrollContainer) return; + + // don't scroll to items when mouse is being used to scroll/drag and drop + if (gFocusMgr.childHasMouseCapture(mScrollContainer)) + { + mNeedsScroll = FALSE; + return; + } + + // if item exists and is in visible portion of parent folder... + if(item) + { + LLRect local_rect = item->getLocalRect(); + LLRect item_scrolled_rect; // item position relative to display area of scroller + LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); + + S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); + S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + + // get portion of item that we want to see... + LLRect item_local_rect = LLRect(item->getIndentation(), + local_rect.getHeight(), + llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), + llmax(0, local_rect.getHeight() - max_height_to_show)); + + LLRect item_doc_rect; + + item->localRectToOtherView(item_local_rect, &item_doc_rect, this); + + mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); + + } +} + +LLRect LLFolderView::getVisibleRect() +{ + S32 visible_height = mScrollContainer->getRect().getHeight(); + S32 visible_width = mScrollContainer->getRect().getWidth(); + LLRect visible_rect; + visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); + return visible_rect; +} + +BOOL LLFolderView::getShowSelectionContext() +{ + if (mShowSelectionContext) + { + return TRUE; + } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + return TRUE; + } + return FALSE; +} + +void LLFolderView::setShowSingleSelection(BOOL show) +{ + if (show != mShowSingleSelection) + { + mMultiSelectionFadeTimer.reset(); + mShowSingleSelection = show; + } +} + +static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); +static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); + +// Main idle routine +void LLFolderView::update() +{ + // If this is associated with the user's inventory, don't do anything + // until that inventory is loaded up. + LLFastTimer t2(FTM_INVENTORY); + + if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) + { + mNeedsAutoSelect = TRUE; + } + getFolderViewModel()->getFilter()->clearModified(); + + // filter to determine visibility before arranging + filter(*(getFolderViewModel()->getFilter())); + + // automatically show matching items, and select first one if we had a selection + if (mNeedsAutoSelect) + { + LLFastTimer t3(FTM_AUTO_SELECT); + // select new item only if a filtered item not currently selected + LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); + if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLSelectFirstFilteredItem functor; + applyFunctorRecursively(functor); + } + + // Open filtered folders for folder views with mAutoSelectOverride=TRUE. + // Used by LLPlacesFolderView. + if (getFolderViewModel()->getFilter()->showAllResults()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLOpenFilteredFolders functor; + applyFunctorRecursively(functor); + } + + scrollToShowSelection(); + } + + BOOL filter_finished = getViewModelItem()->passedFilter() + && mViewModel->contentsReady(); + if (filter_finished + || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container + || gFocusMgr.childHasMouseCapture(getParent())) + { + // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process + mNeedsAutoSelect = FALSE; + } + + + // during filtering process, try to pin selected item's location on screen + // this will happen when searching your inventory and when new items arrive + if (!filter_finished) + { + // calculate rectangle to pin item to at start of animated rearrange + if (!mPinningSelectedItem && !mSelectedItems.empty()) + { + // lets pin it! + mPinningSelectedItem = TRUE; + + LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); + LLFolderViewItem* selected_item = mSelectedItems.back(); + + LLRect item_rect; + selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); + // if item is visible in scrolled region + if (visible_content_rect.overlaps(item_rect)) + { + // then attempt to keep it in same place on screen + mScrollConstraintRect = item_rect; + mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); + } + else + { + // otherwise we just want it onscreen somewhere + LLRect content_rect = mScrollContainer->getContentWindowRect(); + mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + } + } + else + { + // stop pinning selected item after folders stop rearranging + if (!needsArrange()) + { + mPinningSelectedItem = FALSE; + } + } + + LLRect constraint_rect; + if (mPinningSelectedItem) + { + // use last known constraint rect for pinned item + constraint_rect = mScrollConstraintRect; + } + else + { + // during normal use (page up/page down, etc), just try to fit item on screen + LLRect content_rect = mScrollContainer->getContentWindowRect(); + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + + BOOL is_visible = isInVisibleChain(); + + if ( is_visible ) + { + sanitizeSelection(); + if( needsArrange() ) + { + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + } + } + + if (mSelectedItems.size() && mNeedsScroll) + { + scrollToShowItem(mSelectedItems.back(), constraint_rect); + // continue scrolling until animated layout change is done + if (filter_finished + && (!needsArrange() || !is_visible)) + { + mNeedsScroll = FALSE; + } + } + + if (mSignalSelectCallback) + { + //RN: we use keyboard focus as a proxy for user-explicit actions + BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + mSelectSignal(mSelectedItems, take_keyboard_focus); + } + mSignalSelectCallback = FALSE; +} + +void LLFolderView::dumpSelectionInformation() +{ + llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; + llinfos << "****************************************" << llendl; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + llinfos << " " << (*item_it)->getName() << llendl; + } + llinfos << "****************************************" << llendl; +} + +void LLFolderView::updateRenamerPosition() +{ + if(mRenameItem) + { + // See also LLFolderViewItem::draw() + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenameItem->localPointToScreen( x, y, &x, &y ); + screenPointToLocal( x, y, &x, &y ); + mRenamer->setOrigin( x, y ); + + LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); + if (mScrollContainer) + { + scroller_rect = mScrollContainer->getContentWindowRect(); + } + + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenamer->reshape( width, height, TRUE ); + } +} + +// Update visibility and availability (i.e. enabled/disabled) of context menu items. +void LLFolderView::updateMenuOptions(LLMenuGL* menu) +{ + const LLView::child_list_t *list = menu->getChildList(); + + LLView::child_list_t::const_iterator menu_itor; + for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) + { + (*menu_itor)->setVisible(FALSE); + (*menu_itor)->pushVisible(TRUE); + (*menu_itor)->setEnabled(TRUE); + } + + // Successively filter out invalid options + + U32 flags = FIRST_SELECTED_ITEM; + for (selected_items_t::iterator item_itor = mSelectedItems.begin(); + item_itor != mSelectedItems.end(); + ++item_itor) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->buildContextMenu(*menu, flags); + flags = 0x0; + } + + addNoOptions(menu); +} + +// Refresh the context menu (that is already shown). +void LLFolderView::updateMenu() +{ + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + updateMenuOptions(menu); + menu->needsArrange(); // update menu height if needed + } +} + +bool LLFolderView::selectFirstItem() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();++iter) + { + LLFolderViewFolder* folder = (*iter ); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getNextFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} +bool LLFolderView::selectLastItem() +{ + for(items_t::reverse_iterator iit = mItems.rbegin(); + iit != mItems.rend(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + for (folders_t::reverse_iterator iter = mFolders.rbegin(); + iter != mFolders.rend();++iter) + { + LLFolderViewFolder* folder = (*iter); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} + + +S32 LLFolderView::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + scrollToShowSelection(); + return 1; + + } + else if(str_action == "select_last") + { + setFocus(true); + selectLastItem(); + scrollToShowSelection(); + return 1; + } + } + return 0; +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +void LLFolderView::onRenamerLost() +{ + if (mRenamer && mRenamer->getVisible()) + { + mRenamer->setVisible(FALSE); + + // will commit current name (which could be same as original name) + mRenamer->setFocus(FALSE); + } + + if( mRenameItem ) + { + setSelection( mRenameItem, TRUE ); + mRenameItem = NULL; + } +} + +S32 LLFolderView::getItemHeight() +{ + if(!hasVisibleChildren()) + { + //We need to display status textbox, let's reserve some place for it + return llmax(0, mStatusTextBox->getTextPixelHeight()); + } + return 0; +} diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h new file mode 100644 index 0000000000..ba37a11bbe --- /dev/null +++ b/indra/llui/llfolderview.h @@ -0,0 +1,388 @@ +/** + * @file llfolderview.h + * @brief Definition of the folder view collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +/** + * + * The folder view collection of classes provides an interface for + * making a 'folder view' similar to the way the a single pane file + * folder interface works. + * + */ + +#ifndef LL_LLFOLDERVIEW_H +#define LL_LLFOLDERVIEW_H + +#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder + +#include "lluictrl.h" +#include "v4color.h" +#include "stdenums.h" +#include "lldepthstack.h" +#include "lleditmenuhandler.h" +#include "llfontgl.h" +#include "llscrollcontainer.h" + +class LLFolderViewModelInterface; +class LLFolderViewFolder; +class LLFolderViewItem; +class LLFolderViewFilter; +class LLPanel; +class LLLineEditor; +class LLMenuGL; +class LLUICtrl; +class LLTextBox; + +/** + * Class LLFolderViewScrollContainer + * + * A scroll container which provides the information about the height + * of currently displayed folder view contents. + * Used for updating vertical scroll bar visibility in inventory panel. + * See LLScrollContainer::calcVisibleSize(). + */ +class LLFolderViewScrollContainer : public LLScrollContainer +{ +public: + /*virtual*/ ~LLFolderViewScrollContainer() {}; + /*virtual*/ const LLRect getScrolledViewRect() const; + +protected: + LLFolderViewScrollContainer(const LLScrollContainer::Params& p); + friend class LLUICtrlFactory; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderView +// +// The LLFolderView represents the root level folder view object. +// It manages the screen region of the folder view. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler +{ +public: + struct Params : public LLInitParam::Block + { + Mandatory parent_panel; + Optional title; + Optional use_label_suffix, + allow_multiselect, + show_empty_message, + use_ellipses, + show_item_link_overlays; + Mandatory view_model; + + Params(); + }; + + friend class LLFolderViewScrollContainer; + + LLFolderView(const Params&); + virtual ~LLFolderView( void ); + + virtual BOOL canFocusChildren() const; + + virtual const LLFolderView* getRoot() const { return this; } + virtual LLFolderView* getRoot() { return this; } + + LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } + + typedef boost::signals2::signal& items, BOOL user_action)> signal_t; + void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } + void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } + + bool getAllowMultiSelect() { return mAllowMultiSelect; } + + // Close all folders in the view + void closeAllFolders(); + void openTopLevelFolders(); + + virtual BOOL addFolder( LLFolderViewFolder* folder); + + // Find width and height of this object and its children. Also + // makes sure that this view and its children are the right size. + virtual S32 arrange( S32* width, S32* height ); + virtual S32 getItemHeight(); + + void arrangeAll() { mArrangeGeneration++; } + S32 getArrangeGeneration() { return mArrangeGeneration; } + + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); + + // Get the last selected item + virtual LLFolderViewItem* getCurSelectedItem( void ); + + // Record the selected item and pass it down the hierarchy. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus = TRUE); + + // This method is used to toggle the selection of an item. Walks + // children, and keeps track of selected objects. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + virtual std::set getSelectionList() const; + S32 getNumSelectedItems() { return mSelectedItems.size(); } + + // Make sure if ancestor is selected, descendants are not + void sanitizeSelection(); + virtual void clearSelection(); + void addToSelectionList(LLFolderViewItem* item); + void removeFromSelectionList(LLFolderViewItem* item); + + bool startDrag(); + void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } + void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } + LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } + + // Deletion functionality + void removeSelectedItems(); + + // Open the selected item + void openSelectedItems( void ); + void propertiesSelectedItems( void ); + + void autoOpenItem(LLFolderViewFolder* item); + void closeAutoOpenedFolders(); + BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open + + // Copy & paste + virtual void copy(); + virtual BOOL canCopy() const; + + virtual void cut(); + virtual BOOL canCut() const; + + virtual void paste(); + virtual BOOL canPaste() const; + + virtual void doDelete(); + virtual BOOL canDoDelete() const; + + // Public rename functionality - can only start the process + void startRenamingSelectedItem( void ); + + // LLView functionality + ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); + /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); + /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } + virtual void draw(); + virtual void deleteAllChildren(); + + void scrollToShowSelection(); + void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); + void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } + LLRect getVisibleRect(); + + BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); + void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } + BOOL getShowSelectionContext(); + void setShowSingleSelection(BOOL show); + BOOL getShowSingleSelection() { return mShowSingleSelection; } + F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } + bool getUseEllipses() { return mUseEllipses; } + + void update(); // needs to be called periodically (e.g. once per frame) + + BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } + BOOL needsAutoRename() { return mNeedsAutoRename; } + void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } + void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } + void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } + + bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + + void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } + + LLPanel* getParentPanel() { return mParentPanel; } + // DEBUG only + void dumpSelectionInformation(); + + virtual S32 notify(const LLSD& info) ; + + bool useLabelSuffix() { return mUseLabelSuffix; } + void updateMenu(); + +private: + void updateMenuOptions(LLMenuGL* menu); + void updateRenamerPosition(); + +protected: + LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. + + void commitRename( const LLSD& data ); + void onRenamerLost(); + + void finishRenamingItem( void ); + void closeRenamer( void ); + + bool selectFirstItem(); + bool selectLastItem(); + + BOOL addNoOptions(LLMenuGL* menu) const; + + +protected: + LLHandle mPopupMenuHandle; + + typedef std::deque selected_items_t; + selected_items_t mSelectedItems; + BOOL mKeyboardSelection; + BOOL mAllowMultiSelect; + BOOL mShowEmptyMessage; + BOOL mShowFolderHierarchy; + + // Renaming variables and methods + LLFolderViewItem* mRenameItem; // The item currently being renamed + LLLineEditor* mRenamer; + + BOOL mNeedsScroll; + BOOL mPinningSelectedItem; + LLRect mScrollConstraintRect; + BOOL mNeedsAutoSelect; + BOOL mAutoSelectOverride; + BOOL mNeedsAutoRename; + bool mUseLabelSuffix; + bool mShowItemLinkOverlays; + + LLDepthStack mAutoOpenItems; + LLFolderViewFolder* mAutoOpenCandidate; + LLFrameTimer mAutoOpenTimer; + LLFrameTimer mSearchTimer; + std::string mSearchString; + BOOL mShowSelectionContext; + BOOL mShowSingleSelection; + LLFrameTimer mMultiSelectionFadeTimer; + S32 mArrangeGeneration; + + signal_t mSelectSignal; + signal_t mReshapeSignal; + S32 mSignalSelectCallback; + S32 mMinWidth; + BOOL mDragAndDropThisFrame; + + LLPanel* mParentPanel; + + LLFolderViewModelInterface* mViewModel; + + /** + * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. + * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. + */ + bool mUseEllipses; // See EXT-719 + + /** + * Contains item under mouse pointer while dragging + */ + LLFolderViewItem* mDraggingOverItem; // See EXT-719 + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; + +public: + static F32 sAutoOpenTime; + LLTextBox* mStatusTextBox; + +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: + virtual ~LLFolderViewFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder) = 0; + virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +// Flags for buildContextMenu() +const U32 SUPPRESS_OPEN_ITEM = 0x1; +const U32 FIRST_SELECTED_ITEM = 0x2; + +#endif // LL_LLFOLDERVIEW_H diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp new file mode 100644 index 0000000000..741fc9c324 --- /dev/null +++ b/indra/llui/llfolderviewitem.cpp @@ -0,0 +1,2032 @@ +/** +* @file llfolderviewitem.cpp +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#include "linden_common.h" +#include "llfolderviewitem.h" + +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llpanel.h" +#include "llcriticaldamp.h" +#include "llclipboard.h" +#include "llfocusmgr.h" // gFocusMgr +#include "lltrans.h" +#include "llwindow.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderViewItem +///---------------------------------------------------------------------------- + +static LLDefaultChildRegistry::Register r("folder_view_item"); + +// statics +std::map LLFolderViewItem::sFonts; // map of styles to fonts + +// only integers can be initialized in header +const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; +const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + + +//static +LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) +{ + LLFontGL* rtn = sFonts[style]; + if (!rtn) // grab label font with this style, lazily + { + LLFontDescriptor labelfontdesc("SansSerif", "Small", style); + rtn = LLFontGL::getFont(labelfontdesc); + if (!rtn) + { + rtn = LLFontGL::getFontDefault(); + } + sFonts[style] = rtn; + } + return rtn; +} + +//static +void LLFolderViewItem::initClass() +{ +} + +//static +void LLFolderViewItem::cleanupClass() +{ + sFonts.clear(); +} + + +// NOTE: Optimize this, we call it a *lot* when opening a large inventory +LLFolderViewItem::Params::Params() +: root(), + listener(), + folder_arrow_image("folder_arrow_image"), + folder_indentation("folder_indentation"), + selection_image("selection_image"), + item_height("item_height"), + item_top_pad("item_top_pad"), + creation_date() +{} + +// Default constructor +LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) +: LLView(p), + mLabelWidth(0), + mLabelWidthDirty(false), + mParentFolder( NULL ), + mIsSelected( FALSE ), + mIsCurSelection( FALSE ), + mSelectPending(FALSE), + mLabelStyle( LLFontGL::NORMAL ), + mHasVisibleChildren(FALSE), + mIndentation(0), + mItemHeight(p.item_height), + //TODO RN: create interface for string highlighting + //mStringMatchOffset(std::string::npos), + mControlLabelRotation(0.f), + mDragAndDropTarget(FALSE), + mLabel(p.name), + mRoot(p.root), + mViewModelItem(p.listener), + mIsMouseOverTitle(false) +{ + if (mViewModelItem) + { + mViewModelItem->setFolderViewItem(this); + } +} + +BOOL LLFolderViewItem::postBuild() +{ + refresh(); + return TRUE; +} + +// Destroys the object +LLFolderViewItem::~LLFolderViewItem( void ) +{ + delete mViewModelItem; + mViewModelItem = NULL; +} + +LLFolderView* LLFolderViewItem::getRoot() +{ + return mRoot; +} + +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} +// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. +BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) +{ + LLFolderViewItem* root = this; + while( root->mParentFolder ) + { + if( root->mParentFolder == potential_ancestor ) + { + return TRUE; + } + root = root->mParentFolder; + } + return FALSE; +} + +LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit last item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); + + // Skip over items that are invisible or are hidden from the UI. + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit first item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +BOOL LLFolderViewItem::passedFilter(S32 filter_generation) +{ + return getViewModelItem()->passedFilter(filter_generation); +} + +void LLFolderViewItem::refresh() +{ + LLFolderViewModelItem& vmi = *getViewModelItem(); + + mLabel = vmi.getDisplayName(); + + setToolTip(mLabel); + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); + + if (mRoot->useLabelSuffix()) + { + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); + } + + //TODO RN: make sure this logic still fires + //std::string searchable_label(mLabel); + //searchable_label.append(mLabelSuffix); + //LLStringUtil::toUpper(searchable_label); + + //if (mSearchableLabel.compare(searchable_label)) + //{ + // mSearchableLabel.assign(searchable_label); + // vmi.dirtyFilter(); + // // some part of label has changed, so overall width has potentially changed, and sort order too + // if (mParentFolder) + // { + // mParentFolder->requestSort(); + // mParentFolder->requestArrange(); + // } + //} + + mLabelWidthDirty = true; + vmi.dirtyFilter(); +} + +// Utility function for LLFolderView +void LLFolderViewItem::arrangeAndSet(BOOL set_selection, + BOOL take_keyboard_focus) +{ + LLFolderView* root = getRoot(); + if (getParentFolder()) + { + getParentFolder()->requestArrange(); + } + if(set_selection) + { + getRoot()->setSelection(this, TRUE, take_keyboard_focus); + if(root) + { + root->scrollToShowSelection(); + } + } +} + + +std::set LLFolderViewItem::getSelectionList() const +{ + std::set selection; + return selection; +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) +{ + return folder->addItem(this); +} + + +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. +S32 LLFolderViewItem::arrange( S32* width, S32* height ) +{ + const Params& p = LLUICtrlFactory::getDefaultParams(); + S32 indentation = p.folder_indentation(); + // Only indent deeper items in hierarchy + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + indentation + : 0; + if (mLabelWidthDirty) + { + mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; + mLabelWidthDirty = false; + } + + *width = llmax(*width, mLabelWidth + mIndentation); + + // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 + bool use_ellipses = getRoot()->getUseEllipses(); + if (use_ellipses) + { + // limit to set rect to avoid horizontal scrollbar + *width = llmin(*width, getRoot()->getRect().getWidth()); + } + *height = getItemHeight(); + return *height; +} + +S32 LLFolderViewItem::getItemHeight() +{ + return mItemHeight; +} + +// *TODO: This can be optimized a lot by simply recording that it is +// selected in the appropriate places, and assuming that set selection +// means 'deselect' for a leaf item. Do this optimization after +// multiple selection is implemented to make sure it all plays nice +// together. +BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) +{ + if (selection == this && !mIsSelected) + { + selectItem(); + } + else if (mIsSelected) // Deselect everything else. + { + deselectItem(); + } + return mIsSelected; +} + +BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + if (selection == this) + { + if (mIsSelected) + { + deselectItem(); + } + else + { + selectItem(); + } + return TRUE; + } + return FALSE; +} + +void LLFolderViewItem::deselectItem(void) +{ + mIsSelected = FALSE; +} + +void LLFolderViewItem::selectItem(void) +{ + if (mIsSelected == FALSE) + { + getViewModelItem()->selectItem(); + mIsSelected = TRUE; + } +} + +BOOL LLFolderViewItem::isMovable() +{ + return getViewModelItem()->isItemMovable(); +} + +BOOL LLFolderViewItem::isRemovable() +{ + return getViewModelItem()->isItemRemovable(); +} + +void LLFolderViewItem::destroyView() +{ + getRoot()->removeFromSelectionList(this); + + if (mParentFolder) + { + // removeView deletes me + mParentFolder->extractItem(this); + } + delete this; +} + +// Call through to the viewed object and return true if it can be +// removed. +//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) +BOOL LLFolderViewItem::remove() +{ + if(!isRemovable()) + { + return FALSE; + } + return getViewModelItem()->removeItem(); +} + +// Build an appropriate context menu for the item. +void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + getViewModelItem()->buildContextMenu(menu, flags); +} + +void LLFolderViewItem::openItem( void ) +{ + getViewModelItem()->openItem(); +} + +void LLFolderViewItem::rename(const std::string& new_name) +{ + if( !new_name.empty() ) + { + getViewModelItem()->renameItem(new_name); + + if(mParentFolder) + { + mParentFolder->requestSort(); + } + } + } + +const std::string& LLFolderViewItem::getName( void ) const +{ + return getViewModelItem()->getName(); +} + +// LLView functionality +BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + if(!mIsSelected) + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + return TRUE; +} + +BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseDown(x, y, mask)) + { + return TRUE; + } + + // No handler needed for focus lost since this class has no + // state that depends on it. + gFocusMgr.setMouseCapture( this ); + + if (!mIsSelected) + { + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + make_ui_sound("UISndClick"); + } + else + { + mSelectPending = TRUE; + } + + mDragStartX = x; + mDragStartY = y; + return TRUE; +} + +BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) +{ + static LLCachedControl drag_and_drop_threshold(*LLUI::sSettingGroups["config"],"DragAndDropDistanceThreshold"); + + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + if( hasMouseCapture() && isMovable() ) + { + LLFolderView* root = getRoot(); + + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() + && root->getCurSelectedItem() + && root->startDrag()) + { + // RN: when starting drag and drop, clear out last auto-open + root->autoOpenTest(NULL); + root->setShowSelectionContext(TRUE); + + // Release keyboard focus, so that if stuff is dropped into the + // world, pressing the delete key won't blow away the inventory + // item. + gFocusMgr.setKeyboardFocus(NULL); + + getWindow()->setCursor(UI_CURSOR_ARROW); + return TRUE; + } + else + { + getWindow()->setCursor(UI_CURSOR_NOLOCKED); + return TRUE; + } + } + else + { + getRoot()->setShowSelectionContext(FALSE); + getWindow()->setCursor(UI_CURSOR_ARROW); + // let parent handle this then... + return FALSE; + } +} + + +BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + getViewModelItem()->openItem(); + return TRUE; +} + +BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseUp(x, y, mask)) + { + return TRUE; + } + + // if mouse hasn't moved since mouse down... + if ( pointInView(x, y) && mSelectPending ) + { + //...then select + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, FALSE); + } + } + + mSelectPending = FALSE; + + if( hasMouseCapture() ) + { + if (getRoot()) + { + getRoot()->setShowSelectionContext(FALSE); + } + gFocusMgr.setMouseCapture( NULL ); + } + return TRUE; +} + +void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = false; +} + +BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + if(mParentFolder && !handled) + { + // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. + mRoot->setDraggingOverItem(this); + handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + mRoot->setDraggingOverItem(NULL); + } + if (handled) + { + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; + } + + return handled; +} + +void LLFolderViewItem::draw() +{ + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + const Params& default_params = LLUICtrlFactory::getDefaultParams(); + const S32 TOP_PAD = default_params.item_top_pad; + const S32 FOCUS_LEFT = 1; + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + getViewModelItem()->update(); + + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); + } + + + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // + const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); + const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLColor4 bg_color = sHighlightBgColor; + if (!mIsCurSelection) + { + // do time-based fade of extra objects + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, filled); + if (mIsCurSelection) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sFocusOutlineColor, FALSE); + } + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sFocusOutlineColor, FALSE); + if (show_context) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + sHighlightBgColor, TRUE); + } + } + } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sMouseOverColor, FALSE); + } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + sHighlightBgColor, FALSE); + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + sHighlightBgColor, FALSE); + } + mDragAndDropTarget = FALSE; + } + + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + { + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + } + else if (mIcon) + { + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + if (mIconOverlay && getRoot()->showItemLinkOverlays()) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + //--------------------------------------------------------------------------------// + // Exit if no label to draw + // + if (mLabel.empty()) + { + return; + } + + LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + //TODO RN: implement this in terms of getColor() + //if (highlight_link) color = sLinkColor; + //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + + //--------------------------------------------------------------------------------// + // Draw the actual label text + // + font->renderUTF8(mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); + + //--------------------------------------------------------------------------------// + // Draw label suffix + // + if (!mLabelSuffix.empty()) + { + font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x, FALSE ); + } + + //--------------------------------------------------------------------------------// + // Highlight string match + // + //TODO RN: expose interface for highlighting + //if (mStringMatchOffset != std::string::npos) + //{ + // // don't draw backgrounds for zero-length strings + // S32 filter_string_length = getRoot()->getFilterSubString().size(); + // if (filter_string_length > 0) + // { + // std::string combined_string = mLabel + mLabelSuffix; + // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + // S32 top = getRect().getHeight() - TOP_PAD; + // + // LLUIImage* box_image = default_params.selection_image; + // LLRect box_rect(left, top, right, bottom); + // box_image->draw(box_rect, sFilterBGColor); + // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, + // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + // filter_string_length, S32_MAX, &right_x, FALSE ); + // } + //} +} + +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const + { + return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) + { + return getRoot()->getFolderViewModel(); +} + + +///---------------------------------------------------------------------------- +/// Class LLFolderViewFolder +///---------------------------------------------------------------------------- + +LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): + LLFolderViewItem( p ), + mIsOpen(FALSE), + mExpanderHighlighted(FALSE), + mCurHeight(0.f), + mTargetHeight(0.f), + mAutoOpenCountdown(0.f), + mLastArrangeGeneration( -1 ), + mLastCalculatedWidth(0) +{ +} + +// Destroys the object +LLFolderViewFolder::~LLFolderViewFolder( void ) +{ + // The LLView base class takes care of object destruction. make sure that we + // don't have mouse or keyboard focus + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() +} + +// addToFolder() returns TRUE if it succeeds. FALSE otherwise +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) +{ + return folder->addFolder(this); +} + +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); + +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. +S32 LLFolderViewFolder::arrange( S32* width, S32* height ) +{ + // sort before laying out contents + getRoot()->getFolderViewModel()->sort(this); + + LLFastTimer t2(FTM_ARRANGE); + + // evaluate mHasVisibleChildren + mHasVisibleChildren = false; + if (getViewModelItem()->descendantsPassedFilter()) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = itemp->passedFilter(); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = folderp->passedFilter(); + if (found) + break; + } + } + + mHasVisibleChildren = found; + } + + // calculate height as a single item (without any children), and reshapes rectangle to match + LLFolderViewItem::arrange( width, height ); + + // clamp existing animated height so as to never get smaller than a single item + mCurHeight = llmax((F32)*height, mCurHeight); + + // initialize running height value as height of single item in case we have no children + F32 running_height = (F32)*height; + F32 target_height = (F32)*height; + + // are my children visible? + if (needsArrange()) + { + // set last arrange generation first, in case children are animating + // and need to be arranged again + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + if (isOpen()) + { + // Add sizes of children + S32 parent_item_height = getRect().getHeight(); + + for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter + + if (folderp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += folderp->arrange( &child_width, &child_height ); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); + } + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + itemp->setVisible(itemp->passedFilter()); + + if (itemp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - llround(running_height); + + target_height += itemp->arrange( &child_width, &child_height ); + // don't change width, as this item is as wide as its parent folder by construction + itemp->reshape( itemp->getRect().getWidth(), child_height); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); + } + } + } + + mTargetHeight = target_height; + // cache this width so next time we can just return it + mLastCalculatedWidth = *width; + } + else + { + // just use existing width + *width = mLastCalculatedWidth; + } + + // animate current height towards target height + if (llabs(mCurHeight - mTargetHeight) > 1.f) + { + mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + + requestArrange(); + + // hide child elements that fall out of current animated height + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // number of pixels that bottom of folder label is from top of parent folder + if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + // hide if beyond current folder height + (*fit)->setVisible(FALSE); + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + // number of pixels that bottom of item label is from top of parent folder + if (getRect().getHeight() - (*iit)->getRect().mBottom + > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) + { + (*iit)->setVisible(FALSE); + } + } + } + else + { + mCurHeight = mTargetHeight; + } + + // don't change width as this item is already as wide as its parent folder + reshape(getRect().getWidth(),llround(mCurHeight)); + + // pass current height value back to parent + *height = llround(mCurHeight); + + return llround(mTargetHeight); +} + +BOOL LLFolderViewFolder::needsArrange() +{ + return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); +} + +void LLFolderViewFolder::requestSort() +{ + getViewModelItem()->requestSort(); +} + +//TODO RN: get height resetting working +//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) +//{ +// // if this folder is now filtered, but wasn't before +// // (it just passed) +// if (passed && !passedFilter(filter_generation)) +// { +// // reset current height, because last time we drew it +// // it might have had more visible items than now +// mCurHeight = 0.f; +// } +// +// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); +//} + + +// Passes selection information on to children and record selection +// information if necessary. +BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, + BOOL take_keyboard_focus) +{ + BOOL rv = FALSE; + if (selection == this) + { + if (!isSelected()) + { + selectItem(); + } + rv = TRUE; + } + else + { + if (isSelected()) + { + deselectItem(); + } + rv = FALSE; + } + BOOL child_selected = FALSE; + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = TRUE; + child_selected = TRUE; + } + } + if(openitem && child_selected) + { + setOpenArrangeRecursively(TRUE); + } + return rv; +} + +// This method is used to change the selection of an item. +// Recursively traverse all children; if 'selection' is 'this' then change +// the select status if necessary. +// Returns TRUE if the selection state of this folder, or of a child, was changed. +BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) +{ + BOOL rv = FALSE; + if(selection == this) + { + if (isSelected() != selected) + { + rv = TRUE; + if (selected) + { + selectItem(); + } + else + { + deselectItem(); + } + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->changeSelection(selection, selected)) + { + rv = TRUE; + } + } + return rv; +} + +LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) +{ + if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; + + std::deque item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) + { + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + std::deque item_b_ancestors; + + parent = item_b->getParentFolder(); + while(parent) + { + item_b_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + LLFolderViewFolder* common_ancestor = item_a->getRoot(); + + while(item_a_ancestors.size() > item_b_ancestors.size()) + { + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + } + + while(item_b_ancestors.size() > item_a_ancestors.size()) + { + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + while(item_a_ancestors.size()) + { + common_ancestor = item_a_ancestors.front(); + + if (item_a_ancestors.front() == item_b_ancestors.front()) + { + // which came first, sibling a or sibling b? + for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + + for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + break; + } + + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + return NULL; +} + +void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) +{ + bool selecting = start == NULL; + if (reverse) + { + for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } + else + { + for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } +} + +void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) +{ + if (getRoot()->getAllowMultiSelect() == FALSE) return; + + LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); + if (cur_selected_item == NULL) + { + cur_selected_item = new_selection; + } + + + bool reverse = false; + LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); + if (!common_ancestor) return; + + LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; + LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); + + std::vector items_to_select_forward; + + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); + + last_selected_item_from_cur = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + std::vector items_to_select_reverse; + + LLFolderViewItem* last_selected_item_from_new = new_selection; + cur_folder = new_selection->getParentFolder(); + while(cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); + + last_selected_item_from_new = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); + + for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); + it != end_it; + ++it) + { + items_to_select_forward.push_back(*it); + } + + LLFolderView* root = getRoot(); + + for (std::vector::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + if (item->isSelected()) + { + root->removeFromSelectionList(item); + } + else + { + item->selectItem(); + } + root->addToSelectionList(item); + } + + if (new_selection->isSelected()) + { + root->removeFromSelectionList(new_selection); + } + else + { + new_selection->selectItem(); + } + root->addToSelectionList(new_selection); +} + + +void LLFolderViewFolder::destroyView() +{ + std::for_each(mItems.begin(), mItems.end(), DeletePointer()); + mItems.clear(); + + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + folderp->destroyView(); // removes entry from mFolders + } + + LLFolderViewItem::destroyView(); +} + +// extractItem() removes the specified item from the folder, but +// doesn't delete it. +void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) +{ + items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); + if(it == mItems.end()) + { + // This is an evil downcast. However, it's only doing + // pointer comparison to find if (which it should be ) the + // item is in the container, so it's pretty safe. + LLFolderViewFolder* f = static_cast(item); + folders_t::iterator ft; + ft = std::find(mFolders.begin(), mFolders.end(), f); + if (ft != mFolders.end()) + { + mFolders.erase(ft); + } + } + else + { + mItems.erase(it); + } + //item has been removed, need to update filter + getViewModelItem()->removeChild(item->getViewModelItem()); + getViewModelItem()->dirtyFilter(); + //because an item is going away regardless of filter status, force rearrange + requestArrange(); + removeChild(item); +} + +BOOL LLFolderViewFolder::isMovable() +{ + if( !(getViewModelItem()->isItemMovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) + { + return FALSE; + } + } + return TRUE; +} + + +BOOL LLFolderViewFolder::isRemovable() +{ + if( !(getViewModelItem()->isItemRemovable()) ) + { + return FALSE; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) + { + return FALSE; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) + { + return FALSE; + } + } + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) +{ + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + + mItems.push_back(item); + + item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); + item->setVisible(FALSE); + + addChild(item); + + item->getViewModelItem()->dirtyFilter(); + + // Handle sorting + requestArrange(); + requestSort(); + + getViewModelItem()->addChild(item->getViewModelItem()); + + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria + //// Traverse parent folders and update creation date and resort, if necessary + //LLFolderViewFolder* parentp = this; + //while (parentp) + //{ + // if (parentp->mSortFunction.isByDate()) + // { + // // parent folder doesn't have a time stamp yet, so get it from us + // parentp->requestSort(); + // } + + // parentp = parentp->getParentFolder(); + //} + + return TRUE; +} + +// this is an internal method used for adding items to folders. +BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) +{ + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; + mFolders.push_back(folder); + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(FALSE); + addChild( folder ); + folder->getViewModelItem()->dirtyFilter(); + // rearrange all descendants too, as our indentation level might have changed + folder->requestArrange(); + requestSort(); + + getViewModelItem()->addChild(folder->getViewModelItem()); + + return TRUE; +} + +void LLFolderViewFolder::requestArrange() +{ + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } +} + +void LLFolderViewFolder::toggleOpen() +{ + setOpen(!isOpen()); +} + +// Force a folder open or closed +void LLFolderViewFolder::setOpen(BOOL openitem) +{ + setOpenArrangeRecursively(openitem); +} + +void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) +{ + BOOL was_open = isOpen(); + mIsOpen = openitem; + if(!was_open && openitem) + { + getViewModelItem()->openItem(); + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); + } + + if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ + } + } + if (mParentFolder + && (recurse == RECURSE_UP + || recurse == RECURSE_UP_DOWN)) + { + mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); + } + + if (was_open != isOpen()) + { + requestArrange(); + } +} + +BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + // drag and drop to child item, so clear pending auto-opens + getRoot()->autoOpenTest(NULL); + + return TRUE; +} + +void LLFolderViewFolder::openItem( void ) +{ + toggleOpen(); +} + +void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + functor.doItem((*fit)); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) +{ + functor.doFolder(this); + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +// LLView functionality +BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL handled = FALSE; + + if (isOpen()) + { + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); + } + + if (!handled) + { + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; + } + + return TRUE; +} + +BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return TRUE; +} + + +BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + + if( isOpen() ) + { + handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; + } + if (!handled) + { + handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); + } + return handled; +} + + +BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + BOOL handled = LLView::handleHover(x, y, mask); + + if (!handled) + { + // this doesn't do child processing + handled = LLFolderViewItem::handleHover(x, y, mask); + } + + return handled; +} + +BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( isOpen() ) + { + handled = childrenHandleMouseDown(x,y,mask) != NULL; + } + if( !handled ) + { + if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + { + toggleOpen(); + handled = TRUE; + } + else + { + // do normal selection logic + handled = LLFolderViewItem::handleMouseDown(x, y, mask); + } + } + + return handled; +} + +BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + BOOL handled = FALSE; + if( isOpen() ) + { + handled = childrenHandleDoubleClick( x, y, mask ) != NULL; + } + if( !handled ) + { + if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) + { + // don't select when user double-clicks plus sign + // so as not to contradict single-click behavior + toggleOpen(); + } + else + { + getRoot()->setSelection(this, FALSE); + toggleOpen(); + } + handled = TRUE; + } + return handled; +} + +void LLFolderViewFolder::draw() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + } + + LLFolderViewItem::draw(); + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) + { + LLView::draw(); + } + + mExpanderHighlighted = FALSE; +} + +// this does prefix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at beginning + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::iterator fit = mFolders.begin(); + folders_t::iterator fend = mFolders.end(); + + items_t::iterator iit = mItems.begin(); + items_t::iterator iend = mItems.end(); + + // if not trivially starting at the beginning, we have to find the current item + if (!found_item) + { + // first, look among folders, since they are always above items + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // if we are on downwards traversal + if (include_children && (*fit)->isOpen()) + { + // look for first descendant + return (*fit)->getNextFromChild(NULL, TRUE); + } + // otherwise advance to next folder + ++fit; + include_children = TRUE; + break; + } + } + + // didn't find in folders? Check items... + if (!found_item) + { + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found folder, continue through folders + // searching for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + // turn on downwards traversal for next folder + ++fit; + } + + if (fit != fend) + { + result = (*fit); + } + else + { + // otherwise, scan for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + // check to see if we have a valid item + if (iit != iend) + { + result = (*iit); + } + } + + if( !result && mParentFolder ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // and skip children for this folder, as we've already discounted them + result = mParentFolder->getNextFromChild(this, FALSE); + } + + return result; +} + +// this does postfix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) +{ + BOOL found_item = FALSE; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at end + if(item == NULL) + { + found_item = TRUE; + } + + // find current item among children + folders_t::reverse_iterator fit = mFolders.rbegin(); + folders_t::reverse_iterator fend = mFolders.rend(); + + items_t::reverse_iterator iit = mItems.rbegin(); + items_t::reverse_iterator iend = mItems.rend(); + + // if not trivially starting at the end, we have to find the current item + if (!found_item) + { + // first, look among items, since they are always below the folders + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = TRUE; + // point to next item + ++iit; + break; + } + } + + // didn't find in items? Check folders... + if (!found_item) + { + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = TRUE; + // point to next folder + ++fit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(FALSE); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found item, continue through items + // searching for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + if (iit != iend) + { + // we found an appropriate item + result = (*iit); + } + else + { + // otherwise, scan for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + ++fit; + } + + // check to see if we have a valid folder + if (fit != fend) + { + // try selecting child element of this folder + if ((*fit)->isOpen()) + { + result = (*fit)->getPreviousFromChild(NULL); + } + else + { + result = (*fit); + } + } + } + + if( !result ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // which gets back to this folder, which will only be visited if it is a valid, visible item + result = this; + } + + return result; +} + diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h new file mode 100644 index 0000000000..9cb885066a --- /dev/null +++ b/indra/llui/llfolderviewitem.h @@ -0,0 +1,420 @@ +/** +* @file llfolderviewitem.h +* @brief Items and folders that can appear in a hierarchical folder view +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LLFOLDERVIEWITEM_H +#define LLFOLDERVIEWITEM_H + +#include "llview.h" +#include "lluiimage.h" + +class LLFolderView; +class LLFolderViewModelItem; +class LLFolderViewFolder; +class LLFolderViewFunctor; +class LLFolderViewFilter; +class LLFolderViewModelInterface; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewItem +// +// An instance of this class represents a single item in a folder view +// such as an inventory item or a file. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewItem : public LLView +{ +public: + static void initClass(); + static void cleanupClass(); + + struct Params : public LLInitParam::Block + { + Optional folder_arrow_image, + selection_image; + Optional root; + Mandatory listener; + + Optional folder_indentation, // pixels + item_height, + item_top_pad; + + Optional creation_date; + + Params(); + }; + + // layout constants + static const S32 LEFT_PAD = 5; + // LEFT_INDENTATION is set via folder_indentation above + static const S32 ICON_PAD = 2; + static const S32 ICON_WIDTH = 16; + static const S32 TEXT_PAD = 1; + static const S32 TEXT_PAD_RIGHT = 4; + static const S32 ARROW_SIZE = 12; + static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; + // animation parameters + static const F32 FOLDER_CLOSE_TIME_CONSTANT; + static const F32 FOLDER_OPEN_TIME_CONSTANT; + +private: + BOOL mIsSelected; + +protected: + friend class LLUICtrlFactory; + friend class LLFolderViewModelItem; + + LLFolderViewItem(const Params& p); + + std::string mLabel; + S32 mLabelWidth; + bool mLabelWidthDirty; + LLFolderViewFolder* mParentFolder; + LLFolderViewModelItem* mViewModelItem; + BOOL mIsCurSelection; + BOOL mSelectPending; + LLFontGL::StyleFlags mLabelStyle; + std::string mLabelSuffix; + LLUIImagePtr mIcon; + LLUIImagePtr mIconOpen; + LLUIImagePtr mIconOverlay; + BOOL mHasVisibleChildren; + S32 mIndentation; + S32 mItemHeight; + S32 mDragStartX, + mDragStartY; + + //TODO RN: create interface for string highlighting + //std::string::size_type mStringMatchOffset; + F32 mControlLabelRotation; + LLFolderView* mRoot; + BOOL mDragAndDropTarget; + bool mIsMouseOverTitle; + + // this is an internal method used for adding items to folders. A + // no-op at this level, but reimplemented in derived classes. + virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } + virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } + + static LLFontGL* getLabelFontForStyle(U8 style); + +public: + BOOL postBuild(); + + virtual void openItem( void ); + + void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); + + virtual ~LLFolderViewItem( void ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual BOOL addToFolder(LLFolderViewFolder* folder); + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height ); + virtual S32 getItemHeight(); + + // If 'selection' is 'this' then note that otherwise ignore. + // Returns TRUE if this item ends up being selected. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); + + // This method is used to set the selection state of an item. + // If 'selection' is 'this' then note selection. + // Returns TRUE if the selection state of this item was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to deselect this element + void deselectItem(); + + // this method is used to select this element + virtual void selectItem(); + + // gets multiple-element selection + virtual std::set getSelectionList() const; + + // Returns true is this object and all of its children can be removed (deleted by user) + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this item recursively + virtual void destroyView(); + + BOOL isSelected() const { return mIsSelected; } + + void setUnselected() { mIsSelected = FALSE; } + + void setIsCurSelection(BOOL select) { mIsCurSelection = select; } + + BOOL getIsCurSelection() { return mIsCurSelection; } + + BOOL hasVisibleChildren() { return mHasVisibleChildren; } + + // Call through to the viewed object and return true if it can be + // removed. Returns true if it's removed. + //virtual BOOL removeRecursively(BOOL single_item); + BOOL remove(); + + // Build an appropriate context menu for the item. Flags unused. + void buildContextMenu(class LLMenuGL& menu, U32 flags); + + // This method returns the actual name of the thing being + // viewed. This method will ask the viewed object itself. + const std::string& getName( void ) const; + + // This method returns the label displayed on the view. This + // method was primarily added to allow sorting on the folder + // contents possible before the entire view has been constructed. + const std::string& getLabel() const { return mLabel; } + + + LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } + const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } + + void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } + + LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); + + const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } + LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } + + const LLFolderViewModelInterface* getFolderViewModel( void ) const; + LLFolderViewModelInterface* getFolderViewModel( void ); + + // just rename the object. + void rename(const std::string& new_name); + + + // Show children (unfortunate that this is called "open") + virtual void setOpen(BOOL open = TRUE) {}; + virtual BOOL isOpen() const { return FALSE; } + + virtual LLFolderView* getRoot(); + virtual const LLFolderView* getRoot() const; + BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); + S32 getIndentation() { return mIndentation; } + + virtual BOOL passedFilter(S32 filter_generation = -1); + + // refresh information from the object being viewed. + virtual void refresh(); + + // LLView functionality + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } + + // virtual void handleDropped(); + virtual void draw(); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + +private: + static std::map sFonts; // map of styles to fonts +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFolder +// +// An instance of an LLFolderViewFolder represents a collection of +// more folders and items. This is used to build the hierarchy of +// items found in the folder view. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFolderViewFolder : public LLFolderViewItem +{ +protected: + LLFolderViewFolder( const LLFolderViewItem::Params& ); + friend class LLUICtrlFactory; + +public: + + typedef std::list items_t; + typedef std::list folders_t; + +protected: + items_t mItems; + folders_t mFolders; + + BOOL mIsOpen; + BOOL mExpanderHighlighted; + F32 mCurHeight; + F32 mTargetHeight; + F32 mAutoOpenCountdown; + S32 mLastArrangeGeneration; + S32 mLastCalculatedWidth; + S32 mMostFilteredDescendantGeneration; + bool mNeedsSort; + +public: + typedef enum e_recurse_type + { + RECURSE_NO, + RECURSE_UP, + RECURSE_DOWN, + RECURSE_UP_DOWN + } ERecurseType; + + + virtual ~LLFolderViewFolder( void ); + + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); + + // addToFolder() returns TRUE if it succeeds. FALSE otherwise + virtual BOOL addToFolder(LLFolderViewFolder* folder); + + // Finds width and height of this object and it's children. Also + // makes sure that this view and it's children are the right size. + virtual S32 arrange( S32* width, S32* height ); + + BOOL needsArrange(); + + bool descendantsPassedFilter(S32 filter_generation = -1); + + // Passes selection information on to children and record + // selection information if necessary. + // Returns TRUE if this object (or a child) ends up being selected. + // If 'openitem' is TRUE then folders are opened up along the way to the selection. + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); + + // This method is used to change the selection of an item. + // Recursively traverse all children; if 'selection' is 'this' then change + // the select status if necessary. + // Returns TRUE if the selection state of this folder, or of a child, was changed. + virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); + + // this method is used to group select items + void extendSelectionTo(LLFolderViewItem* selection); + + // Returns true is this object and all of its children can be removed. + virtual BOOL isRemovable(); + + // Returns true is this object and all of its children can be moved + virtual BOOL isMovable(); + + // destroys this folder, and all children + virtual void destroyView(); + + // If this folder can be removed, remove all children that can be + // removed, return TRUE if this is empty after the operation and + // it's viewed folder object can be removed. + //virtual BOOL removeRecursively(BOOL single_item); + //virtual BOOL remove(); + + // extractItem() removes the specified item from the folder, but + // doesn't delete it. + virtual void extractItem( LLFolderViewItem* item ); + + // This function is called by a child that needs to be resorted. + void resort(LLFolderViewItem* item); + + void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } + + // folders can be opened. This will usually be called by internal + // methods. + virtual void toggleOpen(); + + // Force a folder open or closed + virtual void setOpen(BOOL openitem = TRUE); + + // Called when a child is refreshed. + virtual void requestArrange(); + + virtual void requestSort(); + + // internal method which doesn't update the entire view. This + // method was written because the list iterators destroy the state + // of other iterations, thus, we can't arrange while iterating + // through the children (such as when setting which is selected. + virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); + + // Get the current state of the folder. + virtual BOOL isOpen() const { return mIsOpen; } + + // special case if an object is dropped on the child. + BOOL handleDragAndDropFromChild(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void applyFunctorRecursively(LLFolderViewFunctor& functor); + + // Just apply this functor to the folder's immediate children. + void applyFunctorToChildren(LLFolderViewFunctor& functor); + + virtual void openItem( void ); + virtual BOOL addItem(LLFolderViewItem* item); + virtual BOOL addFolder( LLFolderViewFolder* folder); + + // LLView functionality + virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + virtual void draw(); + + folders_t::iterator getFoldersBegin() { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() { return mFolders.end(); } + folders_t::size_type getFoldersCount() const { return mFolders.size(); } + + items_t::const_iterator getItemsBegin() const { return mItems.begin(); } + items_t::const_iterator getItemsEnd() const { return mItems.end(); } + items_t::size_type getItemsCount() const { return mItems.size(); } + + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); + void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items); + +public: + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } + template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } +}; + + +#endif // LLFOLDERVIEWITEM_H diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp new file mode 100644 index 0000000000..dc6e4d754b --- /dev/null +++ b/indra/llui/llfolderviewmodel.cpp @@ -0,0 +1,53 @@ +/** + * @file llfolderviewmodel.cpp + * @brief Implementation of the view model collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderviewmodel.h" +#include "lltrans.h" + +bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + +std::string LLFolderViewModelCommon::getStatusText() +{ + if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) + { + return LLTrans::getString("Searching"); + } + else + { + return getFilter()->getEmptyLookupMessage(); + } +} + +void LLFolderViewModelCommon::filter() +{ + getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); + mFolderView->getViewModelItem()->filter(*getFilter()); +} diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h new file mode 100644 index 0000000000..0f5f9a1f50 --- /dev/null +++ b/indra/llui/llfolderviewmodel.h @@ -0,0 +1,353 @@ +/** + * @file llfolderviewmodel.h + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWMODEL_H +#define LLFOLDERVIEWMODEL_H + +#include "llfontgl.h" // just for StyleFlags enum +#include "llfolderview.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: + enum EFilterModified + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + }; + +public: + + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewModelItem* item) = 0; + virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + virtual std::string getEmptyLookupMessage() const = 0; + + virtual bool showAllResults() const = 0; + + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Count + // +-------------------------------------------------------------------+ + virtual void setFilterCount(S32 count) = 0; + virtual S32 getFilterCount() const = 0; + virtual void decrementFilterCount() = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual bool isDefault() const = 0; + virtual bool isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; + + virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; + + virtual bool startDrag(std::vector& items) = 0; +}; + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: + LLFolderViewModelCommon() + : mTargetSortVersion(0), + mFolderView(NULL) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + virtual std::string getStatusText(); + virtual void filter(); + + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; + LLFolderView* mFolderView; + +}; + +template +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: + virtual ~LLFolderViewModelItem( void ) {}; + + virtual void update() {} //called when drawing + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + virtual const std::string& getSearchableName() const = 0; + + virtual LLPointer getIcon() const = 0; + virtual LLPointer getIconOpen() const { return getIcon(); } + virtual LLPointer getIconOverlay() const { return NULL; } + + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; + + virtual void openItem( void ) = 0; + virtual void closeItem( void ) = 0; + virtual void selectItem(void) = 0; + + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(std::vector& batch) = 0; + + virtual BOOL isItemCopyable() const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual BOOL cutToClipboard() const = 0; + + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + + virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? + + virtual bool filter( LLFolderViewFilter& filter) = 0; + virtual bool passedFilter(S32 filter_generation = -1) = 0; + virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; + virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; + virtual void dirtyFilter() = 0; + + virtual S32 getLastFilterGeneration() const = 0; + + virtual bool hasChildren() const = 0; + virtual void addChild(LLFolderViewModelItem* child) = 0; + virtual void removeChild(LLFolderViewModelItem* child) = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; + virtual void setParent(LLFolderViewModelItem* parent) = 0; + +protected: + + friend class LLFolderViewItem; + virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; + +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: + LLFolderViewModelItemCommon() + : mSortVersion(-1), + mPassedFilter(true), + mPassedFolderFilter(true), + mFolderViewItem(NULL), + mLastFilterGeneration(-1), + mMostFilteredDescendantGeneration(-1), + mParent(NULL) + { + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + } + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = version;} + + S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + void dirtyFilter() + { + mLastFilterGeneration = -1; + + // bubble up dirty flag all the way to root + if (mParent) + { + mParent->dirtyFilter(); + } + } + virtual void addChild(LLFolderViewModelItem* child) + { + mChildren.push_back(child); + child->setParent(this); + } + virtual void removeChild(LLFolderViewModelItem* child) + { + mChildren.remove(child); + child->setParent(NULL); + } + +protected: + virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } + + S32 mSortVersion; + bool mPassedFilter; + bool mPassedFolderFilter; + + S32 mLastFilterGeneration; + S32 mMostFilteredDescendantGeneration; + + + typedef std::list child_list_t; + child_list_t mChildren; + LLFolderViewModelItem* mParent; + + void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + LLFolderViewItem* mFolderViewItem; +}; + + +#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 64bc70da58..b31b99f47c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -253,9 +253,6 @@ set(viewer_SOURCE_FILES llfloaterwhitelistentry.cpp llfloaterwindowsize.cpp llfloaterworldmap.cpp - llfolderview.cpp - llfolderviewitem.cpp - llfolderviewmodel.cpp llfolderviewmodelinventory.cpp llfollowcam.cpp llfriendcard.cpp @@ -813,10 +810,7 @@ set(viewer_HEADER_FILES llfloaterwhitelistentry.h llfloaterwindowsize.h llfloaterworldmap.h - llfolderview.h - llfolderviewmodel.h llfolderviewmodelinventory.h - llfolderviewitem.h llfollowcam.h llfriendcard.h llgesturelistener.h diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp deleted file mode 100644 index 10677db094..0000000000 --- a/indra/newview/llfolderview.cpp +++ /dev/null @@ -1,2105 +0,0 @@ -/** - * @file llfolderview.cpp - * @brief Implementation of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpanel.h" -#include "llscrollcontainer.h" // hack to allow scrolling -#include "lltextbox.h" -#include "lltrans.h" -#include "llui.h" -#include "lluictrlfactory.h" - -// Linden library includes -#include "lldbstrings.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llgl.h" -#include "llrender.h" - -// Third-party library includes -#include - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -const S32 RENAME_WIDTH_PAD = 4; -const S32 RENAME_HEIGHT_PAD = 1; -const S32 AUTO_OPEN_STACK_DEPTH = 16; -const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH - + LLFolderViewItem::ICON_PAD - + LLFolderViewItem::ARROW_SIZE - + LLFolderViewItem::TEXT_PAD - + /*first few characters*/ 40; -const S32 MINIMUM_RENAMER_WIDTH = 80; - -// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. -const S32 STATUS_TEXT_HPAD = 6; -const S32 STATUS_TEXT_VPAD = 8; - -enum { - SIGNAL_NO_KEYBOARD_FOCUS = 1, - SIGNAL_KEYBOARD_FOCUS = 2 -}; - -F32 LLFolderView::sAutoOpenTime = 1.f; - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to close themselves -// For efficiency, calls setOpenArrangeRecursively(). -// The calling function must then call: -// LLFolderView* root = getRoot(); -// if( root ) -// { -// root->arrange( NULL, NULL ); -// root->scrollToShowSelection(); -// } -// to patch things up. -class LLCloseAllFoldersFunctor : public LLFolderViewFunctor -{ -public: - LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } - virtual ~LLCloseAllFoldersFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - BOOL mOpen; -}; - - -void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) -{ - folder->setOpenArrangeRecursively(mOpen); -} - -// Do nothing. -void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) -{ } - -///---------------------------------------------------------------------------- -/// Class LLFolderViewScrollContainer -///---------------------------------------------------------------------------- - -// virtual -const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const -{ - LLRect rect = LLRect::null; - if (mScrolledView) - { - LLFolderView* folder_view = dynamic_cast(mScrolledView); - if (folder_view) - { - S32 height = folder_view->getRect().getHeight(); - - rect = mScrolledView->getRect(); - rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); - } - } - - return rect; -} - -LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) -: LLScrollContainer(p) -{} - -///---------------------------------------------------------------------------- -/// Class LLFolderView -///---------------------------------------------------------------------------- -LLFolderView::Params::Params() -: task_id("task_id"), - title("title"), - use_label_suffix("use_label_suffix"), - allow_multiselect("allow_multiselect", true), - show_empty_message("show_empty_message", true), - use_ellipses("use_ellipses", false) -{ - folder_indentation = -4; -} - - -// Default constructor -LLFolderView::LLFolderView(const Params& p) -: LLFolderViewFolder(p), - mScrollContainer( NULL ), - mPopupMenuHandle(), - mAllowMultiSelect(p.allow_multiselect), - mShowEmptyMessage(p.show_empty_message), - mShowFolderHierarchy(FALSE), - mSourceID(p.task_id), - mRenameItem( NULL ), - mNeedsScroll( FALSE ), - mUseLabelSuffix(p.use_label_suffix), - mPinningSelectedItem(FALSE), - mNeedsAutoSelect( FALSE ), - mAutoSelectOverride(FALSE), - mNeedsAutoRename(FALSE), - mShowSelectionContext(FALSE), - mShowSingleSelection(FALSE), - mArrangeGeneration(0), - mSignalSelectCallback(0), - mMinWidth(0), - mDragAndDropThisFrame(FALSE), - mCallbackRegistrar(NULL), - mParentPanel(p.parent_panel), - mUseEllipses(p.use_ellipses), - mDraggingOverItem(NULL), - mStatusTextBox(NULL), - mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model) -{ - mViewModel->setFolderView(this); - mRoot = this; - - LLRect rect = p.rect; - LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); - setRect( rect ); - reshape(rect.getWidth(), rect.getHeight()); - mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); - mKeyboardSelection = FALSE; - mIndentation = p.folder_indentation; - - //clear label - // go ahead and render root folder as usual - // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; - - // Escape is handled by reverting the rename, not commiting it (default behavior) - LLLineEditor::Params params; - params.name("ren"); - params.rect(rect); - params.font(getLabelFontForStyle(LLFontGL::NORMAL)); - params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); - params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); - params.commit_on_focus_lost(true); - params.visible(false); - mRenamer = LLUICtrlFactory::create (params); - addChild(mRenamer); - - // Textbox - LLTextBox::Params text_p; - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - LLRect new_r = LLRect(rect.mLeft + ICON_PAD, - rect.mTop - TEXT_PAD, - rect.mRight, - rect.mTop - TEXT_PAD - font->getLineHeight()); - text_p.rect(new_r); - text_p.name(std::string(p.name)); - text_p.font(font); - text_p.visible(false); - text_p.parse_urls(true); - text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 - // set text padding the same as in People panel. EXT-7047, EXT-4837 - text_p.h_pad(STATUS_TEXT_HPAD); - text_p.v_pad(STATUS_TEXT_VPAD); - mStatusTextBox = LLUICtrlFactory::create (text_p); - mStatusTextBox->setFollowsLeft(); - mStatusTextBox->setFollowsTop(); - //addChild(mStatusTextBox); - - - // make the popup menu available - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - - mViewModelItem->openItem(); -} - -// Destroys the object -LLFolderView::~LLFolderView( void ) -{ - closeRenamer(); - - // The release focus call can potentially call the - // scrollcontainer, which can potentially be called with a partly - // destroyed scollcontainer. Just null it out here, and no worries - // about calling into the invalid scroll container. - // Same with the renamer. - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - mAutoOpenItems.removeAllNodes(); - - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - - mAutoOpenItems.removeAllNodes(); - clearSelection(); - mItems.clear(); - mFolders.clear(); - - delete mViewModel; - mViewModel = NULL; -} - -BOOL LLFolderView::canFocusChildren() const -{ - return FALSE; -} - -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) -{ - LLFolderViewFolder::addFolder(folder); - - // TODO RN: enforce sort order of My Inventory followed by Library - //mFolders.remove(folder); - //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - //{ - // mFolders.push_back(folder); - //} - //else - //{ - // mFolders.insert(mFolders.begin(), folder); - //} - - return TRUE; -} - -void LLFolderView::closeAllFolders() -{ - // Close all the folders - setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); - arrangeAll(); -} - -void LLFolderView::openTopLevelFolders() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpen(TRUE); - } -} - -// This view grows and shrinks to enclose all of its children items and folders. -// *width should be 0 -// conform show folder state works -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) -{ - mMinWidth = 0; - S32 target_height; - - LLFolderViewFolder::arrange(&mMinWidth, &target_height); - - LLRect scroll_rect = mScrollContainer->getContentWindowRect(); - reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - - LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); - if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) - { - reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - } - - // move item renamer text field to item's new position - updateRenamerPosition(); - - return llround(mTargetHeight); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); - -void LLFolderView::filter( LLFolderViewFilter& filter ) -{ - LLFastTimer t2(FTM_FILTER); - filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); - - getViewModelItem()->filter(filter); -} - -void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLRect scroll_rect; - if (mScrollContainer) - { - LLView::reshape(width, height, called_from_parent); - scroll_rect = mScrollContainer->getContentWindowRect(); - } - width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(llround(mCurHeight), scroll_rect.getHeight()); - - // Restrict width within scroll container's width - if (mUseEllipses && mScrollContainer) - { - width = scroll_rect.getWidth(); - } - - LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, FALSE); -} - -void LLFolderView::addToSelectionList(LLFolderViewItem* item) -{ - if (item->isSelected()) - { - removeFromSelectionList(item); - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - item->setIsCurSelection(TRUE); - mSelectedItems.push_back(item); -} - -void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) -{ - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(FALSE); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) - { - if (*item_iter == item) - { - item_iter = mSelectedItems.erase(item_iter); - } - else - { - ++item_iter; - } - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(TRUE); - } -} - -LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) -{ - if(mSelectedItems.size()) - { - LLFolderViewItem* itemp = mSelectedItems.back(); - llassert(itemp->getIsCurSelection()); - return itemp; - } - return NULL; -} - - -// Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - - if( selection == this ) - { - return FALSE; - } - - if( selection && take_keyboard_focus) - { - mParentPanel->setFocus(TRUE); - } - - // clear selection down here because change of keyboard focus can potentially - // affect selection - clearSelection(); - - if(selection) - { - addToSelectionList(selection); - } - - BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); - if(openitem && selection) - { - selection->getParentFolder()->requestArrange(); - } - - llassert(mSelectedItems.size() <= 1); - - return rv; -} - -BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - - // can't select root folder - if(!selection || selection == this) - { - return FALSE; - } - - if (!mAllowMultiSelect) - { - clearSelection(); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - if (*item_iter == selection) - { - break; - } - } - - BOOL on_list = (item_iter != mSelectedItems.end()); - - if(selected && !on_list) - { - addToSelectionList(selection); - } - if(!selected && on_list) - { - removeFromSelectionList(selection); - } - - rv = LLFolderViewFolder::changeSelection(selection, selected); - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - - return rv; -} - -static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); -void LLFolderView::sanitizeSelection() -{ - LLFastTimer _(FTM_SANITIZE_SELECTION); - // store off current item in case it is automatically deselected - // and we want to preserve context - LLFolderViewItem* original_selected_item = getCurSelectedItem(); - - std::vector items_to_remove; - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewItem* item = *item_iter; - - // ensure that each ancestor is open and potentially passes filtering - BOOL visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item - // modify with parent open and filters states - LLFolderViewFolder* parent_folder = item->getParentFolder(); - // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - - // deselect item if any ancestor is closed or didn't pass filter requirements. - if (!visible) - { - items_to_remove.push_back(item); - } - - // disallow nested selections (i.e. folder items plus one or more ancestors) - // could check cached mum selections count and only iterate if there are any - // but that may be a premature optimization. - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) - { - LLFolderViewItem* other_item = *other_item_iter; - for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - } - } - - // Don't allow invisible items (such as root folders) to be selected. - if (item == getRoot()) - { - items_to_remove.push_back(item); - } - } - - std::vector::iterator item_it; - for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) - { - changeSelection(*item_it, FALSE); // toggle selection (also removes from list) - } - - // if nothing selected after prior constraints... - if (mSelectedItems.empty()) - { - // ...select first available parent of original selection - LLFolderViewItem* new_selection = NULL; - if (original_selected_item) - { - for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); - parent_folder; - parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder->getViewModelItem()->potentiallyVisible()) - { - // give initial selection to first ancestor folder that potentially passes the filter - if (!new_selection) - { - new_selection = parent_folder; - } - - // if any ancestor folder of original item is closed, move the selection up - // to the highest closed - if (!parent_folder->isOpen()) - { - new_selection = parent_folder; - } - } - } - } - else - { - new_selection = NULL; - } - - if (new_selection) - { - setSelection(new_selection, FALSE, FALSE); - } - } -} - -void LLFolderView::clearSelection() -{ - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) - { - (*item_it)->setUnselected(); - } - - mSelectedItems.clear(); -} - -std::set LLFolderView::getSelectionList() const -{ - std::set selection; - std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); - return selection; -} - -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) -{ - std::vector types; - uuid_vec_t cargo_ids; - selected_items_t::iterator item_it; - BOOL can_drag = TRUE; - if (!mSelectedItems.empty()) - { - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - EDragAndDropType type = DAD_NONE; - LLUUID id = LLUUID::null; - can_drag = can_drag && (*item_it)->getViewModelItem()->startDrag(&type, &id); - - types.push_back(type); - cargo_ids.push_back(id); - } - - LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID); - } - return can_drag; -} - -void LLFolderView::commitRename( const LLSD& data ) -{ - finishRenamingItem(); -} - -void LLFolderView::draw() -{ - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - // if cursor has moved off of me during drag and drop - // close all auto opened folders - if (!mDragAndDropThisFrame) - { - closeAutoOpenedFolders(); - } - - // while dragging, update selection rendering to reflect single/multi drag status - if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) - { - EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); - if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) - { - setShowSingleSelection(TRUE); - } - else - { - setShowSingleSelection(FALSE); - } - } - else - { - setShowSingleSelection(FALSE); - } - - - if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size()) - { - mSearchString.clear(); - } - - if (hasVisibleChildren()) - { - mStatusTextBox->setVisible( FALSE ); - } - else if (mShowEmptyMessage) - { - mStatusTextBox->setValue(getFolderViewModel()->getStatusText()); - mStatusTextBox->setVisible( TRUE ); - - // firstly reshape message textbox with current size. This is necessary to - // LLTextBox::getTextPixelHeight works properly - const LLRect local_rect = getLocalRect(); - mStatusTextBox->setShape(local_rect); - - // get preferable text height... - S32 pixel_height = mStatusTextBox->getTextPixelHeight(); - bool height_changed = local_rect.getHeight() != pixel_height; - if (height_changed) - { - // ... if it does not match current height, lets rearrange current view. - // This will indirectly call ::arrange and reshape of the status textbox. - // We should call this method to also notify parent about required rect. - // See EXT-7564, EXT-7047. - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - - LLUI::popMatrix(); - LLUI::pushMatrix(); - LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); - } - } - - // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, - // and arrow for the root folder - LLView::draw(); - - mDragAndDropThisFrame = FALSE; -} - -void LLFolderView::finishRenamingItem( void ) -{ - if(!mRenamer) - { - return; - } - if( mRenameItem ) - { - mRenameItem->rename( mRenamer->getText() ); - } - - closeRenamer(); - - // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. - scrollToShowSelection(); -} - -void LLFolderView::closeRenamer( void ) -{ - if (mRenamer && mRenamer->getVisible()) - { - // Triggers onRenamerLost() that actually closes the renamer. - LLUI::removePopup(mRenamer); - } -} - -bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector& selectedItems) -{ - LLFolderViewItem* item_parent = dynamic_cast(item->getParent()); - - if (item_parent) - { - for(std::vector::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) - { - const LLFolderViewItem* const selected_item = (*it); - - LLFolderViewItem* parent = item_parent; - - while (parent) - { - if (selected_item == parent) - { - return true; - } - - parent = dynamic_cast(parent->getParent()); - } - } - } - - return false; -} - -void LLFolderView::removeSelectedItems() -{ - if(getVisible() && getEnabled()) - { - // just in case we're removing the renaming item. - mRenameItem = NULL; - - // create a temporary structure which we will use to remove - // items, since the removal will futz with internal data - // structures. - std::vector items; - S32 count = mSelectedItems.size(); - if(count == 0) return; - LLFolderViewItem* item = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - item = *item_it; - if (item && item->isRemovable()) - { - items.push_back(item); - } - else - { - llinfos << "Cannot delete " << item->getName() << llendl; - return; - } - } - - // iterate through the new container. - count = items.size(); - LLUUID new_selection_id; - if(count == 1) - { - LLFolderViewItem* item_to_delete = items[0]; - LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); - if (!new_selection) - { - new_selection = item_to_delete->getPreviousOpenNode(FALSE); - } - if(parent) - { - if (item_to_delete->remove()) - { - // change selection on successful delete - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } - } - } - arrangeAll(); - } - else if (count > 1) - { - LLDynamicArray listeners; - LLFolderViewModelItem* listener; - LLFolderViewItem* last_item = items[count - 1]; - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(FALSE); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(FALSE); - while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) - { - new_selection = new_selection->getPreviousOpenNode(FALSE); - } - } - if (new_selection) - { - getRoot()->setSelection(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); - } - else - { - getRoot()->setSelection(NULL, mParentPanel->hasFocus()); - } - - for(S32 i = 0; i < count; ++i) - { - listener = items[i]->getViewModelItem(); - if(listener && (listeners.find(listener) == LLDynamicArray::FAIL)) - { - listeners.put(listener); - } - } - listener = static_cast(listeners.get(0)); - if(listener) - { - listener->removeBatch(listeners); - } - } - arrangeAll(); - scrollToShowSelection(); - } -} - -// TODO RN: abstract -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // mSelectedItems.front()->openItem(); - // } - // else - // { - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // listener->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - // } - //} -} - -void LLFolderView::propertiesSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - // } - // else - // { - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // LLFloater::setFloaterHost(multi_propertiesp); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } - - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - // } - //} -} - - -void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) -{ - if ((mAutoOpenItems.check() == item) || - (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || - item->isOpen()) - { - return; - } - - // close auto-opened folders - LLFolderViewFolder* close_item = mAutoOpenItems.check(); - while (close_item && close_item != item->getParentFolder()) - { - mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(FALSE); - close_item = mAutoOpenItems.check(); - } - - item->requestArrange(); - - mAutoOpenItems.push(item); - - item->setOpen(TRUE); - LLRect content_rect = mScrollContainer->getContentWindowRect(); - LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); - scrollToShowItem(item, constraint_rect); -} - -void LLFolderView::closeAutoOpenedFolders() -{ - while (mAutoOpenItems.check()) - { - LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(FALSE); - } - - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); -} - -BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) -{ - if (folder && mAutoOpenCandidate == folder) - { - if (mAutoOpenTimer.getStarted()) - { - if (!mAutoOpenCandidate->isOpen()) - { - mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); - } - if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) - { - autoOpenItem(folder); - mAutoOpenTimer.stop(); - return TRUE; - } - } - return FALSE; - } - - // otherwise new candidate, restart timer - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = folder; - mAutoOpenTimer.start(); - return FALSE; -} - -BOOL LLFolderView::canCopy() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - if (!item->getViewModelItem()->isItemCopyable()) - { - return FALSE; - } - } - return TRUE; -} - -// copy selected item -void LLFolderView::copy() -{ - // *NOTE: total hack to clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->copyToClipboard(); - } - } - } - mSearchString.clear(); -} - -BOOL LLFolderView::canCut() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return FALSE; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItem* listener = item->getViewModelItem(); - - if (!listener || !listener->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::cut() -{ - // clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->cutToClipboard(); - listener->removeItem(); - } - } - } - mSearchString.clear(); -} - -BOOL LLFolderView::canPaste() const -{ - if (mSelectedItems.empty()) - { - return FALSE; - } - - if(getVisible() && getEnabled()) - { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); ++item_it) - { - // *TODO: only check folders and parent folders of items - const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItem* listener = item->getViewModelItem(); - if(!listener || !listener->isClipboardPasteable()) - { - const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getViewModelItem(); - if (!listener || !listener->isClipboardPasteable()) - { - return FALSE; - } - } - } - return TRUE; - } - return FALSE; -} - -// paste selected item -void LLFolderView::paste() -{ - if(getVisible() && getEnabled()) - { - // find set of unique folders to paste into - std::set folder_set; - - selected_items_t::iterator selected_it; - for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - LLFolderViewItem* item = *selected_it; - LLFolderViewFolder* folder = dynamic_cast(item); - if (folder == NULL) - { - item = item->getParentFolder(); - } - folder_set.insert(folder); - } - - std::set::iterator set_iter; - for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) - { - LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); - if(listener && listener->isClipboardPasteable()) - { - listener->pasteFromClipboard(); - } - } - } - mSearchString.clear(); -} - -// public rename functionality - can only start the process -void LLFolderView::startRenamingSelectedItem( void ) -{ - // make sure selection is visible - scrollToShowSelection(); - - S32 count = mSelectedItems.size(); - LLFolderViewItem* item = NULL; - if(count > 0) - { - item = mSelectedItems.front(); - } - if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && - item->getViewModelItem()->isItemRenameable()) - { - mRenameItem = item; - - updateRenamerPosition(); - - - mRenamer->setText(item->getName()); - mRenamer->selectAll(); - mRenamer->setVisible( TRUE ); - // set focus will fail unless item is visible - mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - LLUI::addPopup(mRenamer); - } -} - -BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - LLView *item = NULL; - if (getChildCount() > 0) - { - item = *(getChildList()->begin()); - } - - switch( key ) - { - case KEY_F2: - mSearchString.clear(); - startRenamingSelectedItem(); - handled = TRUE; - break; - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( mRenameItem && mRenamer->getVisible() ) - { - finishRenamingItem(); - mSearchString.clear(); - handled = TRUE; - } - else - { - LLFolderView::openSelectedItems(); - handled = TRUE; - } - } - break; - - case KEY_ESCAPE: - if( mRenameItem && mRenamer->getVisible() ) - { - closeRenamer(); - handled = TRUE; - } - mSearchString.clear(); - break; - - case KEY_PAGE_UP: - mSearchString.clear(); - mScrollContainer->pageUp(30); - handled = TRUE; - break; - - case KEY_PAGE_DOWN: - mSearchString.clear(); - mScrollContainer->pageDown(30); - handled = TRUE; - break; - - case KEY_HOME: - mSearchString.clear(); - mScrollContainer->goToTop(); - handled = TRUE; - break; - - case KEY_END: - mSearchString.clear(); - mScrollContainer->goToBottom(); - break; - - case KEY_DOWN: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* next = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - next = last_selected->getNextOpenNode(FALSE); - if (next) - { - if (next->isSelected()) - { - // shrink selection - getRoot()->changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == next->getParentFolder()) - { - // grow selection - getRoot()->changeSelection(next, TRUE); - } - } - } - else - { - next = last_selected->getNextOpenNode(); - if( next ) - { - if (next == last_selected) - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - setSelection( next, FALSE, TRUE ); - } - else - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - return FALSE; - } - } - scrollToShowSelection(); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_UP: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = mSelectedItems.back(); - - if (!mKeyboardSelection) - { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; - } - - LLFolderViewItem* prev = NULL; - if (mask & MASK_SHIFT) - { - // don't shift select down to children of folders (they are implicitly selected through parent) - prev = last_selected->getPreviousOpenNode(FALSE); - if (prev) - { - if (prev->isSelected()) - { - // shrink selection - getRoot()->changeSelection(last_selected, FALSE); - } - else if (last_selected->getParentFolder() == prev->getParentFolder()) - { - // grow selection - getRoot()->changeSelection(prev, TRUE); - } - } - } - else - { - prev = last_selected->getPreviousOpenNode(); - if( prev ) - { - if (prev == this) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - { - clearSelection(); - return TRUE; - } - - return FALSE; - } - setSelection( prev, FALSE, TRUE ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - - handled = TRUE; - } - break; - - case KEY_RIGHT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( TRUE ); - mSearchString.clear(); - handled = TRUE; - } - break; - - case KEY_LEFT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - LLFolderViewItem* parent_folder = last_selected->getParentFolder(); - if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) - { - setSelection(parent_folder, FALSE, TRUE); - } - else - { - last_selected->setOpen( FALSE ); - } - mSearchString.clear(); - scrollToShowSelection(); - handled = TRUE; - } - break; - } - - if (!handled && mParentPanel->hasFocus()) - { - if (key == KEY_BACKSPACE) - { - mSearchTimer.reset(); - if (mSearchString.size()) - { - mSearchString.erase(mSearchString.size() - 1, 1); - } - search(getCurSelectedItem(), mSearchString, FALSE); - handled = TRUE; - } - } - - return handled; -} - - -BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) -{ - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return FALSE; - } - - if (uni_char > 0x7f) - { - llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; - return FALSE; - } - - BOOL handled = FALSE; - if (mParentPanel->hasFocus()) - { - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - //do text search - if (mSearchTimer.getElapsedTimeF32() > LLUI::sSettingGroups["config"]->getF32("TypeAheadTimeout")) - { - mSearchString.clear(); - } - mSearchTimer.reset(); - if (mSearchString.size() < 128) - { - mSearchString += uni_char; - } - search(getCurSelectedItem(), mSearchString, FALSE); - - handled = TRUE; - } - - return handled; -} - - -BOOL LLFolderView::canDoDelete() const -{ - if (mSelectedItems.size() == 0) return FALSE; - - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - if (!(*item_it)->getViewModelItem()->isItemRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -void LLFolderView::doDelete() -{ - if(mSelectedItems.size() > 0) - { - removeSelectedItems(); - } -} - - -BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - mKeyboardSelection = FALSE; - mSearchString.clear(); - - mParentPanel->setFocus(TRUE); - - LLEditMenuHandler::gEditMenuHandler = this; - - return LLView::handleMouseDown( x, y, mask ); -} - -BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) -{ - // get first selected item - LLFolderViewItem* search_item = first_item; - - // make sure search string is upper case - std::string upper_case_string = search_string; - LLStringUtil::toUpper(upper_case_string); - - // if nothing selected, select first item in folder - if (!search_item) - { - // start from first item - search_item = getNextFromChild(NULL); - } - - // search over all open nodes for first substring match (with wrapping) - BOOL found = FALSE; - LLFolderViewItem* original_search_item = search_item; - do - { - // wrap at end - if (!search_item) - { - if (backward) - { - search_item = getPreviousFromChild(NULL); - } - else - { - search_item = getNextFromChild(NULL); - } - if (!search_item || search_item == original_search_item) - { - break; - } - } - - const std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); - if (!current_item_label.compare(0, search_string_length, upper_case_string)) - { - found = TRUE; - break; - } - if (backward) - { - search_item = search_item->getPreviousOpenNode(); - } - else - { - search_item = search_item->getNextOpenNode(); - } - - } while(search_item != original_search_item); - - - if (found) - { - setSelection(search_item, FALSE, TRUE); - scrollToShowSelection(); - } - - return found; -} - -BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - // skip LLFolderViewFolder::handleDoubleClick() - return LLView::handleDoubleClick( x, y, mask ); -} - -BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - // all user operations move keyboard focus to inventory - // this way, we know when to stop auto-updating a search - mParentPanel->setFocus(TRUE); - - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if ( handled - && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible - && menu ) - { - if (mCallbackRegistrar) - mCallbackRegistrar->pushScope(); - - updateMenuOptions(menu); - - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - if (mCallbackRegistrar) - mCallbackRegistrar->popScope(); - } - else - { - if (menu && menu->getVisible()) - { - menu->setVisible(FALSE); - } - setSelection(NULL, FALSE, TRUE); - } - return handled; -} - -// Add "--no options--" if the menu is completely blank. -BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const -{ - const std::string nooptions_str = "--no options--"; - LLView *nooptions_item = NULL; - - const LLView::child_list_t *list = menu->getChildList(); - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) - { - LLView *menu_item = (*itor); - if (menu_item->getVisible()) - { - return FALSE; - } - std::string name = menu_item->getName(); - if (menu_item->getName() == nooptions_str) - { - nooptions_item = menu_item; - } - } - if (nooptions_item) - { - nooptions_item->setVisible(TRUE); - nooptions_item->setEnabled(FALSE); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) -{ - return LLView::handleHover( x, y, mask ); -} - -BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - mDragAndDropThisFrame = TRUE; - // have children handle it first - BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); - - // when drop is not handled by child, it should be handled - // by the folder which is the hierarchy root. - if (!handled) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - return handled; -} - -void LLFolderView::deleteAllChildren() -{ - closeRenamer(); - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle = LLHandle(); - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - clearSelection(); - LLView::deleteAllChildren(); -} - -void LLFolderView::scrollToShowSelection() -{ - if ( mSelectedItems.size() ) - { - mNeedsScroll = TRUE; - } -} - -// If the parent is scroll container, scroll it to make the selection -// is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) -{ - if (!mScrollContainer) return; - - // don't scroll to items when mouse is being used to scroll/drag and drop - if (gFocusMgr.childHasMouseCapture(mScrollContainer)) - { - mNeedsScroll = FALSE; - return; - } - - // if item exists and is in visible portion of parent folder... - if(item) - { - LLRect local_rect = item->getLocalRect(); - LLRect item_scrolled_rect; // item position relative to display area of scroller - LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); - - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); - // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder - S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); - - // get portion of item that we want to see... - LLRect item_local_rect = LLRect(item->getIndentation(), - local_rect.getHeight(), - llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()), - llmax(0, local_rect.getHeight() - max_height_to_show)); - - LLRect item_doc_rect; - - item->localRectToOtherView(item_local_rect, &item_doc_rect, this); - - mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - - } -} - -LLRect LLFolderView::getVisibleRect() -{ - S32 visible_height = mScrollContainer->getRect().getHeight(); - S32 visible_width = mScrollContainer->getRect().getWidth(); - LLRect visible_rect; - visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); - return visible_rect; -} - -BOOL LLFolderView::getShowSelectionContext() -{ - if (mShowSelectionContext) - { - return TRUE; - } - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - return TRUE; - } - return FALSE; -} - -void LLFolderView::setShowSingleSelection(BOOL show) -{ - if (show != mShowSingleSelection) - { - mMultiSelectionFadeTimer.reset(); - mShowSingleSelection = show; - } -} - -static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); -static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); - -// Main idle routine -void LLFolderView::update() -{ - // If this is associated with the user's inventory, don't do anything - // until that inventory is loaded up. - LLFastTimer t2(FTM_INVENTORY); - - if (getFolderViewModel()->getFilter()->isModified() && getFolderViewModel()->getFilter()->isNotDefault()) - { - mNeedsAutoSelect = TRUE; - } - getFolderViewModel()->getFilter()->clearModified(); - - // filter to determine visibility before arranging - filter(*(getFolderViewModel()->getFilter())); - - // automatically show matching items, and select first one if we had a selection - if (mNeedsAutoSelect) - { - LLFastTimer t3(FTM_AUTO_SELECT); - // select new item only if a filtered item not currently selected - LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLSelectFirstFilteredItem functor; - applyFunctorRecursively(functor); - } - - // Open filtered folders for folder views with mAutoSelectOverride=TRUE. - // Used by LLPlacesFolderView. - if (getFolderViewModel()->getFilter()->showAllResults()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLOpenFilteredFolders functor; - applyFunctorRecursively(functor); - } - - scrollToShowSelection(); - } - - BOOL filter_finished = getViewModelItem()->passedFilter() - && mViewModel->contentsReady(); - if (filter_finished - || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container - || gFocusMgr.childHasMouseCapture(getParent())) - { - // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process - mNeedsAutoSelect = FALSE; - } - - - // during filtering process, try to pin selected item's location on screen - // this will happen when searching your inventory and when new items arrive - if (!filter_finished) - { - // calculate rectangle to pin item to at start of animated rearrange - if (!mPinningSelectedItem && !mSelectedItems.empty()) - { - // lets pin it! - mPinningSelectedItem = TRUE; - - LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); - LLFolderViewItem* selected_item = mSelectedItems.back(); - - LLRect item_rect; - selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); - // if item is visible in scrolled region - if (visible_content_rect.overlaps(item_rect)) - { - // then attempt to keep it in same place on screen - mScrollConstraintRect = item_rect; - mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); - } - else - { - // otherwise we just want it onscreen somewhere - LLRect content_rect = mScrollContainer->getContentWindowRect(); - mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - } - } - else - { - // stop pinning selected item after folders stop rearranging - if (!needsArrange()) - { - mPinningSelectedItem = FALSE; - } - } - - LLRect constraint_rect; - if (mPinningSelectedItem) - { - // use last known constraint rect for pinned item - constraint_rect = mScrollConstraintRect; - } - else - { - // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = mScrollContainer->getContentWindowRect(); - constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - - BOOL is_visible = isInVisibleChain(); - - if ( is_visible ) - { - sanitizeSelection(); - if( needsArrange() ) - { - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - } - } - - if (mSelectedItems.size() && mNeedsScroll) - { - scrollToShowItem(mSelectedItems.back(), constraint_rect); - // continue scrolling until animated layout change is done - if (filter_finished - && (!needsArrange() || !is_visible)) - { - mNeedsScroll = FALSE; - } - } - - if (mSignalSelectCallback) - { - //RN: we use keyboard focus as a proxy for user-explicit actions - BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); - mSelectSignal(mSelectedItems, take_keyboard_focus); - } - mSignalSelectCallback = FALSE; -} - -void LLFolderView::dumpSelectionInformation() -{ - llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; - llinfos << "****************************************" << llendl; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - llinfos << " " << (*item_it)->getName() << llendl; - } - llinfos << "****************************************" << llendl; -} - -void LLFolderView::updateRenamerPosition() -{ - if(mRenameItem) - { - // See also LLFolderViewItem::draw() - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); - S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenameItem->localPointToScreen( x, y, &x, &y ); - screenPointToLocal( x, y, &x, &y ); - mRenamer->setOrigin( x, y ); - - LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); - if (mScrollContainer) - { - scroller_rect = mScrollContainer->getContentWindowRect(); - } - - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenamer->reshape( width, height, TRUE ); - } -} - -// Update visibility and availability (i.e. enabled/disabled) of context menu items. -void LLFolderView::updateMenuOptions(LLMenuGL* menu) -{ - const LLView::child_list_t *list = menu->getChildList(); - - LLView::child_list_t::const_iterator menu_itor; - for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) - { - (*menu_itor)->setVisible(FALSE); - (*menu_itor)->pushVisible(TRUE); - (*menu_itor)->setEnabled(TRUE); - } - - // Successively filter out invalid options - - U32 flags = FIRST_SELECTED_ITEM; - for (selected_items_t::iterator item_itor = mSelectedItems.begin(); - item_itor != mSelectedItems.end(); - ++item_itor) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->buildContextMenu(*menu, flags); - flags = 0x0; - } - - addNoOptions(menu); -} - -// Refresh the context menu (that is already shown). -void LLFolderView::updateMenu() -{ - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - updateMenuOptions(menu); - menu->needsArrange(); // update menu height if needed - } -} - -bool LLFolderView::selectFirstItem() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();++iter) - { - LLFolderViewFolder* folder = (*iter ); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getNextFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; -} -bool LLFolderView::selectLastItem() -{ - for(items_t::reverse_iterator iit = mItems.rbegin(); - iit != mItems.rend(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,FALSE,TRUE); - return true; - } - } - for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();++iter) - { - LLFolderViewFolder* folder = (*iter); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); - if(itemp) - setSelection(itemp,FALSE,TRUE); - return true; - } - } - return false; -} - - -S32 LLFolderView::notify(const LLSD& info) -{ - if(info.has("action")) - { - std::string str_action = info["action"]; - if(str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - scrollToShowSelection(); - return 1; - - } - else if(str_action == "select_last") - { - setFocus(true); - selectLastItem(); - scrollToShowSelection(); - return 1; - } - } - return 0; -} - - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- - -void LLFolderView::onRenamerLost() -{ - if (mRenamer && mRenamer->getVisible()) - { - mRenamer->setVisible(FALSE); - - // will commit current name (which could be same as original name) - mRenamer->setFocus(FALSE); - } - - if( mRenameItem ) - { - setSelection( mRenameItem, TRUE ); - mRenameItem = NULL; - } -} - -S32 LLFolderView::getItemHeight() -{ - if(!hasVisibleChildren()) - { - //We need to display status textbox, let's reserve some place for it - return llmax(0, mStatusTextBox->getTextPixelHeight()); - } - return 0; -} diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h deleted file mode 100644 index 78f1d8aff2..0000000000 --- a/indra/newview/llfolderview.h +++ /dev/null @@ -1,393 +0,0 @@ -/** - * @file llfolderview.h - * @brief Definition of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -/** - * - * The folder view collection of classes provides an interface for - * making a 'folder view' similar to the way the a single pane file - * folder interface works. - * - */ - -#ifndef LL_LLFOLDERVIEW_H -#define LL_LLFOLDERVIEW_H - -#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder - -#include "lluictrl.h" -#include "v4color.h" -#include "stdenums.h" -#include "lldepthstack.h" -#include "lleditmenuhandler.h" -#include "llfontgl.h" -#include "llscrollcontainer.h" -#include "lltooldraganddrop.h" - -class LLFolderViewModelInterface; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLFolderViewFilter; -class LLPanel; -class LLLineEditor; -class LLMenuGL; -class LLUICtrl; -class LLTextBox; - -/** - * Class LLFolderViewScrollContainer - * - * A scroll container which provides the information about the height - * of currently displayed folder view contents. - * Used for updating vertical scroll bar visibility in inventory panel. - * See LLScrollContainer::calcVisibleSize(). - */ -class LLFolderViewScrollContainer : public LLScrollContainer -{ -public: - /*virtual*/ ~LLFolderViewScrollContainer() {}; - /*virtual*/ const LLRect getScrolledViewRect() const; - -protected: - LLFolderViewScrollContainer(const LLScrollContainer::Params& p); - friend class LLUICtrlFactory; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderView -// -// The LLFolderView represents the root level folder view object. -// It manages the screen region of the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler -{ -public: - struct Params : public LLInitParam::Block - { - Mandatory parent_panel; - Optional task_id; - Optional title; - Optional use_label_suffix, - allow_multiselect, - show_empty_message, - use_ellipses, - show_item_link_overlays; - Mandatory view_model; - - Params(); - }; - - friend class LLFolderViewScrollContainer; - - LLFolderView(const Params&); - virtual ~LLFolderView( void ); - - virtual BOOL canFocusChildren() const; - - virtual const LLFolderView* getRoot() const { return this; } - virtual LLFolderView* getRoot() { return this; } - - LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } - const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } - - void setFilterPermMask(PermissionMask filter_perm_mask); - - typedef boost::signals2::signal& items, BOOL user_action)> signal_t; - void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } - void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - - bool getAllowMultiSelect() { return mAllowMultiSelect; } - - // Close all folders in the view - void closeAllFolders(); - void openTopLevelFolders(); - - virtual BOOL addFolder( LLFolderViewFolder* folder); - - // Find width and height of this object and its children. Also - // makes sure that this view and its children are the right size. - virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); - - void arrangeAll() { mArrangeGeneration++; } - S32 getArrangeGeneration() { return mArrangeGeneration; } - - // applies filters to control visibility of items - virtual void filter( LLFolderViewFilter& filter); - - // Get the last selected item - virtual LLFolderViewItem* getCurSelectedItem( void ); - - // Record the selected item and pass it down the hierarchy. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus = TRUE); - - // This method is used to toggle the selection of an item. Walks - // children, and keeps track of selected objects. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - virtual std::set getSelectionList() const; - S32 getNumSelectedItems() { return mSelectedItems.size(); } - - // Make sure if ancestor is selected, descendants are not - void sanitizeSelection(); - virtual void clearSelection(); - void addToSelectionList(LLFolderViewItem* item); - void removeFromSelectionList(LLFolderViewItem* item); - - BOOL startDrag(LLToolDragAndDrop::ESource source); - void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } - void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } - LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - - // Deletion functionality - void removeSelectedItems(); - - // Open the selected item - void openSelectedItems( void ); - void propertiesSelectedItems( void ); - - void autoOpenItem(LLFolderViewFolder* item); - void closeAutoOpenedFolders(); - BOOL autoOpenTest(LLFolderViewFolder* item); - BOOL isOpen() const { return TRUE; } // root folder always open - - // Copy & paste - virtual void copy(); - virtual BOOL canCopy() const; - - virtual void cut(); - virtual BOOL canCut() const; - - virtual void paste(); - virtual BOOL canPaste() const; - - virtual void doDelete(); - virtual BOOL canDoDelete() const; - - // Public rename functionality - can only start the process - void startRenamingSelectedItem( void ); - - // LLView functionality - ///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); - /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); - /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } - virtual void draw(); - virtual void deleteAllChildren(); - - void scrollToShowSelection(); - void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); - void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } - LLRect getVisibleRect(); - - BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); - void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } - BOOL getShowSelectionContext(); - void setShowSingleSelection(BOOL show); - BOOL getShowSingleSelection() { return mShowSingleSelection; } - F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } - bool getUseEllipses() { return mUseEllipses; } - - void update(); // needs to be called periodically (e.g. once per frame) - - BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } - BOOL needsAutoRename() { return mNeedsAutoRename; } - void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } - void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } - void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } - - bool showItemLinkOverlays() { return mShowItemLinkOverlays; } - - void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - - LLPanel* getParentPanel() { return mParentPanel; } - // DEBUG only - void dumpSelectionInformation(); - - virtual S32 notify(const LLSD& info) ; - - bool useLabelSuffix() { return mUseLabelSuffix; } - void updateMenu(); - -private: - void updateMenuOptions(LLMenuGL* menu); - void updateRenamerPosition(); - -protected: - LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. - - void commitRename( const LLSD& data ); - void onRenamerLost(); - - void finishRenamingItem( void ); - void closeRenamer( void ); - - bool selectFirstItem(); - bool selectLastItem(); - - BOOL addNoOptions(LLMenuGL* menu) const; - - -protected: - LLHandle mPopupMenuHandle; - - typedef std::deque selected_items_t; - selected_items_t mSelectedItems; - BOOL mKeyboardSelection; - BOOL mAllowMultiSelect; - BOOL mShowEmptyMessage; - BOOL mShowFolderHierarchy; - LLUUID mSourceID; - - // Renaming variables and methods - LLFolderViewItem* mRenameItem; // The item currently being renamed - LLLineEditor* mRenamer; - - BOOL mNeedsScroll; - BOOL mPinningSelectedItem; - LLRect mScrollConstraintRect; - BOOL mNeedsAutoSelect; - BOOL mAutoSelectOverride; - BOOL mNeedsAutoRename; - bool mUseLabelSuffix; - bool mShowItemLinkOverlays; - - LLDepthStack mAutoOpenItems; - LLFolderViewFolder* mAutoOpenCandidate; - LLFrameTimer mAutoOpenTimer; - LLFrameTimer mSearchTimer; - std::string mSearchString; - BOOL mShowSelectionContext; - BOOL mShowSingleSelection; - LLFrameTimer mMultiSelectionFadeTimer; - S32 mArrangeGeneration; - - signal_t mSelectSignal; - signal_t mReshapeSignal; - S32 mSignalSelectCallback; - S32 mMinWidth; - BOOL mDragAndDropThisFrame; - - LLPanel* mParentPanel; - - LLFolderViewModelInterface* mViewModel; - - /** - * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. - * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. - */ - bool mUseEllipses; // See EXT-719 - - /** - * Contains item under mouse pointer while dragging - */ - LLFolderViewItem* mDraggingOverItem; // See EXT-719 - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; - -public: - static F32 sAutoOpenTime; - LLTextBox* mStatusTextBox; - -}; - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: - virtual ~LLFolderViewFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder) = 0; - virtual void doItem(LLFolderViewItem* item) = 0; -}; - -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -// Flags for buildContextMenu() -const U32 SUPPRESS_OPEN_ITEM = 0x1; -const U32 FIRST_SELECTED_ITEM = 0x2; - -#endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp deleted file mode 100644 index dee3fe7218..0000000000 --- a/indra/newview/llfolderviewitem.cpp +++ /dev/null @@ -1,2060 +0,0 @@ -/** -* @file llfolderviewitem.cpp -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#include "llviewerprecompiledheaders.h" - -#include "llfolderviewitem.h" - -// viewer includes -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llpanel.h" - -// linden library includes -#include "llclipboard.h" -#include "llfocusmgr.h" // gFocusMgr -#include "lltrans.h" - -///---------------------------------------------------------------------------- -/// Class LLFolderViewItem -///---------------------------------------------------------------------------- - -static LLDefaultChildRegistry::Register r("folder_view_item"); - -// statics -std::map LLFolderViewItem::sFonts; // map of styles to fonts - -// only integers can be initialized in header -const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; -const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; - -const LLColor4U DEFAULT_WHITE(255, 255, 255); - - -//static -LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) -{ - LLFontGL* rtn = sFonts[style]; - if (!rtn) // grab label font with this style, lazily - { - LLFontDescriptor labelfontdesc("SansSerif", "Small", style); - rtn = LLFontGL::getFont(labelfontdesc); - if (!rtn) - { - rtn = LLFontGL::getFontDefault(); - } - sFonts[style] = rtn; - } - return rtn; -} - -//static -void LLFolderViewItem::initClass() -{ -} - -//static -void LLFolderViewItem::cleanupClass() -{ - sFonts.clear(); -} - - -// NOTE: Optimize this, we call it a *lot* when opening a large inventory -LLFolderViewItem::Params::Params() -: root(), - listener(), - folder_arrow_image("folder_arrow_image"), - folder_indentation("folder_indentation"), - selection_image("selection_image"), - item_height("item_height"), - item_top_pad("item_top_pad"), - creation_date() -{} - -// Default constructor -LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) -: LLView(p), - mLabelWidth(0), - mLabelWidthDirty(false), - mParentFolder( NULL ), - mIsSelected( FALSE ), - mIsCurSelection( FALSE ), - mSelectPending(FALSE), - mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(FALSE), - mIndentation(0), - mItemHeight(p.item_height), - //TODO RN: create interface for string highlighting - //mStringMatchOffset(std::string::npos), - mControlLabelRotation(0.f), - mDragAndDropTarget(FALSE), - mLabel(p.name), - mRoot(p.root), - mViewModelItem(p.listener), - mIsMouseOverTitle(false) -{ - if (mViewModelItem) - { - mViewModelItem->setFolderViewItem(this); - } -} - -BOOL LLFolderViewItem::postBuild() -{ - refresh(); - return TRUE; -} - -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) -{ - delete mViewModelItem; - mViewModelItem = NULL; -} - -LLFolderView* LLFolderViewItem::getRoot() -{ - return mRoot; -} - -const LLFolderView* LLFolderViewItem::getRoot() const -{ - return mRoot; -} -// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) -{ - LLFolderViewItem* root = this; - while( root->mParentFolder ) - { - if( root->mParentFolder == potential_ancestor ) - { - return TRUE; - } - root = root->mParentFolder; - } - return FALSE; -} - -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit last item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - - // Skip over items that are invisible or are hidden from the UI. - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit first item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -BOOL LLFolderViewItem::passedFilter(S32 filter_generation) -{ - return getViewModelItem()->passedFilter(filter_generation); -} - -void LLFolderViewItem::refresh() -{ - LLFolderViewModelItem& vmi = *getViewModelItem(); - - mLabel = vmi.getDisplayName(); - - setToolTip(mLabel); - mIcon = vmi.getIcon(); - mIconOpen = vmi.getIconOpen(); - mIconOverlay = vmi.getIconOverlay(); - - if (mRoot->useLabelSuffix()) - { - mLabelStyle = vmi.getLabelStyle(); - mLabelSuffix = vmi.getLabelSuffix(); - } - - //TODO RN: make sure this logic still fires - //std::string searchable_label(mLabel); - //searchable_label.append(mLabelSuffix); - //LLStringUtil::toUpper(searchable_label); - - //if (mSearchableLabel.compare(searchable_label)) - //{ - // mSearchableLabel.assign(searchable_label); - // vmi.dirtyFilter(); - // // some part of label has changed, so overall width has potentially changed, and sort order too - // if (mParentFolder) - // { - // mParentFolder->requestSort(); - // mParentFolder->requestArrange(); - // } - //} - - mLabelWidthDirty = true; - vmi.dirtyFilter(); -} - -// Utility function for LLFolderView -void LLFolderViewItem::arrangeAndSet(BOOL set_selection, - BOOL take_keyboard_focus) -{ - LLFolderView* root = getRoot(); - if (getParentFolder()) - { - getParentFolder()->requestArrange(); - } - if(set_selection) - { - getRoot()->setSelection(this, TRUE, take_keyboard_focus); - if(root) - { - root->scrollToShowSelection(); - } - } -} - - -std::set LLFolderViewItem::getSelectionList() const -{ - std::set selection; - return selection; -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) -{ - return folder->addItem(this); -} - - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height ) -{ - const Params& p = LLUICtrlFactory::getDefaultParams(); - S32 indentation = p.folder_indentation(); - // Only indent deeper items in hierarchy - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + indentation - : 0; - if (mLabelWidthDirty) - { - mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT; - mLabelWidthDirty = false; - } - - *width = llmax(*width, mLabelWidth + mIndentation); - - // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 - bool use_ellipses = getRoot()->getUseEllipses(); - if (use_ellipses) - { - // limit to set rect to avoid horizontal scrollbar - *width = llmin(*width, getRoot()->getRect().getWidth()); - } - *height = getItemHeight(); - return *height; -} - -S32 LLFolderViewItem::getItemHeight() -{ - return mItemHeight; -} - -// *TODO: This can be optimized a lot by simply recording that it is -// selected in the appropriate places, and assuming that set selection -// means 'deselect' for a leaf item. Do this optimization after -// multiple selection is implemented to make sure it all plays nice -// together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) -{ - if (selection == this && !mIsSelected) - { - selectItem(); - } - else if (mIsSelected) // Deselect everything else. - { - deselectItem(); - } - return mIsSelected; -} - -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - if (selection == this) - { - if (mIsSelected) - { - deselectItem(); - } - else - { - selectItem(); - } - return TRUE; - } - return FALSE; -} - -void LLFolderViewItem::deselectItem(void) -{ - mIsSelected = FALSE; -} - -void LLFolderViewItem::selectItem(void) -{ - if (mIsSelected == FALSE) - { - getViewModelItem()->selectItem(); - mIsSelected = TRUE; - } -} - -BOOL LLFolderViewItem::isMovable() -{ - return getViewModelItem()->isItemMovable(); -} - -BOOL LLFolderViewItem::isRemovable() -{ - return getViewModelItem()->isItemRemovable(); -} - -void LLFolderViewItem::destroyView() -{ - getRoot()->removeFromSelectionList(this); - - if (mParentFolder) - { - // removeView deletes me - mParentFolder->extractItem(this); - } - delete this; -} - -// Call through to the viewed object and return true if it can be -// removed. -//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) -BOOL LLFolderViewItem::remove() -{ - if(!isRemovable()) - { - return FALSE; - } - return getViewModelItem()->removeItem(); -} - -// Build an appropriate context menu for the item. -void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - getViewModelItem()->buildContextMenu(menu, flags); -} - -void LLFolderViewItem::openItem( void ) -{ - getViewModelItem()->openItem(); -} - -void LLFolderViewItem::rename(const std::string& new_name) -{ - if( !new_name.empty() ) - { - getViewModelItem()->renameItem(new_name); - - if(mParentFolder) - { - mParentFolder->requestSort(); - } - } - } - -const std::string& LLFolderViewItem::getName( void ) const -{ - return getViewModelItem()->getName(); -} - -// LLView functionality -BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - if(!mIsSelected) - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - return TRUE; -} - -BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseDown(x, y, mask)) - { - return TRUE; - } - - // No handler needed for focus lost since this class has no - // state that depends on it. - gFocusMgr.setMouseCapture( this ); - - if (!mIsSelected) - { - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - make_ui_sound("UISndClick"); - } - else - { - mSelectPending = TRUE; - } - - if( isMovable() ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); - } - return TRUE; -} - -BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - if( hasMouseCapture() && isMovable() ) - { - S32 screen_x; - S32 screen_y; - localPointToScreen(x, y, &screen_x, &screen_y ); - BOOL can_drag = TRUE; - if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) - { - LLFolderView* root = getRoot(); - - if(root->getCurSelectedItem()) - { - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; - - // *TODO: push this into listener and remove - // dependency on llagent - src = getViewModelItem()->getDragSource(); - - can_drag = root->startDrag(src); - if (can_drag) - { - // if (getViewModelItem()) getViewModelItem()->startDrag(); - // RN: when starting drag and drop, clear out last auto-open - root->autoOpenTest(NULL); - root->setShowSelectionContext(TRUE); - - // Release keyboard focus, so that if stuff is dropped into the - // world, pressing the delete key won't blow away the inventory - // item. - gFocusMgr.setKeyboardFocus(NULL); - - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); - } - } - } - - if (can_drag) - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - else - { - getWindow()->setCursor(UI_CURSOR_NOLOCKED); - } - return TRUE; - } - else - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(FALSE); - } - getWindow()->setCursor(UI_CURSOR_ARROW); - // let parent handle this then... - return FALSE; - } -} - - -BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - getViewModelItem()->openItem(); - return TRUE; -} - -BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseUp(x, y, mask)) - { - return TRUE; - } - - // if mouse hasn't moved since mouse down... - if ( pointInView(x, y) && mSelectPending ) - { - //...then select - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, FALSE); - } - } - - mSelectPending = FALSE; - - if( hasMouseCapture() ) - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(FALSE); - } - gFocusMgr.setMouseCapture( NULL ); - } - return TRUE; -} - -void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = false; -} - -BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = FALSE; - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - if(mParentFolder && !handled) - { - // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. - mRoot->setDraggingOverItem(this); - handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - mRoot->setDraggingOverItem(NULL); - } - if (handled) - { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; - } - - return handled; -} - -void LLFolderViewItem::draw() -{ - static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - - const Params& default_params = LLUICtrlFactory::getDefaultParams(); - const S32 TOP_PAD = default_params.item_top_pad; - const S32 FOCUS_LEFT = 1; - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - getViewModelItem()->update(); - - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - if (hasVisibleChildren() || getViewModelItem()->hasChildren()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); - } - - - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled - const S32 focus_top = getRect().getHeight(); - const S32 focus_bottom = getRect().getHeight() - mItemHeight; - const bool folder_open = (getRect().getHeight() > mItemHeight + 4); - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = sHighlightBgColor; - if (!mIsCurSelection) - { - // do time-based fade of extra objects - F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); - if (getRoot() && getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } - } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sFocusOutlineColor, FALSE); - } - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sFocusOutlineColor, FALSE); - if (show_context) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - sHighlightBgColor, TRUE); - } - } - } - else if (mIsMouseOverTitle) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sMouseOverColor, FALSE); - } - - //--------------------------------------------------------------------------------// - // Draw DragNDrop highlight - // - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - sHighlightBgColor, FALSE); - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - sHighlightBgColor, FALSE); - } - mDragAndDropTarget = FALSE; - } - - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - if (mIconOverlay && getRoot()->showItemLinkOverlays()) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - //--------------------------------------------------------------------------------// - // Exit if no label to draw - // - if (mLabel.empty()) - { - return; - } - - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - //TODO RN: implement this in terms of getColor() - //if (highlight_link) color = sLinkColor; - //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - - F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - - //--------------------------------------------------------------------------------// - // Draw the actual label text - // - font->renderUTF8(mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); - - //--------------------------------------------------------------------------------// - // Draw label suffix - // - if (!mLabelSuffix.empty()) - { - font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); - } - - //--------------------------------------------------------------------------------// - // Highlight string match - // - //TODO RN: expose interface for highlighting - //if (mStringMatchOffset != std::string::npos) - //{ - // // don't draw backgrounds for zero-length strings - // S32 filter_string_length = getRoot()->getFilterSubString().size(); - // if (filter_string_length > 0) - // { - // std::string combined_string = mLabel + mLabelSuffix; - // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - // S32 top = getRect().getHeight() - TOP_PAD; - // - // LLUIImage* box_image = default_params.selection_image; - // LLRect box_rect(left, top, right, bottom); - // box_image->draw(box_rect, sFilterBGColor); - // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - // filter_string_length, S32_MAX, &right_x, FALSE ); - // } - //} -} - -const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const - { - return getRoot()->getFolderViewModel(); -} - -LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) - { - return getRoot()->getFolderViewModel(); -} - - -///---------------------------------------------------------------------------- -/// Class LLFolderViewFolder -///---------------------------------------------------------------------------- - -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), - mIsOpen(FALSE), - mExpanderHighlighted(FALSE), - mCurHeight(0.f), - mTargetHeight(0.f), - mAutoOpenCountdown(0.f), - mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0) -{ -} - -// Destroys the object -LLFolderViewFolder::~LLFolderViewFolder( void ) -{ - // The LLView base class takes care of object destruction. make sure that we - // don't have mouse or keyboard focus - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) -{ - return folder->addFolder(this); -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height ) -{ - // sort before laying out contents - getRoot()->getFolderViewModel()->sort(this); - - LLFastTimer t2(FTM_ARRANGE); - - // evaluate mHasVisibleChildren - mHasVisibleChildren = false; - if (getViewModelItem()->descendantsPassedFilter()) - { - // We have to verify that there's at least one child that's not filtered out - bool found = false; - // Try the items first - for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - found = itemp->passedFilter(); - if (found) - break; - } - if (!found) - { - // If no item found, try the folders - for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - found = folderp->passedFilter(); - if (found) - break; - } - } - - mHasVisibleChildren = found; - } - - // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height ); - - // clamp existing animated height so as to never get smaller than a single item - mCurHeight = llmax((F32)*height, mCurHeight); - - // initialize running height value as height of single item in case we have no children - F32 running_height = (F32)*height; - F32 target_height = (F32)*height; - - // are my children visible? - if (needsArrange()) - { - // set last arrange generation first, in case children are animating - // and need to be arranged again - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (isOpen()) - { - // Add sizes of children - S32 parent_item_height = getRect().getHeight(); - - for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - folderp->setVisible(folderp->passedFilter()); // passed filter or has descendants that passed filter - - if (folderp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += folderp->arrange( &child_width, &child_height ); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); - } - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->passedFilter()); - - if (itemp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - llround(running_height); - - target_height += itemp->arrange( &child_width, &child_height ); - // don't change width, as this item is as wide as its parent folder by construction - itemp->reshape( itemp->getRect().getWidth(), child_height); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); - } - } - } - - mTargetHeight = target_height; - // cache this width so next time we can just return it - mLastCalculatedWidth = *width; - } - else - { - // just use existing width - *width = mLastCalculatedWidth; - } - - // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) - { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - - requestArrange(); - - // hide child elements that fall out of current animated height - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - // number of pixels that bottom of folder label is from top of parent folder - if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - // hide if beyond current folder height - (*fit)->setVisible(FALSE); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - // number of pixels that bottom of item label is from top of parent folder - if (getRect().getHeight() - (*iit)->getRect().mBottom - > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) - { - (*iit)->setVisible(FALSE); - } - } - } - else - { - mCurHeight = mTargetHeight; - } - - // don't change width as this item is already as wide as its parent folder - reshape(getRect().getWidth(),llround(mCurHeight)); - - // pass current height value back to parent - *height = llround(mCurHeight); - - return llround(mTargetHeight); -} - -BOOL LLFolderViewFolder::needsArrange() -{ - return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); -} - -void LLFolderViewFolder::requestSort() -{ - getViewModelItem()->requestSort(); -} - -//TODO RN: get height resetting working -//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) -//{ -// // if this folder is now filtered, but wasn't before -// // (it just passed) -// if (passed && !passedFilter(filter_generation)) -// { -// // reset current height, because last time we drew it -// // it might have had more visible items than now -// mCurHeight = 0.f; -// } -// -// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); -//} - - -// Passes selection information on to children and record selection -// information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) -{ - BOOL rv = FALSE; - if (selection == this) - { - if (!isSelected()) - { - selectItem(); - } - rv = TRUE; - } - else - { - if (isSelected()) - { - deselectItem(); - } - rv = FALSE; - } - BOOL child_selected = FALSE; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = TRUE; - child_selected = TRUE; - } - } - if(openitem && child_selected) - { - setOpenArrangeRecursively(TRUE); - } - return rv; -} - -// This method is used to change the selection of an item. -// Recursively traverse all children; if 'selection' is 'this' then change -// the select status if necessary. -// Returns TRUE if the selection state of this folder, or of a child, was changed. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ - BOOL rv = FALSE; - if(selection == this) - { - if (isSelected() != selected) - { - rv = TRUE; - if (selected) - { - selectItem(); - } - else - { - deselectItem(); - } - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->changeSelection(selection, selected)) - { - rv = TRUE; - } - } - return rv; -} - -LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) -{ - if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; - - std::deque item_a_ancestors; - - LLFolderViewFolder* parent = item_a->getParentFolder(); - while(parent) - { - item_a_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - std::deque item_b_ancestors; - - parent = item_b->getParentFolder(); - while(parent) - { - item_b_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - LLFolderViewFolder* common_ancestor = item_a->getRoot(); - - while(item_a_ancestors.size() > item_b_ancestors.size()) - { - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - } - - while(item_b_ancestors.size() > item_a_ancestors.size()) - { - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - while(item_a_ancestors.size()) - { - common_ancestor = item_a_ancestors.front(); - - if (item_a_ancestors.front() == item_b_ancestors.front()) - { - // which came first, sibling a or sibling b? - for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - - for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - break; - } - - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - return NULL; -} - -void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) -{ - bool selecting = start == NULL; - if (reverse) - { - for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } - else - { - for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } -} - -void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) -{ - if (getRoot()->getAllowMultiSelect() == FALSE) return; - - LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); - if (cur_selected_item == NULL) - { - cur_selected_item = new_selection; - } - - - bool reverse = false; - LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); - if (!common_ancestor) return; - - LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; - LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); - - std::vector items_to_select_forward; - - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); - - last_selected_item_from_cur = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - std::vector items_to_select_reverse; - - LLFolderViewItem* last_selected_item_from_new = new_selection; - cur_folder = new_selection->getParentFolder(); - while(cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); - - last_selected_item_from_new = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); - - for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); - it != end_it; - ++it) - { - items_to_select_forward.push_back(*it); - } - - LLFolderView* root = getRoot(); - - for (std::vector::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - if (item->isSelected()) - { - root->removeFromSelectionList(item); - } - else - { - item->selectItem(); - } - root->addToSelectionList(item); - } - - if (new_selection->isSelected()) - { - root->removeFromSelectionList(new_selection); - } - else - { - new_selection->selectItem(); - } - root->addToSelectionList(new_selection); -} - - -void LLFolderViewFolder::destroyView() -{ - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); - mItems.clear(); - - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - folderp->destroyView(); // removes entry from mFolders - } - - LLFolderViewItem::destroyView(); -} - -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) -{ - items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); - if(it == mItems.end()) - { - // This is an evil downcast. However, it's only doing - // pointer comparison to find if (which it should be ) the - // item is in the container, so it's pretty safe. - LLFolderViewFolder* f = static_cast(item); - folders_t::iterator ft; - ft = std::find(mFolders.begin(), mFolders.end(), f); - if (ft != mFolders.end()) - { - mFolders.erase(ft); - } - } - else - { - mItems.erase(it); - } - //item has been removed, need to update filter - getViewModelItem()->removeChild(item->getViewModelItem()); - getViewModelItem()->dirtyFilter(); - //because an item is going away regardless of filter status, force rearrange - requestArrange(); - removeChild(item); -} - -BOOL LLFolderViewFolder::isMovable() -{ - if( !(getViewModelItem()->isItemMovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return FALSE; - } - } - return TRUE; -} - - -BOOL LLFolderViewFolder::isRemovable() -{ - if( !(getViewModelItem()->isItemRemovable()) ) - { - return FALSE; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return FALSE; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return FALSE; - } - } - return TRUE; -} - -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) -{ - if (item->getParentFolder()) - { - item->getParentFolder()->extractItem(item); - } - item->setParentFolder(this); - - mItems.push_back(item); - - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(FALSE); - - addChild(item); - - item->getViewModelItem()->dirtyFilter(); - - // Handle sorting - requestArrange(); - requestSort(); - - getViewModelItem()->addChild(item->getViewModelItem()); - - //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria - //// Traverse parent folders and update creation date and resort, if necessary - //LLFolderViewFolder* parentp = this; - //while (parentp) - //{ - // if (parentp->mSortFunction.isByDate()) - // { - // // parent folder doesn't have a time stamp yet, so get it from us - // parentp->requestSort(); - // } - - // parentp = parentp->getParentFolder(); - //} - - return TRUE; -} - -// this is an internal method used for adding items to folders. -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ - if (folder->mParentFolder) - { - folder->mParentFolder->extractItem(folder); - } - folder->mParentFolder = this; - mFolders.push_back(folder); - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); - addChild( folder ); - folder->getViewModelItem()->dirtyFilter(); - // rearrange all descendants too, as our indentation level might have changed - folder->requestArrange(); - requestSort(); - - getViewModelItem()->addChild(folder->getViewModelItem()); - - return TRUE; -} - -void LLFolderViewFolder::requestArrange() -{ - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } -} - -void LLFolderViewFolder::toggleOpen() -{ - setOpen(!isOpen()); -} - -// Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL openitem) -{ - setOpenArrangeRecursively(openitem); -} - -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - BOOL was_open = isOpen(); - mIsOpen = openitem; - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } - - if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ - } - } - if (mParentFolder - && (recurse == RECURSE_UP - || recurse == RECURSE_UP_DOWN)) - { - mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); - } - - if (was_open != isOpen()) - { - requestArrange(); - } -} - -BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - // drag and drop to child item, so clear pending auto-opens - getRoot()->autoOpenTest(NULL); - - return TRUE; -} - -void LLFolderViewFolder::openItem( void ) -{ - toggleOpen(); -} - -void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - functor.doItem((*fit)); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) -{ - functor.doFolder(this); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -// LLView functionality -BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL handled = FALSE; - - if (isOpen()) - { - handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); - } - - if (!handled) - { - handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; - } - - return TRUE; -} - -BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - getRoot()->autoOpenTest(this); - } - - return TRUE; -} - - -BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - - if( isOpen() ) - { - handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - } - if (!handled) - { - handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); - } - return handled; -} - - -BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - BOOL handled = LLView::handleHover(x, y, mask); - - if (!handled) - { - // this doesn't do child processing - handled = LLFolderViewItem::handleHover(x, y, mask); - } - - return handled; -} - -BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleMouseDown(x,y,mask) != NULL; - } - if( !handled ) - { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) - { - toggleOpen(); - handled = TRUE; - } - else - { - // do normal selection logic - handled = LLFolderViewItem::handleMouseDown(x, y, mask); - } - } - - return handled; -} - -BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - BOOL handled = FALSE; - if( isOpen() ) - { - handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - } - if( !handled ) - { - if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) - { - // don't select when user double-clicks plus sign - // so as not to contradict single-click behavior - toggleOpen(); - } - else - { - getRoot()->setSelection(this, FALSE); - toggleOpen(); - } - handled = TRUE; - } - return handled; -} - -void LLFolderViewFolder::draw() -{ - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); - } - - LLFolderViewItem::draw(); - - // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) - { - LLView::draw(); - } - - mExpanderHighlighted = FALSE; -} - -// this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at beginning - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::iterator fit = mFolders.begin(); - folders_t::iterator fend = mFolders.end(); - - items_t::iterator iit = mItems.begin(); - items_t::iterator iend = mItems.end(); - - // if not trivially starting at the beginning, we have to find the current item - if (!found_item) - { - // first, look among folders, since they are always above items - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // if we are on downwards traversal - if (include_children && (*fit)->isOpen()) - { - // look for first descendant - return (*fit)->getNextFromChild(NULL, TRUE); - } - // otherwise advance to next folder - ++fit; - include_children = TRUE; - break; - } - } - - // didn't find in folders? Check items... - if (!found_item) - { - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found folder, continue through folders - // searching for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - // turn on downwards traversal for next folder - ++fit; - } - - if (fit != fend) - { - result = (*fit); - } - else - { - // otherwise, scan for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - // check to see if we have a valid item - if (iit != iend) - { - result = (*iit); - } - } - - if( !result && mParentFolder ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, FALSE); - } - - return result; -} - -// this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) -{ - BOOL found_item = FALSE; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at end - if(item == NULL) - { - found_item = TRUE; - } - - // find current item among children - folders_t::reverse_iterator fit = mFolders.rbegin(); - folders_t::reverse_iterator fend = mFolders.rend(); - - items_t::reverse_iterator iit = mItems.rbegin(); - items_t::reverse_iterator iend = mItems.rend(); - - // if not trivially starting at the end, we have to find the current item - if (!found_item) - { - // first, look among items, since they are always below the folders - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = TRUE; - // point to next item - ++iit; - break; - } - } - - // didn't find in items? Check folders... - if (!found_item) - { - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = TRUE; - // point to next folder - ++fit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(FALSE); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found item, continue through items - // searching for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - if (iit != iend) - { - // we found an appropriate item - result = (*iit); - } - else - { - // otherwise, scan for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - ++fit; - } - - // check to see if we have a valid folder - if (fit != fend) - { - // try selecting child element of this folder - if ((*fit)->isOpen()) - { - result = (*fit)->getPreviousFromChild(NULL); - } - else - { - result = (*fit); - } - } - } - - if( !result ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // which gets back to this folder, which will only be visited if it is a valid, visible item - result = this; - } - - return result; -} - diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h deleted file mode 100644 index 92923e82da..0000000000 --- a/indra/newview/llfolderviewitem.h +++ /dev/null @@ -1,418 +0,0 @@ -/** -* @file llfolderviewitem.h -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#ifndef LLFOLDERVIEWITEM_H -#define LLFOLDERVIEWITEM_H - -#include "llview.h" -#include "lluiimage.h" - -class LLFolderView; -class LLFolderViewModelItem; -class LLFolderViewFolder; -class LLFolderViewFunctor; -class LLFolderViewFilter; -class LLFolderViewModelInterface; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewItem -// -// An instance of this class represents a single item in a folder view -// such as an inventory item or a file. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewItem : public LLView -{ -public: - static void initClass(); - static void cleanupClass(); - - struct Params : public LLInitParam::Block - { - Optional folder_arrow_image, - selection_image; - Optional root; - Mandatory listener; - - Optional folder_indentation, // pixels - item_height, - item_top_pad; - - Optional creation_date; - - Params(); - }; - - // layout constants - static const S32 LEFT_PAD = 5; - // LEFT_INDENTATION is set via folder_indentation above - static const S32 ICON_PAD = 2; - static const S32 ICON_WIDTH = 16; - static const S32 TEXT_PAD = 1; - static const S32 TEXT_PAD_RIGHT = 4; - static const S32 ARROW_SIZE = 12; - static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; - // animation parameters - static const F32 FOLDER_CLOSE_TIME_CONSTANT; - static const F32 FOLDER_OPEN_TIME_CONSTANT; - -private: - BOOL mIsSelected; - -protected: - friend class LLUICtrlFactory; - friend class LLFolderViewModelItem; - - LLFolderViewItem(const Params& p); - - std::string mLabel; - S32 mLabelWidth; - bool mLabelWidthDirty; - LLFolderViewFolder* mParentFolder; - LLFolderViewModelItem* mViewModelItem; - BOOL mIsCurSelection; - BOOL mSelectPending; - LLFontGL::StyleFlags mLabelStyle; - std::string mLabelSuffix; - LLUIImagePtr mIcon; - LLUIImagePtr mIconOpen; - LLUIImagePtr mIconOverlay; - BOOL mHasVisibleChildren; - S32 mIndentation; - S32 mItemHeight; - - //TODO RN: create interface for string highlighting - //std::string::size_type mStringMatchOffset; - F32 mControlLabelRotation; - LLFolderView* mRoot; - BOOL mDragAndDropTarget; - bool mIsMouseOverTitle; - - // this is an internal method used for adding items to folders. A - // no-op at this level, but reimplemented in derived classes. - virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } - virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } - - static LLFontGL* getLabelFontForStyle(U8 style); - -public: - BOOL postBuild(); - - virtual void openItem( void ); - - void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); - - virtual ~LLFolderViewItem( void ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height ); - virtual S32 getItemHeight(); - - // If 'selection' is 'this' then note that otherwise ignore. - // Returns TRUE if this item ends up being selected. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - - // This method is used to set the selection state of an item. - // If 'selection' is 'this' then note selection. - // Returns TRUE if the selection state of this item was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to deselect this element - void deselectItem(); - - // this method is used to select this element - virtual void selectItem(); - - // gets multiple-element selection - virtual std::set getSelectionList() const; - - // Returns true is this object and all of its children can be removed (deleted by user) - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this item recursively - virtual void destroyView(); - - BOOL isSelected() const { return mIsSelected; } - - void setUnselected() { mIsSelected = FALSE; } - - void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - - BOOL getIsCurSelection() { return mIsCurSelection; } - - BOOL hasVisibleChildren() { return mHasVisibleChildren; } - - // Call through to the viewed object and return true if it can be - // removed. Returns true if it's removed. - //virtual BOOL removeRecursively(BOOL single_item); - BOOL remove(); - - // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(class LLMenuGL& menu, U32 flags); - - // This method returns the actual name of the thing being - // viewed. This method will ask the viewed object itself. - const std::string& getName( void ) const; - - // This method returns the label displayed on the view. This - // method was primarily added to allow sorting on the folder - // contents possible before the entire view has been constructed. - const std::string& getLabel() const { return mLabel; } - - - LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } - const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } - - void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; } - - LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - - const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; } - LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; } - - const LLFolderViewModelInterface* getFolderViewModel( void ) const; - LLFolderViewModelInterface* getFolderViewModel( void ); - - // just rename the object. - void rename(const std::string& new_name); - - - // Show children (unfortunate that this is called "open") - virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } - - virtual LLFolderView* getRoot(); - virtual const LLFolderView* getRoot() const; - BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); - S32 getIndentation() { return mIndentation; } - - virtual BOOL passedFilter(S32 filter_generation = -1); - - // refresh information from the object being viewed. - virtual void refresh(); - - // LLView functionality - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - - virtual void onMouseLeave(S32 x, S32 y, MASK mask); - - virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } - - // virtual void handleDropped(); - virtual void draw(); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - -private: - static std::map sFonts; // map of styles to fonts -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFolder -// -// An instance of an LLFolderViewFolder represents a collection of -// more folders and items. This is used to build the hierarchy of -// items found in the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewFolder : public LLFolderViewItem -{ -protected: - LLFolderViewFolder( const LLFolderViewItem::Params& ); - friend class LLUICtrlFactory; - -public: - - typedef std::list items_t; - typedef std::list folders_t; - -protected: - items_t mItems; - folders_t mFolders; - - BOOL mIsOpen; - BOOL mExpanderHighlighted; - F32 mCurHeight; - F32 mTargetHeight; - F32 mAutoOpenCountdown; - S32 mLastArrangeGeneration; - S32 mLastCalculatedWidth; - S32 mMostFilteredDescendantGeneration; - bool mNeedsSort; - -public: - typedef enum e_recurse_type - { - RECURSE_NO, - RECURSE_UP, - RECURSE_DOWN, - RECURSE_UP_DOWN - } ERecurseType; - - - virtual ~LLFolderViewFolder( void ); - - LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); - - // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder); - - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. - virtual S32 arrange( S32* width, S32* height ); - - BOOL needsArrange(); - - bool descendantsPassedFilter(S32 filter_generation = -1); - - // Passes selection information on to children and record - // selection information if necessary. - // Returns TRUE if this object (or a child) ends up being selected. - // If 'openitem' is TRUE then folders are opened up along the way to the selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE); - - // This method is used to change the selection of an item. - // Recursively traverse all children; if 'selection' is 'this' then change - // the select status if necessary. - // Returns TRUE if the selection state of this folder, or of a child, was changed. - virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - - // this method is used to group select items - void extendSelectionTo(LLFolderViewItem* selection); - - // Returns true is this object and all of its children can be removed. - virtual BOOL isRemovable(); - - // Returns true is this object and all of its children can be moved - virtual BOOL isMovable(); - - // destroys this folder, and all children - virtual void destroyView(); - - // If this folder can be removed, remove all children that can be - // removed, return TRUE if this is empty after the operation and - // it's viewed folder object can be removed. - //virtual BOOL removeRecursively(BOOL single_item); - //virtual BOOL remove(); - - // extractItem() removes the specified item from the folder, but - // doesn't delete it. - virtual void extractItem( LLFolderViewItem* item ); - - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } - - // folders can be opened. This will usually be called by internal - // methods. - virtual void toggleOpen(); - - // Force a folder open or closed - virtual void setOpen(BOOL openitem = TRUE); - - // Called when a child is refreshed. - virtual void requestArrange(); - - virtual void requestSort(); - - // internal method which doesn't update the entire view. This - // method was written because the list iterators destroy the state - // of other iterations, thus, we can't arrange while iterating - // through the children (such as when setting which is selected. - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); - - // Get the current state of the folder. - virtual BOOL isOpen() const { return mIsOpen; } - - // special case if an object is dropped on the child. - BOOL handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - void applyFunctorRecursively(LLFolderViewFunctor& functor); - - // Just apply this functor to the folder's immediate children. - void applyFunctorToChildren(LLFolderViewFunctor& functor); - - virtual void openItem( void ); - virtual BOOL addItem(LLFolderViewItem* item); - virtual BOOL addFolder( LLFolderViewFolder* folder); - - // LLView functionality - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - virtual void draw(); - - folders_t::iterator getFoldersBegin() { return mFolders.begin(); } - folders_t::iterator getFoldersEnd() { return mFolders.end(); } - folders_t::size_type getFoldersCount() const { return mFolders.size(); } - - items_t::const_iterator getItemsBegin() const { return mItems.begin(); } - items_t::const_iterator getItemsEnd() const { return mItems.end(); } - items_t::size_type getItemsCount() const { return mItems.size(); } - - LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); - void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items); - -public: - //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead - template void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); } - template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } -}; - - -#endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfolderviewmodel.cpp b/indra/newview/llfolderviewmodel.cpp deleted file mode 100644 index ca6225aca7..0000000000 --- a/indra/newview/llfolderviewmodel.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file llfolderviewmodel.cpp - * @brief Implementation of the view model collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfolderviewmodel.h" -#include "lltrans.h" - -bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item) -{ - return item->getSortVersion() < mTargetSortVersion; -} - -std::string LLFolderViewModelCommon::getStatusText() -{ - if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter()->getCurrentGeneration()) - { - return LLTrans::getString("Searching"); - } - else - { - return getFilter()->getEmptyLookupMessage(); - } -} - -void LLFolderViewModelCommon::filter() -{ - getFilter()->setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000)); - mFolderView->getViewModelItem()->filter(*getFilter()); -} diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h deleted file mode 100644 index 079409c2a4..0000000000 --- a/indra/newview/llfolderviewmodel.h +++ /dev/null @@ -1,357 +0,0 @@ -/** - * @file llfolderviewmodel.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWMODEL_H -#define LLFOLDERVIEWMODEL_H - -#include "llfontgl.h" // just for StyleFlags enum -#include "llfolderview.h" - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLUIImage; -class LLUUID; -class LLFolderViewItem; -class LLFolderViewFolder; - -class LLFolderViewFilter -{ -public: - enum EFilterModified - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - }; - -public: - - LLFolderViewFilter() {} - virtual ~LLFolderViewFilter() {} - - // +-------------------------------------------------------------------+ - // + Execution And Results - // +-------------------------------------------------------------------+ - virtual bool check(const LLFolderViewModelItem* item) = 0; - virtual bool check(const LLInventoryItem* item) = 0; - virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0; - virtual bool checkFolder(const LLUUID& folder_id) const = 0; - - virtual void setEmptyLookupMessage(const std::string& message) = 0; - virtual std::string getEmptyLookupMessage() const = 0; - - virtual bool showAllResults() const = 0; - - // +-------------------------------------------------------------------+ - // + Status - // +-------------------------------------------------------------------+ - virtual bool isActive() const = 0; - virtual bool isModified() const = 0; - virtual void clearModified() = 0; - virtual const std::string& getName() const = 0; - virtual const std::string& getFilterText() = 0; - //RN: this is public to allow system to externally force a global refilter - virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; - - // +-------------------------------------------------------------------+ - // + Count - // +-------------------------------------------------------------------+ - virtual void setFilterCount(S32 count) = 0; - virtual S32 getFilterCount() const = 0; - virtual void decrementFilterCount() = 0; - - // +-------------------------------------------------------------------+ - // + Default - // +-------------------------------------------------------------------+ - virtual bool isDefault() const = 0; - virtual bool isNotDefault() const = 0; - virtual void markDefault() = 0; - virtual void resetDefault() = 0; - - // +-------------------------------------------------------------------+ - // + Generation - // +-------------------------------------------------------------------+ - virtual S32 getCurrentGeneration() const = 0; - virtual S32 getFirstSuccessGeneration() const = 0; - virtual S32 getFirstRequiredGeneration() const = 0; -}; - -class LLFolderViewModelInterface -{ -public: - virtual void requestSortAll() = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; - - virtual bool contentsReady() = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter* getFilter() = 0; - virtual const LLFolderViewFilter* getFilter() const = 0; - virtual std::string getStatusText() = 0; -}; - -class LLFolderViewModelCommon : public LLFolderViewModelInterface -{ -public: - LLFolderViewModelCommon() - : mTargetSortVersion(0), - mFolderView(NULL) - {} - - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - virtual std::string getStatusText(); - virtual void filter(); - - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} - -protected: - bool needsSort(class LLFolderViewModelItem* item); - - S32 mTargetSortVersion; - LLFolderView* mFolderView; - -}; - -template -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - - virtual FilterType* getFilter() { return &mFilter; } - virtual const FilterType* getFilter() const { return &mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - - struct ViewModelCompare - { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - const SortType& mSorter; - }; - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } - -protected: - SortType mSorter; - FilterType mFilter; -}; - -// This is am abstract base class that users of the folderview classes -// would use to bridge the folder view with the underlying data -class LLFolderViewModelItem -{ -public: - virtual ~LLFolderViewModelItem( void ) {}; - - virtual void update() {} //called when drawing - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const std::string& getSearchableName() const = 0; - - virtual LLPointer getIcon() const = 0; - virtual LLPointer getIconOpen() const { return getIcon(); } - virtual LLPointer getIconOverlay() const { return NULL; } - - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - - virtual void openItem( void ) = 0; - virtual void closeItem( void ) = 0; - virtual void selectItem(void) = 0; - - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - - virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder - virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL removeItem() = 0; - virtual void removeBatch(std::vector& batch) = 0; - - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; - - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - - virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - - virtual bool filter( LLFolderViewFilter& filter) = 0; - virtual bool passedFilter(S32 filter_generation = -1) = 0; - virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; - virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; - virtual void dirtyFilter() = 0; - - virtual S32 getLastFilterGeneration() const = 0; - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual LLToolDragAndDrop::ESource getDragSource() const = 0; - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - virtual bool hasChildren() const = 0; - virtual void addChild(LLFolderViewModelItem* child) = 0; - virtual void removeChild(LLFolderViewModelItem* child) = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; - - virtual void requestSort() = 0; - virtual S32 getSortVersion() = 0; - virtual void setSortVersion(S32 version) = 0; - virtual void setParent(LLFolderViewModelItem* parent) = 0; - -protected: - - friend class LLFolderViewItem; - virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0; - -}; - -class LLFolderViewModelItemCommon : public LLFolderViewModelItem -{ -public: - LLFolderViewModelItemCommon() - : mSortVersion(-1), - mPassedFilter(true), - mPassedFolderFilter(true), - mFolderViewItem(NULL), - mLastFilterGeneration(-1), - mMostFilteredDescendantGeneration(-1), - mParent(NULL) - { - std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); - } - - void requestSort() { mSortVersion = -1; } - S32 getSortVersion() { return mSortVersion; } - void setSortVersion(S32 version) { mSortVersion = version;} - - S32 getLastFilterGeneration() const { return mLastFilterGeneration; } - void dirtyFilter() - { - mLastFilterGeneration = -1; - - // bubble up dirty flag all the way to root - if (mParent) - { - mParent->dirtyFilter(); - } - } - virtual void addChild(LLFolderViewModelItem* child) - { - mChildren.push_back(child); - child->setParent(this); - } - virtual void removeChild(LLFolderViewModelItem* child) - { - mChildren.remove(child); - child->setParent(NULL); - } - -protected: - virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - - S32 mSortVersion; - bool mPassedFilter; - bool mPassedFolderFilter; - - S32 mLastFilterGeneration; - S32 mMostFilteredDescendantGeneration; - - - typedef std::list child_list_t; - child_list_t mChildren; - LLFolderViewModelItem* mParent; - - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} - LLFolderViewItem* mFolderViewItem; -}; - - -#endif // LLFOLDERVIEWMODEL_H diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 99831c61bf..d23b4af8cb 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -28,12 +28,38 @@ #include "llfolderviewmodelinventory.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" +#include "lltooldraganddrop.h" // // class LLFolderViewModelInventory // static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); +bool LLFolderViewModelInventory::startDrag(std::vector& items) +{ + std::vector types; + uuid_vec_t cargo_ids; + std::vector::iterator item_it; + bool can_drag = true; + if (!items.empty()) + { + for (item_it = items.begin(); item_it != items.end(); ++item_it) + { + EDragAndDropType type = DAD_NONE; + LLUUID id = LLUUID::null; + can_drag = can_drag && static_cast(*item_it)->startDrag(&type, &id); + + types.push_back(type); + cargo_ids.push_back(id); + } + + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, + static_cast(items.front())->getDragSource(), mTaskID); + } + return can_drag; +} + + void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) { LLFastTimer _(FTM_INVENTORY_SORT); diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index a8fe3f57ea..12a977b28b 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -29,6 +29,9 @@ #define LL_LLFOLDERVIEWMODELINVENTORY_H #include "llinventoryfilter.h" +#include "llinventory.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon @@ -62,6 +65,10 @@ public: virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); virtual bool filter( LLFolderViewFilter& filter); virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; + virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + protected: class LLFolderViewModelInventory* mRootViewModel; }; @@ -97,11 +104,13 @@ class LLFolderViewModelInventory public: typedef LLFolderViewModel base_t; - virtual ~LLFolderViewModelInventory() {} + void setTaskID(const LLUUID& id) {mTaskID = id;} void sort(LLFolderViewFolder* folder); - bool contentsReady(); + bool startDrag(std::vector& items); +private: + LLUUID mTaskID; }; #endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 9615f3f44d..f68cf07d8c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -65,8 +65,6 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual PermissionMask getPermissionMask() const { return PERM_ALL; } - virtual LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } virtual LLPointer getIcon() const { return NULL; } virtual LLPointer getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } @@ -88,8 +86,6 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } virtual bool hasChildren() const { return FALSE; } - virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } - virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } virtual bool potentiallyVisible() { return true; } virtual bool filter( LLFolderViewFilter& filter) { return true; } @@ -107,11 +103,6 @@ public: void setVisibleIfDetached(BOOL visible); - // This method should be called when a drag begins. - // Returns TRUE if the drag can begin, FALSE otherwise. - virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_PEOPLE; } - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const { return FALSE; } - // This method will be called to determine if a drop can be // performed, and will set drop to TRUE if a drop is // requested. diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index e235d9cf5f..b4a91ca0f7 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -35,6 +35,7 @@ #include "llinventorypanel.h" #include "llviewercontrol.h" #include "llwearable.h" +#include "lltooldraganddrop.h" class LLInventoryFilter; class LLInventoryPanel; @@ -119,7 +120,7 @@ public: void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items, menuentry_vec_t &disabled_items, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual LLToolDragAndDrop::ESource getDragSource() const; + virtual LLToolDragAndDrop::ESource getDragSource() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index fed9893158..0aa67cddca 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -571,7 +571,24 @@ void LLInventoryPanel::onIdle(void *userdata) void LLInventoryPanel::idle(void* user_data) { LLInventoryPanel* panel = (LLInventoryPanel*)user_data; - panel->mFolderRoot->doIdle(); + panel->mFolderRoot->update(); + // while dragging, update selection rendering to reflect single/multi drag status + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + { + EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); + if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) + { + panel->mFolderRoot->setShowSingleSelection(TRUE); + } + else + { + panel->mFolderRoot->setShowSingleSelection(FALSE); + } + } + else + { + panel->mFolderRoot->setShowSingleSelection(FALSE); + } } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 002c0c1113..ca20051a51 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1557,7 +1557,6 @@ void LLPanelObjectInventory::reset() LLFolderView::Params p; p.name = "task inventory"; p.title = "task inventory"; - p.task_id = getTaskUUID(); p.parent_panel = this; p.tool_tip= LLTrans::getString("PanelContentsTooltip"); p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); @@ -1823,6 +1822,7 @@ void LLPanelObjectInventory::refresh() removeVOInventoryListener(); clearContents(); } + mInventoryViewModel.setTaskID(mTaskUUID); //llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 4a9e106687..cb59f704a5 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -58,6 +58,7 @@ #include "lltoolmgr.h" #include "lltoolpipette.h" #include "llfiltereditor.h" +#include "llwindow.h" #include "lltool.h" #include "llviewerwindow.h" -- cgit v1.2.3 From d3edb1c466f42e2c46c77e43b26d700c6298b8d6 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 4 Jul 2012 00:30:00 -0700 Subject: CHUI-101 WIP Make LLFolderview general purpose partial fix for crash on startup --- indra/llui/llfolderview.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llimfloatercontainer.cpp | 17 ++++++++++++++--- indra/newview/llimfloatercontainer.h | 1 + 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 0d3bc44ae4..990b79a30b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1798,8 +1798,8 @@ void LLFolderView::update() BOOL filter_finished = getViewModelItem()->passedFilter() && mViewModel->contentsReady(); if (filter_finished - || gFocusMgr.childHasKeyboardFocus(getParent()) // assume we are inside a scroll container - || gFocusMgr.childHasMouseCapture(getParent())) + || gFocusMgr.childHasKeyboardFocus(mParentPanel) + || gFocusMgr.childHasMouseCapture(mParentPanel)) { // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process mNeedsAutoSelect = FALSE; diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 9cb885066a..50d3e0580e 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -53,7 +53,7 @@ public: { Optional folder_arrow_image, selection_image; - Optional root; + Mandatory root; Mandatory listener; Optional folder_indentation, // pixels diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 261b5f33a2..2b943df48f 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -47,8 +47,9 @@ // LLIMFloaterContainer // LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -: LLMultiFloater(seed) - ,mExpandCollapseBtn(NULL) +: LLMultiFloater(seed), + mExpandCollapseBtn(NULL), + mFolders(NULL) { // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -90,6 +91,16 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild("conversations_list_panel"); + LLFolderView::Params p; + //TODO RN: define view model for conversations + //p.view_model = ?; + p.parent_panel = mConversationsListPanel; + p.rect = mConversationsListPanel->getLocalRect(); + p.follows.flags = FOLLOWS_ALL; + + mFolders = LLUICtrlFactory::create(p); + mConversationsListPanel->addChild(mFolders); + mExpandCollapseBtn = getChild("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -512,7 +523,7 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); //params.creation_date = bridge->getCreationDate(); - //params.root = mFolderRoot; + params.root = mFolders; params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index f68cf07d8c..890a115a04 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -194,6 +194,7 @@ private: LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) conversations_items_map mConversationsItems; conversations_widgets_map mConversationsWidgets; + LLFolderView* mFolders; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From 22f8301b1dea787e0adda80b2625a8d7d9ddbda4 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 4 Jul 2012 17:18:48 +0300 Subject: CHUI-172 CHUI-183 FIX Disabled applying stored rect dimensions when Nearby chat is hosted in Conversations floater. --- indra/newview/llimconversation.cpp | 4 ---- indra/newview/llnearbychat.cpp | 32 +++++++++++++++++++------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index acdd7ba46a..c855a844cf 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -254,9 +254,7 @@ void LLIMConversation::updateHeaderAndToolbar() if (mDragHandle) { mDragHandle->setTitleVisible(!is_hosted); - setCanDrag(!is_hosted); } - setCanResize(!is_hosted); // The button (>>) should be disabled for torn off P2P conversations. mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); @@ -349,8 +347,6 @@ void LLIMConversation::onOpen(const LLSD& key) host_floater->collapseMessagesPane(false); } - setCanResize(TRUE); - updateHeaderAndToolbar(); } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a81d6b4025..13e9eeee66 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -364,20 +364,18 @@ void LLNearbyChat::onOpen(const LLSD& key) bool LLNearbyChat::applyRectControl() { - bool rect_controlled = LLFloater::applyRectControl(); + bool is_torn_off = getHost() == NULL; -/* if (!mNearbyChat->getVisible()) + // Resize is limited to torn off floaters. + // A hosted floater is not resizable. + if (is_torn_off) { - reshape(getRect().getWidth(), getMinHeight()); - enableResizeCtrls(true, true, false); - } - else - {*/ enableResizeCtrls(true); - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -// } + } - return rect_controlled; + setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); + + return LLFloater::applyRectControl(); } void LLNearbyChat::onChatFontChange(LLFontGL* fontp) @@ -408,9 +406,17 @@ void LLNearbyChat::showHistory() { openFloater(); setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - reshape(getRect().getWidth(), mExpandedHeight); - enableResizeCtrls(true); - storeRectControl(); + + bool is_torn_off = getHost() == NULL; + + // Reshape and enable resize controls only if it's a torn off floater. + // Otherwise all the size changes should be handled by LLIMFloaterContainer. + if (is_torn_off) + { + reshape(getRect().getWidth(), mExpandedHeight); + enableResizeCtrls(true); + storeRectControl(); + } } std::string LLNearbyChat::getCurrentChat() -- cgit v1.2.3 From e0eeed2680a2c6ba1055ac2a9f6465cb8004b7d6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Wed, 4 Jul 2012 20:53:47 +0300 Subject: CHUI-189 FIXED (Blocked objects by name are not sorted correctly) - Fixed sort criteria. It's needed to take into account that objects in mute list are represented by two types: LLMute::BY_NAME and LLMute::OBJECT --- indra/newview/llblocklist.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index cb68f677eb..0165a9c4e8 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -267,9 +267,15 @@ bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_i LLMute::EType type1 = blocked_item1->getType(); LLMute::EType type2 = blocked_item2->getType(); - if (type1 != type2) + // if mute type is LLMute::BY_NAME or LLMute::OBJECT it means that this mute is an object + bool both_mutes_are_objects = (LLMute::OBJECT == type1 || LLMute::BY_NAME == type1) && (LLMute::OBJECT == type2 || LLMute::BY_NAME == type2); + + // mute types may be different, but since both LLMute::BY_NAME and LLMute::OBJECT types represent objects + // it's needed to perform additional checking of both_mutes_are_objects variable + if (type1 != type2 && !both_mutes_are_objects) { - return type1 > type2; + // objects in block list go first, so return true if mute type is not an avatar + return LLMute::AGENT != type1; } return NAME_COMPARATOR.compare(blocked_item1, blocked_item2); -- cgit v1.2.3 From 1fa326ccdbb9b99fedac0b4cdab232ec1fbe8d74 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Wed, 4 Jul 2012 21:13:25 +0300 Subject: CHUI-136 ADDITIONAL FIX (Implement new design for blocked list on the people floater) - Disabled object profile functionality according to the spec --- indra/newview/llblocklist.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp index 0165a9c4e8..066cb71677 100644 --- a/indra/newview/llblocklist.cpp +++ b/indra/newview/llblocklist.cpp @@ -195,7 +195,13 @@ bool LLBlockList::isActionEnabled(const LLSD& userdata) const std::string command_name = userdata.asString(); - if ("unblock_item" == command_name || "profile_item" == command_name) + if ("profile_item" == command_name) + { + LLBlockedListItem* item = getBlockedItem(); + action_enabled = item && (LLMute::AGENT == item->getType()); + } + + if ("unblock_item" == command_name) { action_enabled = getSelectedItem() != NULL; } @@ -227,10 +233,6 @@ void LLBlockList::onCustomAction(const LLSD& userdata) LLAvatarActions::showProfile(item->getUUID()); break; - case LLMute::OBJECT: - LLFloaterSidePanelContainer::showPanel("inventory", LLSD().with("id", item->getUUID())); - break; - default: break; } -- cgit v1.2.3 From ff448aed525b8c1d2f05b6a5816ba6855707e4b8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 5 Jul 2012 19:23:34 +0300 Subject: CHUI-200 FIXED Show correct and localized name of the nearby chat In the conversations list --- indra/newview/llimfloatercontainer.cpp | 4 ---- indra/newview/llnearbychat.cpp | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 08ace601a3..134623722c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -534,10 +534,6 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mFloater(floaterp), mContainer(containerp) { - // Hack: the nearby chat has no name so we catch that case and impose one - // Of course, we won't be doing this in the final code - if (name == "") - mName = "Nearby Chat"; } // Virtual action callbacks diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 13e9eeee66..644304aff3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -158,6 +158,10 @@ BOOL LLNearbyChat::postBuild() enableResizeCtrls(true, true, false); + // title must be defined BEFORE call addToHost() because + // it is used for show the item's name in the conversations list + setTitle(getString("NearbyChatTitle")); + addToHost(); //for menu @@ -182,7 +186,6 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } - setTitle(getString("NearbyChatTitle")); return LLIMConversation::postBuild(); } -- cgit v1.2.3 From 89d8a49f28dac5d99ec05a5201203ec57f72be02 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 5 Jul 2012 14:14:35 +0300 Subject: CHUI-197 FIXED Conversation names updating when checked corresponding preference --- indra/newview/llimfloatercontainer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 134623722c..30a77bef98 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -104,6 +104,8 @@ BOOL LLIMFloaterContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); + LLAvatarNameCache::addUseDisplayNamesCallback( + boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); return TRUE; } -- cgit v1.2.3 From c76c73770bf1a4095100cdb79021826ebebbd2f0 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 4 Jul 2012 17:57:46 +0300 Subject: CHUI-195 FIXED Starting ad-hoc conference call does not open Conversations floater --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 79018ec366..cdbb7c7cca 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2583,7 +2583,6 @@ LLUUID LLIMMgr::addSession( LLDynamicArray ids; ids.put(other_participant_id); LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice); - notifyObserverSessionVoiceOrIMStarted(session_id); return session_id; } @@ -2653,6 +2652,8 @@ LLUUID LLIMMgr::addSession( noteMutedUsers(session_id, ids); } + notifyObserverSessionVoiceOrIMStarted(session_id); + return session_id; } -- cgit v1.2.3 From 73ad740443e615467f7e14fe4fb3f04d8abe2f9c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 4 Jul 2012 16:45:02 +0300 Subject: CHUI-170 FIXED Save Torn off state of Nearby Chat between sessions --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llimconversation.cpp | 8 +------- indra/newview/llimconversation.h | 2 +- indra/newview/llimfloatercontainer.cpp | 5 ++--- indra/newview/llnearbychat.cpp | 27 ++++++++++++++++++++++++--- indra/newview/llnearbychat.h | 2 ++ 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4a586b02af..da3ff2d1ee 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1639,6 +1639,17 @@ Value + NearbyChatIsNotTornOff + + Comment + saving torn-off state of the nearby chat between sessions + Persist + 1 + Type + Boolean + Value + 1 + CloseChatOnReturn Comment diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index c855a844cf..3c6c5c3898 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -55,12 +55,6 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) { mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); -// mCommitCallbackRegistrar.add("IMSession.ExpCollapseBtn.Click", -// boost::bind(&LLIMConversation::onSlide, this)); -// mCommitCallbackRegistrar.add("IMSession.CloseBtn.Click", -// boost::bind(&LLFloater::onClickClose, this)); - mCommitCallbackRegistrar.add("IMSession.TearOffBtn.Click", - boost::bind(&LLIMConversation::onTearOffClicked, this)); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", @@ -366,7 +360,7 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - onClickTearOff(this); + LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); } diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 50663137ac..682779a44b 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -78,7 +78,7 @@ protected: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); static void onSlide(LLIMConversation *self); - void onTearOffClicked(); + virtual void onTearOffClicked(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 30a77bef98..546eccbd04 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -302,9 +302,8 @@ void LLIMFloaterContainer::setVisible(BOOL visible) if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container - LLUUID nearbychat_uuid = LLUUID::null; // Hacky but true: the session id for nearby chat is always null - LLFloater* floaterp = findConversationItem(nearbychat_uuid); - if (floaterp == NULL) + LLFloater* nearby_chat = LLFloaterReg::findInstance("chat_bar"); + if (nearby_chat == NULL) { // If not found, force the creation of the nearby chat conversation panel // *TODO: find a way to move this to XML as a default panel or something like that diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 644304aff3..384762549a 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -345,15 +345,36 @@ void LLNearbyChat::enableDisableCallBtn() getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); } +void LLNearbyChat::onTearOffClicked() +{ + LLIMConversation::onTearOffClicked(); + + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + + // see CHUI-170: Save torn-off state of the nearby chat between sessions + BOOL in_the_multifloater = (getHost() == im_box); + gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); +} + void LLNearbyChat::addToHost() { - if (LLIMConversation::isChatMultiTab()) + if ( LLIMConversation::isChatMultiTab()) { LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); - if (im_box) { - im_box->addFloater(this, FALSE, LLTabContainer::END); + if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) + { + im_box->addFloater(this, TRUE, LLTabContainer::END); + } + else + { + // setting of the "potential" host: this sequence sets + // LLFloater::mHostHandle = NULL (a current host), but + // LLFloater::mLastHostHandle = im_box (a "future" host) + setHost(im_box); + setHost(NULL); + } } } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 61404df942..90feb71488 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -101,6 +101,8 @@ protected: void onToggleNearbyChatPanel(); + /*virtual*/ void onTearOffClicked(); + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); EChatType processChatTypeTriggers(EChatType type, std::string &str); -- cgit v1.2.3 From ec15ff6350c0997421cf2884e40aa9feaa070d4d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 5 Jul 2012 16:42:20 -0700 Subject: CHUI-98 : WIP, use the refactored folder view for conversation view list --- indra/llui/llfolderview.cpp | 36 ++++++++++----- indra/newview/llimfloatercontainer.cpp | 23 +++++++++- indra/newview/llimfloatercontainer.h | 83 ++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 14 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 990b79a30b..92e3b7a8e9 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -320,10 +320,10 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) LLFolderViewFolder::arrange(&mMinWidth, &target_height); - LLRect scroll_rect = mScrollContainer->getContentWindowRect(); + LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); - LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); + LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { reshape( llmax(scroll_rect.getWidth(), mMinWidth), llround(mCurHeight) ); @@ -945,7 +945,7 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); item->setOpen(TRUE); - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); scrollToShowItem(item, constraint_rect); } @@ -1225,25 +1225,37 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) case KEY_PAGE_UP: mSearchString.clear(); - mScrollContainer->pageUp(30); + if (mScrollContainer) + { + mScrollContainer->pageUp(30); + } handled = TRUE; break; case KEY_PAGE_DOWN: mSearchString.clear(); - mScrollContainer->pageDown(30); + if (mScrollContainer) + { + mScrollContainer->pageDown(30); + } handled = TRUE; break; case KEY_HOME: mSearchString.clear(); - mScrollContainer->goToTop(); + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } handled = TRUE; break; case KEY_END: mSearchString.clear(); - mScrollContainer->goToBottom(); + if (mScrollContainer) + { + mScrollContainer->goToBottom(); + } break; case KEY_DOWN: @@ -1719,8 +1731,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr LLRect LLFolderView::getVisibleRect() { - S32 visible_height = mScrollContainer->getRect().getHeight(); - S32 visible_width = mScrollContainer->getRect().getWidth(); + S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); + S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); LLRect visible_rect; visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); return visible_rect; @@ -1816,7 +1828,7 @@ void LLFolderView::update() // lets pin it! mPinningSelectedItem = TRUE; - LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); + LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); LLFolderViewItem* selected_item = mSelectedItems.back(); LLRect item_rect; @@ -1831,7 +1843,7 @@ void LLFolderView::update() else { // otherwise we just want it onscreen somewhere - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } } @@ -1854,7 +1866,7 @@ void LLFolderView::update() else { // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = mScrollContainer->getContentWindowRect(); + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 2b943df48f..be38eddbaf 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -91,12 +91,14 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild("conversations_list_panel"); + mRoot = new LLConversationItem(); LLFolderView::Params p; - //TODO RN: define view model for conversations - //p.view_model = ?; + // CHUI-98 : View Model for conversations + p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; p.rect = mConversationsListPanel->getLocalRect(); p.follows.flags = FOLLOWS_ALL; + p.listener = mRoot; mFolders = LLUICtrlFactory::create(p); mConversationsListPanel->addChild(mFolders); @@ -544,6 +546,15 @@ LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLF mName = "Nearby Chat"; } +LLConversationItem::LLConversationItem() : + mName(""), + mUUID(), + mFloater(NULL), + mContainer(NULL) +{ +} + + // Virtual action callbacks void LLConversationItem::selectItem(void) { @@ -589,4 +600,12 @@ void LLConversationItem::showProperties(void) { } +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ + // We compare only by name for the moment + // *TODO : Implement the sorting by date + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + return (compare < 0); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 890a115a04..f146e65897 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -57,6 +57,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon { public: LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); + LLConversationItem(); virtual ~LLConversationItem() {} // Stub those things we won't really be using in this conversation context @@ -120,6 +121,86 @@ private: LLFloater* mFloater; LLIMFloaterContainer* mContainer; }; + +// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. +// We just stubb everything for the moment. +class LLConversationFilter : public LLFolderViewFilter +{ +public: + + enum ESortOrderType + { + SO_NAME = 0, // Sort inventory by name + SO_DATE = 0x1, // Sort inventory by date + }; + + LLConversationFilter() { mEmpty = ""; } + ~LLConversationFilter() {} + + bool check(const LLFolderViewModelItem* item) { return true; } + bool checkFolder(const LLFolderViewModelItem* folder) const { return true; } + void setEmptyLookupMessage(const std::string& message) { } + std::string getEmptyLookupMessage() const { return mEmpty; } + bool showAllResults() const { return true; } + + bool isActive() const { return false; } + bool isModified() const { return false; } + void clearModified() { } + const std::string& getName() const { return mEmpty; } + const std::string& getFilterText() { return mEmpty; } + void setModified(EFilterModified behavior = FILTER_RESTART) { } + + void setFilterCount(S32 count) { } + S32 getFilterCount() const { return 0; } + void decrementFilterCount() { } + + bool isDefault() const { return true; } + bool isNotDefault() const { return false; } + void markDefault() { } + void resetDefault() { } + + S32 getCurrentGeneration() const { return 0; } + S32 getFirstSuccessGeneration() const { return 0; } + S32 getFirstRequiredGeneration() const { return 0; } +private: + std::string mEmpty; +}; + +class LLConversationSort +{ +public: + LLConversationSort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mByName(false) + { + mByDate = (order & LLConversationFilter::SO_DATE); + mByName = (order & LLConversationFilter::SO_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mByName; +}; + +class LLConversationViewModel +: public LLFolderViewModel +{ +public: + typedef LLFolderViewModel base_t; + + void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort + bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat + bool startDrag(std::vector& items) { return false; } // We do not allow drag of conversation items + +private: +}; + // CHUI-137 : End class LLIMFloaterContainer @@ -189,6 +270,8 @@ public: void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); LLFloater* findConversationItem(LLUUID& uuid); private: + LLConversationViewModel mConversationViewModel; + LLConversationItem* mRoot; LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) -- cgit v1.2.3 From aee13892c870473a3d38d2b7524871e0024a92f2 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 6 Jul 2012 01:12:54 +0000 Subject: Adding debian package build to teamcity build script. --- build.sh | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index a95ca91d82..ac7fdc4f75 100755 --- a/build.sh +++ b/build.sh @@ -271,12 +271,89 @@ then end_section WaitParallel fi +# build debian package +if [ "$arch" == "Linux" ] +then + if $succeeded + then + if $build_viewer_deb && [ "$last_built_variant" == "Release" ] + then + begin_section "Build Debian Package" + # mangle the changelog + dch --force-bad-version \ + --distribution unstable \ + --newversion "${VIEWER_VERSION}" \ + "Automated build #$build_id, repository $branch revision $revision." \ + >> "$build_log" 2>&1 + + # build the debian package + $pkg_default_debuild_command >>"$build_log" 2>&1 || record_failure "\"$pkg_default_debuild_command\" failed." + + # Unmangle the changelog file + hg revert debian/changelog + + end_section "Build Debian Package" + + # upload debian package and create repository + begin_section "Upload Debian Repository" + for deb_file in ./*.deb; do + upload_item debian $deb_file binary/octet-stream + done + if [ -d "$build_log_dir/debian_repo" ] + then + pushd "$build_log_dir/debian_repo" + cat > Release < Packages.gz \ + && dpkg-scansources . /dev/null | gzip -9c > Sources.gz + then + begin_section Packages.gz + gunzip --stdout Packages.gz + for file in *.deb + do + stat "$file" | sed 2q + md5sum "$file" + done + end_section Packages.gz + + for file in * + do + upload_item debian_repo "$file" binary/octet-stream + done + else + record_failure 'Unable to generate Packages.gz or Sources.gz' + fi + popd + + process_pending_uploads + + # Rename the local debian_repo directory so that the master buildscript + # doesn't make a remote repo again. + + mv $build_log_dir/debian_repo $build_log_dir/debian_repo_pushed + fi + end_section "Upload Debian Repository" + + else + echo skipping debian build + fi + else + echo skipping debian build due to failed build. + fi +fi + + # check status and upload results to S3 if $succeeded then if $build_viewer then - begin_section Upload + begin_section Upload Installer # Upload installer - note that ONLY THE FIRST ITEM uploaded as "installer" # will appear in the version manager. package=$(installer_$arch) @@ -302,12 +379,12 @@ then # Upload stub installers upload_stub_installers "$build_dir_stubs" fi - end_section Upload + end_section Upload Installer else - echo skipping viewer + echo skipping upload of installer fi else - echo skipping upload of build results due to failed build. + echo skipping upload of installer due to failed build. fi # The branch independent build.sh script invoking this script will finish processing -- cgit v1.2.3 From a6ecafceff18497deba2e0d308f97b044027f7f0 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 6 Jul 2012 01:53:34 +0000 Subject: Change install directory to include viewer version --- build.sh | 2 +- debian/rules | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index ac7fdc4f75..47b3ff545e 100755 --- a/build.sh +++ b/build.sh @@ -296,7 +296,7 @@ then # upload debian package and create repository begin_section "Upload Debian Repository" - for deb_file in ./*.deb; do + for deb_file in ../*.deb; do upload_item debian $deb_file binary/octet-stream done if [ -d "$build_log_dir/debian_repo" ] diff --git a/debian/rules b/debian/rules index eedeeef879..e4106ff75c 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,9 @@ SRCDIR=build-linux-i686/newview/packaged DESTDIR=$(CURDIR)/debian/secondlife-viewer -INSTALLDIR=opt/linden/viewer +BASEDIR=opt/linden/viewer +VIEWER_VERSION:=$(shell dpkg-parsechangelog | grep ^Version | sed 's/^Version: //') +INSTALLDIR:=$(BASEDIR)/SecondLife-i686-$(VIEWER_VERSION) configure: configure-stamp configure-stamp: @@ -59,6 +61,7 @@ install: build install -v -m $$PERM -o root -g root "$(SRCDIR)/$$file" "$(DESTDIR)/$(INSTALLDIR)/$$file"; \ done dh_link /$(INSTALLDIR)/secondlife /usr/bin/secondlife + dh_link $(BASEDIR)/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/SecondLife # Build architecture-independent files here. -- cgit v1.2.3 From c3e048a2f14b08ec4428ea9f5a10f17de154e1fc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 6 Jul 2012 13:30:05 +0300 Subject: build fix --- indra/newview/llimfloatercontainer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 546eccbd04..f3b97776fc 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -37,6 +37,7 @@ #include "llagent.h" #include "llavataractions.h" #include "llavatariconctrl.h" +#include "llavatarnamecache.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" #include "llimview.h" -- cgit v1.2.3 From 9ab042dd1d003da15dd579f366db04d4aae3ff6b Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 6 Jul 2012 17:49:02 +0300 Subject: CHUI-196 FIXED (Chat text entry area gets resized unexpectedly with certain user display names) - Fixed label length calculating --- indra/llui/lltextbase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3b3bc64c5b..a7bc6bbb77 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -510,7 +510,7 @@ void LLTextBase::drawText() } else if (text_len <= 0 && !mLabel.empty() && !hasFocus()) { - text_len = mLabel.length(); + text_len = mLabel.getWString().length(); } S32 selection_left = -1; @@ -1816,7 +1816,7 @@ void LLTextBase::resetLabel() style->setColor(mTentativeFgColor); LLStyleConstSP sp(style); - LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, getLabel().length() + 1, *this); + LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, mLabel.getWString().length() + 1, *this); insertSegment(label); } } @@ -2988,7 +2988,7 @@ const LLWString& LLLabelTextSegment::getWText() const /*virtual*/ const S32 LLLabelTextSegment::getLength() const { - return mEditor.getLabel().length(); + return mEditor.getWlabel().length(); } // -- cgit v1.2.3 From 0b8a57cab8628ba064a14250a140ca9615669d2c Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Sat, 7 Jul 2012 00:50:31 +0300 Subject: Linux build fix. LLFolderViewModelItem placed before the call to a method of this class in LLFolderViewModel::sort(). --- indra/llui/llfolderviewmodel.h | 207 ++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 104 deletions(-) diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 0f5f9a1f50..268ae8eea8 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -107,110 +107,6 @@ public: virtual S32 getFirstRequiredGeneration() const = 0; }; -class LLFolderViewModelInterface -{ -public: - virtual ~LLFolderViewModelInterface() {} - virtual void requestSortAll() = 0; - - virtual void sort(class LLFolderViewFolder*) = 0; - virtual void filter() = 0; - - virtual bool contentsReady() = 0; - virtual void setFolderView(LLFolderView* folder_view) = 0; - virtual LLFolderViewFilter* getFilter() = 0; - virtual const LLFolderViewFilter* getFilter() const = 0; - virtual std::string getStatusText() = 0; - - virtual bool startDrag(std::vector& items) = 0; -}; - -class LLFolderViewModelCommon : public LLFolderViewModelInterface -{ -public: - LLFolderViewModelCommon() - : mTargetSortVersion(0), - mFolderView(NULL) - {} - - virtual void requestSortAll() - { - // sort everything - mTargetSortVersion++; - } - virtual std::string getStatusText(); - virtual void filter(); - - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} - -protected: - bool needsSort(class LLFolderViewModelItem* item); - - S32 mTargetSortVersion; - LLFolderView* mFolderView; - -}; - -template -class LLFolderViewModel : public LLFolderViewModelCommon -{ -public: - LLFolderViewModel(){} - virtual ~LLFolderViewModel() {} - - typedef SORT_TYPE SortType; - typedef ITEM_TYPE ItemType; - typedef FOLDER_TYPE FolderType; - typedef FILTER_TYPE FilterType; - - virtual SortType& getSorter() { return mSorter; } - virtual const SortType& getSorter() const { return mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } - - virtual FilterType* getFilter() { return &mFilter; } - virtual const FilterType* getFilter() const { return &mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = filter; } - - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() - virtual bool contentsReady() { return true; } - - - struct ViewModelCompare - { - ViewModelCompare(const SortType& sorter) - : mSorter(sorter) - {} - - bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const - { - return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); - } - - const SortType& mSorter; - }; - - void sort(LLFolderViewFolder* folder) - { - if (needsSort(folder->getViewModelItem())) - { - folder->sortFolders(ViewModelCompare(getSorter())); - folder->sortItems(ViewModelCompare(getSorter())); - folder->getViewModelItem()->setSortVersion(mTargetSortVersion); - folder->requestArrange(); - } - } - -protected: - SortType mSorter; - FilterType mFilter; -}; - // This is am abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem @@ -349,5 +245,108 @@ protected: LLFolderViewItem* mFolderViewItem; }; +class LLFolderViewModelInterface +{ +public: + virtual ~LLFolderViewModelInterface() {} + virtual void requestSortAll() = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter() = 0; + + virtual bool contentsReady() = 0; + virtual void setFolderView(LLFolderView* folder_view) = 0; + virtual LLFolderViewFilter* getFilter() = 0; + virtual const LLFolderViewFilter* getFilter() const = 0; + virtual std::string getStatusText() = 0; + + virtual bool startDrag(std::vector& items) = 0; +}; + +class LLFolderViewModelCommon : public LLFolderViewModelInterface +{ +public: + LLFolderViewModelCommon() + : mTargetSortVersion(0), + mFolderView(NULL) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + virtual std::string getStatusText(); + virtual void filter(); + + void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; + LLFolderView* mFolderView; + +}; + +template +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel(){} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + + virtual FilterType* getFilter() { return &mFilter; } + virtual const FilterType* getFilter() const { return &mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + // TODO RN: remove this and put all filtering logic in view model + // add getStatusText and isFiltering() + virtual bool contentsReady() { return true; } + + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const + { + return mSorter(static_cast(a->getViewModelItem()), static_cast(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + +protected: + SortType mSorter; + FilterType mFilter; +}; #endif // LLFOLDERVIEWMODEL_H -- cgit v1.2.3 From c9e11635488720626601b7b4a7926f09031a6908 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Sat, 7 Jul 2012 01:10:30 +0300 Subject: Another Linux build fix. --- indra/llui/llfolderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 92e3b7a8e9..8ade17b763 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1927,7 +1927,7 @@ void LLFolderView::updateRenamerPosition() screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - LLRect scroller_rect(0, 0, LLUI::getWindowSize().mV[VX], 0); + LLRect scroller_rect(0, 0, (S32)LLUI::getWindowSize().mV[VX], 0); if (mScrollContainer) { scroller_rect = mScrollContainer->getContentWindowRect(); -- cgit v1.2.3 From b7bcad3164c6d94bb4f9a626982145eefa40e346 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sun, 8 Jul 2012 10:49:08 +0000 Subject: Added support for lib symlinks in deb package. --- debian/rules | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/rules b/debian/rules index e4106ff75c..c41f02d4fb 100755 --- a/debian/rules +++ b/debian/rules @@ -50,15 +50,21 @@ install: build dh_installdirs # Add here commands to install the package into debian/secondlife-viewer. - #$(MAKE) DESTDIR=$(CURDIR)/debian/secondlife-viewer install - for file in $$(find $(SRCDIR) -type f | sed 's~$(SRCDIR)/~~'); do \ + for file in $$(find $(SRCDIR) -type f -o -type l | sed 's~$(SRCDIR)/~~'); do \ # create containing directory \ install -v -m 755 -o root -g root -d "$$(dirname "$(DESTDIR)/$(INSTALLDIR)/$$file")"; \ PERM=644; \ if [ -x "$(SRCDIR)/$$file" ]; then \ PERM=755; \ fi; \ - install -v -m $$PERM -o root -g root "$(SRCDIR)/$$file" "$(DESTDIR)/$(INSTALLDIR)/$$file"; \ + if [ -L "$(SRCDIR)/$$file" ]; then \ + REAL="$$( readlink -f $(SRCDIR)/$$file )"; \ + RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(SRCDIR)/~~' )"; \ + echo dh_link "$(INSTALLDIR)/$$RELATIVE" "$(INSTALLDIR)/$$file" ; \ + dh_link "$(INSTALLDIR)/$$RELATIVE" "$(INSTALLDIR)/$$file" ; \ + else \ + install -v -m $$PERM -o root -g root "$(SRCDIR)/$$file" "$(DESTDIR)/$(INSTALLDIR)/$$file"; \ + fi; \ done dh_link /$(INSTALLDIR)/secondlife /usr/bin/secondlife dh_link $(BASEDIR)/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/SecondLife -- cgit v1.2.3 From bc2517215cbf79cdf8a910e93cc5d3f2ac1534c7 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Mon, 9 Jul 2012 00:48:02 +0000 Subject: Skipping shiftObject pipeline method in headless mode --- indra/newview/llviewerobjectlist.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index beb68c1cbb..e4ce670a43 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1491,6 +1491,7 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { + if (gHeadlessClient) return; // This is called when we shift our origin when we cross region boundaries... // We need to update many object caches, I'll document this more as I dig through the code // cleaning things out... -- cgit v1.2.3 From 033c84dc9452f4b38cdf87446203241c4554d126 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 9 Jul 2012 14:03:08 -0400 Subject: SH-3171 FIX switched texture pipeline to use the new cap request URL If we support server side texture baking, requests for baked textures will go through the http url received at login. --- indra/newview/llviewerobject.cpp | 17 +++++++++++++++++ indra/newview/llviewerobject.h | 1 + indra/newview/llvoavatar.cpp | 18 ++++++++++++++++-- indra/newview/llvoavatardefines.cpp | 12 ++++++------ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index cd300accb7..877e475928 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4141,6 +4141,23 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) } +S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, const std::string &url ) +{ + S32 retval = 0; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + retval = LLPrimitive::setTETexture(te, uuid); + mTEImages[te] = LLViewerTextureManager::getFetchedTextureFromUrl (url, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; +} + S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host) { S32 retval = 0; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index c8152e1539..b380e9b8ce 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -314,6 +314,7 @@ public: /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); S32 setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host); + S32 setTETextureCore(const U8 te, const LLUUID& uuid, const std::string &url ); /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 531d3b4940..d48d79f807 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2370,6 +2370,17 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) // to redirect certain avatar texture requests to different sims. if (isIndexBakedTexture((ETextureIndex)te)) { + std::string url = gSavedSettings.getString("AgentAppearanceServiceURL"); + if (LLAppearanceMgr::instance().useServerTextureBaking() && !url.empty()) + { + const LLVOAvatarDictionary::TextureEntry* texture_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)te); + if (texture_entry != NULL) + { + url += "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); + return setTETextureCore(te, uuid, url); + } + } + LLHost target_host = getObjectHost(); return setTETextureCore(te, uuid, target_host); } @@ -4669,7 +4680,10 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel //the texture pipeline will stop fetching this texture. imagep->resetTextureStats(); - imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures. + if (!LLAppearanceMgr::instance().useServerTextureBaking()) + { + imagep->setCanUseHTTP(false); //turn off http fetching for baked textures. + } imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; @@ -7294,7 +7308,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData, LLAppearanceMgr::instance().useServerTextureBaking()); + unpackTEMessage(mesgsys, _PREHASH_ObjectData, FALSE); // dumpAvatarTEs( "POST processAvatarAppearance()" ); // prevent the overwriting of valid baked textures with invalid baked textures diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp index 1ed4e3b61c..ef96a9e923 100644 --- a/indra/newview/llvoavatardefines.cpp +++ b/indra/newview/llvoavatardefines.cpp @@ -66,12 +66,12 @@ LLVOAvatarDictionary::Textures::Textures() addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD)); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER)); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER)); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES)); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR)); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT)); + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); } LLVOAvatarDictionary::BakedTextures::BakedTextures() -- cgit v1.2.3 From b490266226ac79cc7570ff7ee921506e941cce16 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 9 Jul 2012 11:49:43 -0700 Subject: CHUI-98 : WIP. Clean up conversation list data structure and comments --- indra/newview/llimfloatercontainer.cpp | 14 +++++++------- indra/newview/llimfloatercontainer.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index be38eddbaf..d343c8be24 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -49,7 +49,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), - mFolders(NULL) + mConversationsRoot(NULL) { // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -91,17 +91,17 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild("conversations_list_panel"); - mRoot = new LLConversationItem(); - LLFolderView::Params p; // CHUI-98 : View Model for conversations + LLConversationItem* base_item = new LLConversationItem(); + LLFolderView::Params p; p.view_model = &mConversationViewModel; p.parent_panel = mConversationsListPanel; p.rect = mConversationsListPanel->getLocalRect(); p.follows.flags = FOLLOWS_ALL; - p.listener = mRoot; + p.listener = base_item; - mFolders = LLUICtrlFactory::create(p); - mConversationsListPanel->addChild(mFolders); + mConversationsRoot = LLUICtrlFactory::create(p); + mConversationsListPanel->addChild(mConversationsRoot); mExpandCollapseBtn = getChild("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); @@ -525,7 +525,7 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat //params.icon = bridge->getIcon(); //params.icon_open = bridge->getOpenIcon(); //params.creation_date = bridge->getCreationDate(); - params.root = mFolders; + params.root = mConversationsRoot; params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index f146e65897..8f0ec27905 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -264,20 +264,20 @@ private: LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; - // CHUI-137 : Temporary implementation of conversations list + // Conversation list implementation public: void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); LLFloater* findConversationItem(LLUUID& uuid); private: - LLConversationViewModel mConversationViewModel; - LLConversationItem* mRoot; LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + // Conversation list data - LLPanel* mConversationsListPanel; // This is the widget we add items to (i.e. clickable title for each conversation) + LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to conversations_items_map mConversationsItems; conversations_widgets_map mConversationsWidgets; - LLFolderView* mFolders; + LLConversationViewModel mConversationViewModel; + LLFolderView* mConversationsRoot; }; #endif // LL_LLIMFLOATERCONTAINER_H -- cgit v1.2.3 From cb2b59b48b6cf8aeb17f5b0f9f4063e8340ce144 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 10 Jul 2012 00:42:10 +0000 Subject: Added new settings: DisableAllRenderTypes, DisableAllRenderFeatures, and MaxFPS. --- indra/newview/app_settings/settings.xml | 33 ++++++++++++++++++++++++++ indra/newview/llappviewer.cpp | 20 ++++++++++++++++ indra/newview/llappviewer.h | 1 + indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/pipeline.cpp | 42 ++++++++++++++++++++++++++------- indra/newview/pipeline.h | 5 +++- 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5e50bd6e01..dde423f86c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8705,6 +8705,28 @@ Value 1 + DisableAllRenderTypes + + Comment + Disables all rendering types. + Persist + 0 + Type + Boolean + Value + 0 + + DisableAllRenderFeatures + + Comment + Disables all rendering features. + Persist + 0 + Type + Boolean + Value + 0 + RenderHUDInSnapshot Comment @@ -13010,6 +13032,17 @@ Value -1 + MaxFPS + + Comment + Yield some time to the local host if we reach a threshold framerate. + Persist + 1 + Type + F32 + Value + -1.0 + ZoomDirect Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index efa24796e5..f01f62c798 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -632,6 +632,7 @@ LLAppViewer::LLAppViewer() : mQuitRequested(false), mLogoutRequestSent(false), mYieldTime(-1), + mMinFrameTime(-1.0), mMainloopTimeout(NULL), mAgentRegionLastAlive(false), mRandomizeFramerate(LLCachedControl(gSavedSettings,"Randomize Framerate", FALSE)), @@ -1465,6 +1466,19 @@ bool LLAppViewer::mainLoop() { gFrameStalls++; } + + // Limit FPS + if (mMinFrameTime > F_APPROXIMATELY_ZERO) + { + // Sleep a while to limit frame rate. + S32 milliseconds_to_sleep = llclamp((S32)((mMinFrameTime - frameTimer.getElapsedTimeF64()) * 1000.f), 0, 1000); + if (milliseconds_to_sleep > 0) + { + LLFastTimer t(FTM_YIELD); + ms_sleep(milliseconds_to_sleep); + } + } + frameTimer.reset(); resumeMainloopTimeout(); @@ -2577,6 +2591,12 @@ bool LLAppViewer::initConfiguration() } mYieldTime = gSavedSettings.getS32("YieldTime"); + mMinFrameTime = -1.0f; + F32 max_fps = gSavedSettings.getF32("MaxFPS"); + if (max_fps > F_APPROXIMATELY_ZERO) + { + mMinFrameTime = 1.0f / max_fps; + } // Read skin/branding settings if specified. //if (! gDirUtilp->getSkinDir().empty() ) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index ae3c795d1e..f55954234f 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -254,6 +254,7 @@ private: bool mQuitRequested; // User wants to quit, may have modified documents open. bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim. S32 mYieldTime; + F32 mMinFrameTime; struct SettingsFiles* mSettingsLocationList; LLWatchdogTimeout* mMainloopTimeout; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 4571d08050..e4451c3c93 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1042,7 +1042,7 @@ void render_hud_attachments() gPipeline.pushRenderTypeMask(); // turn off everything - gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); + gPipeline.clearAllRenderTypes(); // turn on HUD gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); // turn on HUD particles diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index de72d79043..cd4c7289a7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -471,19 +471,29 @@ void LLPipeline::init() LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) { - mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + mRenderDebugFeatureMask = 0x0; + } + else + { + mRenderDebugFeatureMask = 0xffffffff; // By default, all debugging features on } - - mRenderDebugFeatureMask = 0xffffffff; // All debugging features on mRenderDebugMask = 0; // All debug starts off - // Don't turn on ground when this is set - // Mac Books with intel 950s need this - if(!gSavedSettings.getBOOL("RenderGround")) + if (gSavedSettings.getBOOL("DisableAllRenderTypes")) { - toggleRenderType(RENDER_TYPE_GROUND); + clearAllRenderTypes(); + } + else + { + setAllRenderTypes(); // By default, all rendering types start enabled + // Don't turn on ground when this is set + // Mac Books with intel 950s need this + if(!gSavedSettings.getBOOL("RenderGround")) + { + toggleRenderType(RENDER_TYPE_GROUND); + } } // make sure RenderPerformanceTest persists (hackity hack hack) @@ -9945,6 +9955,22 @@ void LLPipeline::clearRenderTypeMask(U32 type, ...) } } +void LLPipeline::setAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; + } +} + +void LLPipeline::clearAllRenderTypes() +{ + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = FALSE; + } +} + void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color) { DebugBlip blip(position, color); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 6ae482fa06..3536746eb1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -311,9 +311,12 @@ public: BOOL hasAnyRenderType(const U32 type, ...) const; void setRenderTypeMask(U32 type, ...); - void orRenderTypeMask(U32 type, ...); + // This is equivalent to 'setRenderTypeMask' + //void orRenderTypeMask(U32 type, ...); void andRenderTypeMask(U32 type, ...); void clearRenderTypeMask(U32 type, ...); + void setAllRenderTypes(); + void clearAllRenderTypes(); void pushRenderTypeMask(); void popRenderTypeMask(); -- cgit v1.2.3 From b203fe12f8ea19ee80d9de1ac6ff4ebbc3bdb493 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 10 Jul 2012 16:49:49 +0300 Subject: CHUI-201 FIX for crash when leaving a voice call via the end call prompt. Fixed the problem with confirmLeaveCallCallback() firing after the chat floater is destroyed. --- indra/newview/llimfloater.cpp | 57 +++++++++++++++++++++++-------------------- indra/newview/llimfloater.h | 2 ++ 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a506f0f9f3..23c97c5345 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -118,6 +118,35 @@ void LLIMFloater::refresh() } } +// virtual +void LLIMFloater::onClickCloseBtn() +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + mSessionID); + + if (session == NULL) + { + llwarns << "Empty session." << llendl; + return; + } + + bool is_call_with_chat = session->isGroupSessionType() + || session->isAdHocSessionType() || session->isP2PSessionType(); + + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + + if (is_call_with_chat && voice_channel != NULL + && voice_channel->isActive()) + { + LLSD payload; + payload["session_id"] = mSessionID; + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); + return; + } + + LLIMConversation::onClickCloseBtn(); +} + /* static */ void LLIMFloater::newIMCallback(const LLSD& data) { @@ -407,8 +436,7 @@ void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); // then we can close the current session - gIMMgr->leaveSession(mSessionID); - LLIMConversation::onClose(false); + onClose(false); // Start a new ad hoc voice call if we invite new participants to a P2P call, // or start a text chat otherwise. @@ -667,29 +695,6 @@ LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) void LLIMFloater::onClose(bool app_quitting) { - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); - - if (session == NULL) - { - llwarns << "Empty session." << llendl; - return; - } - - bool is_call_with_chat = session->isGroupSessionType() - || session->isAdHocSessionType() || session->isP2PSessionType(); - - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - - if (is_call_with_chat && voice_channel != NULL - && voice_channel->isActive()) - { - LLSD payload; - payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); - return; - } - setTyping(false); // The source of much argument and design thrashing @@ -1278,7 +1283,7 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& const LLSD& payload = notification["payload"]; LLUUID session_id = payload["session_id"]; - LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); + LLFloater* im_floater = findInstance(session_id); if (option == 0 && im_floater != NULL) { im_floater->closeFloater(); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 2e8fc84746..2ac11ded20 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -132,6 +132,8 @@ private: /*virtual*/ void refresh(); + /*virtual*/ void onClickCloseBtn(); + // Update the window title, input field help text, etc. void updateSessionName(const std::string& ui_title, const std::string& ui_label); -- cgit v1.2.3 From a589bc99701d6258d3dd467a5d36fb989348a758 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 11 Jul 2012 00:30:04 +0000 Subject: Added LLPipeline eventhost API. Added ForcePeriodicRenderingTime setting. --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llappviewer.cpp | 47 ++++--- indra/newview/llappviewer.h | 2 - indra/newview/llpipelinelistener.cpp | 216 ++++++++++++++++++++++++++++++++ indra/newview/llpipelinelistener.h | 41 ++++++ indra/newview/llviewermenu.h | 5 + indra/newview/pipeline.cpp | 25 +++- indra/newview/pipeline.h | 10 +- 9 files changed, 337 insertions(+), 22 deletions(-) create mode 100644 indra/newview/llpipelinelistener.cpp create mode 100644 indra/newview/llpipelinelistener.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9783601696..5a1055319a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -418,6 +418,7 @@ set(viewer_SOURCE_FILES llpatchvertexarray.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp + llpipelinelistener.cpp llplacesinventorybridge.cpp llplacesinventorypanel.cpp llpopupview.cpp @@ -967,6 +968,7 @@ set(viewer_HEADER_FILES llpatchvertexarray.h llphysicsmotion.h llphysicsshapebuilderutil.h + llpipelinelistener.h llplacesinventorybridge.h llplacesinventorypanel.h llpolymesh.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dde423f86c..8c82b761bb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13043,6 +13043,17 @@ Value -1.0 + ForcePeriodicRenderingTime + + Comment + Periodically enable all rendering masks for a single frame. + Persist + 1 + Type + F32 + Value + -1.0 + ZoomDirect Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f01f62c798..f5dce58758 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -631,8 +631,6 @@ LLAppViewer::LLAppViewer() : mForceGraphicsDetail(false), mQuitRequested(false), mLogoutRequestSent(false), - mYieldTime(-1), - mMinFrameTime(-1.0), mMainloopTimeout(NULL), mAgentRegionLastAlive(false), mRandomizeFramerate(LLCachedControl(gSavedSettings,"Randomize Framerate", FALSE)), @@ -1200,7 +1198,7 @@ bool LLAppViewer::mainLoop() LLVoiceChannel::initClass(); LLVoiceClient::getInstance()->init(gServicePump); LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true); - LLTimer frameTimer,idleTimer; + LLTimer frameTimer,idleTimer,periodicRenderingTimer; LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); @@ -1212,6 +1210,8 @@ bool LLAppViewer::mainLoop() // point of posting. LLSD newFrame; + BOOL restore_rendering_masks = FALSE; + //LLPrivateMemoryPoolTester::getInstance()->run(false) ; //LLPrivateMemoryPoolTester::getInstance()->run(true) ; //LLPrivateMemoryPoolTester::destroy() ; @@ -1229,6 +1229,28 @@ bool LLAppViewer::mainLoop() try { + // Check if we need to restore rendering masks. + if (restore_rendering_masks) + { + gPipeline.popRenderDebugFeatureMask(); + gPipeline.popRenderTypeMask(); + } + // Check if we need to temporarily enable rendering. + F32 periodic_rendering = gSavedSettings.getF32("ForcePeriodicRenderingTime"); + if (periodic_rendering > F_APPROXIMATELY_ZERO && periodicRenderingTimer.getElapsedTimeF64() > periodic_rendering) + { + periodicRenderingTimer.reset(); + restore_rendering_masks = TRUE; + gPipeline.pushRenderTypeMask(); + gPipeline.pushRenderDebugFeatureMask(); + gPipeline.setAllRenderTypes(); + gPipeline.setAllRenderDebugFeatures(); + } + else + { + restore_rendering_masks = FALSE; + } + pingMainloopTimeout("Main:MiscNativeWindowEvents"); if (gViewerWindow) @@ -1351,10 +1373,11 @@ bool LLAppViewer::mainLoop() LLFastTimer t2(FTM_SLEEP); // yield some time to the os based on command line option - if(mYieldTime >= 0) + S32 yield_time = gSavedSettings.getS32("YieldTime"); + if(yield_time >= 0) { LLFastTimer t(FTM_YIELD); - ms_sleep(mYieldTime); + ms_sleep(yield_time); } // yield cooperatively when not running as foreground window @@ -1468,10 +1491,12 @@ bool LLAppViewer::mainLoop() } // Limit FPS - if (mMinFrameTime > F_APPROXIMATELY_ZERO) + F32 max_fps = gSavedSettings.getF32("MaxFPS"); + if (max_fps > F_APPROXIMATELY_ZERO) { // Sleep a while to limit frame rate. - S32 milliseconds_to_sleep = llclamp((S32)((mMinFrameTime - frameTimer.getElapsedTimeF64()) * 1000.f), 0, 1000); + F32 min_frame_time = 1.f / max_fps; + S32 milliseconds_to_sleep = llclamp((S32)((min_frame_time - frameTimer.getElapsedTimeF64()) * 1000.f), 0, 1000); if (milliseconds_to_sleep > 0) { LLFastTimer t(FTM_YIELD); @@ -2590,14 +2615,6 @@ bool LLAppViewer::initConfiguration() } } - mYieldTime = gSavedSettings.getS32("YieldTime"); - mMinFrameTime = -1.0f; - F32 max_fps = gSavedSettings.getF32("MaxFPS"); - if (max_fps > F_APPROXIMATELY_ZERO) - { - mMinFrameTime = 1.0f / max_fps; - } - // Read skin/branding settings if specified. //if (! gDirUtilp->getSkinDir().empty() ) //{ diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index f55954234f..043893020b 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -253,8 +253,6 @@ private: bool mQuitRequested; // User wants to quit, may have modified documents open. bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim. - S32 mYieldTime; - F32 mMinFrameTime; struct SettingsFiles* mSettingsLocationList; LLWatchdogTimeout* mMainloopTimeout; diff --git a/indra/newview/llpipelinelistener.cpp b/indra/newview/llpipelinelistener.cpp new file mode 100644 index 0000000000..20759239bf --- /dev/null +++ b/indra/newview/llpipelinelistener.cpp @@ -0,0 +1,216 @@ +/** + * @file llpipelinelistener.h + * @author Don Kjer + * @date 2012-07-09 + * @brief Implementation for LLPipelineListener + * + * $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$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" + +#include "llpipelinelistener.h" + +#include "pipeline.h" +#include "stringize.h" +#include +#include "llviewermenu.h" + + +namespace { + // Render Types + void toggle_render_types_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["types"].beginArray(); + iter != request["types"].endArray(); + ++iter) + { + U32 render_type = render_type_from_string( iter->asString() ); + if ( render_type != 0 ) + { + LLPipeline::toggleRenderTypeControl( (void*) render_type ); + } + } + } + + void has_render_type_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 render_type = render_type_from_string( request["type"].asString() ); + if ( render_type != 0 ) + { + response["value"] = LLPipeline::hasRenderTypeControl( (void*) render_type ); + } + else + { + response.error(STRINGIZE("unknown type '" << request["type"].asString() << "'")); + } + } + + void disable_all_render_types_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderTypes(); + } + + void enable_all_render_types_wrapper(LLSD const& request) + { + gPipeline.setAllRenderTypes(); + } + + // Render Features + void toggle_render_features_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["features"].beginArray(); + iter != request["features"].endArray(); + ++iter) + { + U32 render_feature = feature_from_string( iter->asString() ); + if ( render_feature != 0 ) + { + LLPipeline::toggleRenderDebugControl( (void*) render_feature ); + } + } + } + + void has_render_feature_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 render_feature = feature_from_string( request["feature"].asString() ); + if ( render_feature != 0 ) + { + response["value"] = gPipeline.hasRenderDebugFeatureMask(render_feature); + } + else + { + response.error(STRINGIZE("unknown feature '" << request["feature"].asString() << "'")); + } + } + + void disable_all_render_features_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderDebugFeatures(); + } + + void enable_all_render_features_wrapper(LLSD const& request) + { + gPipeline.setAllRenderDebugFeatures(); + } + + // Render Info Displays + void toggle_info_displays_wrapper(LLSD const& request) + { + for (LLSD::array_const_iterator iter = request["displays"].beginArray(); + iter != request["displays"].endArray(); + ++iter) + { + U32 info_display = info_display_from_string( iter->asString() ); + if ( info_display != 0 ) + { + LLPipeline::toggleRenderDebug( (void*) info_display ); + } + } + } + + void has_info_display_wrapper(LLSD const& request) + { + LLEventAPI::Response response(LLSD(), request); + U32 info_display = info_display_from_string( request["display"].asString() ); + if ( info_display != 0 ) + { + response["value"] = gPipeline.hasRenderDebugMask(info_display); + } + else + { + response.error(STRINGIZE("unknown display '" << request["display"].asString() << "'")); + } + } + + void disable_all_info_displays_wrapper(LLSD const& request) + { + gPipeline.clearAllRenderDebugDisplays(); + } + + void enable_all_info_displays_wrapper(LLSD const& request) + { + gPipeline.setAllRenderDebugDisplays(); + } + +} + + +LLPipelineListener::LLPipelineListener(): + LLEventAPI("LLPipeline", + "API to te rendering pipeline.") +{ + // Render Types + add("toggleRenderTypes", + "Toggle rendering [\"types\"]:\n" + "See: llviewermenu.cpp:render_type_from_string for list of available types.", + &toggle_render_types_wrapper); + add("hasRenderType", + "Check if rendering [\"type\"] is enabled:\n" + "See: llviewermenu.cpp:render_type_from_string for list of available types.", + &has_render_type_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderTypes", + "Turn off all rendering types.", + &disable_all_render_types_wrapper); + add("enableAllRenderTypes", + "Turn on all rendering types.", + &enable_all_render_types_wrapper); + + // Render Features + add("toggleRenderFeatures", + "Toggle rendering [\"features\"]:\n" + "See: llviewermenu.cpp:feature_from_string for list of available features.", + &toggle_render_features_wrapper); + add("hasRenderFeature", + "Check if rendering [\"feature\"] is enabled:\n" + "See: llviewermenu.cpp:render_feature_from_string for list of available features.", + &has_render_feature_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderFeatures", + "Turn off all rendering features.", + &disable_all_render_features_wrapper); + add("enableAllRenderFeatures", + "Turn on all rendering features.", + &enable_all_render_features_wrapper); + + // Render Info Displays + add("toggleRenderInfoDisplays", + "Toggle info [\"displays\"]:\n" + "See: llviewermenu.cpp:info_display_from_string for list of available displays.", + &toggle_info_displays_wrapper); + add("hasRenderInfoDisplay", + "Check if info [\"display\"] is enabled:\n" + "See: llviewermenu.cpp:info_display_from_string for list of available displays.", + &has_info_display_wrapper, + LLSDMap("reply", LLSD())); + add("disableAllRenderInfoDisplays", + "Turn off all info displays.", + &disable_all_info_displays_wrapper); + add("enableAllRenderInfoDisplays", + "Turn on all info displays.", + &enable_all_info_displays_wrapper); +} + diff --git a/indra/newview/llpipelinelistener.h b/indra/newview/llpipelinelistener.h new file mode 100644 index 0000000000..da1898e57b --- /dev/null +++ b/indra/newview/llpipelinelistener.h @@ -0,0 +1,41 @@ +/** + * @file llpipelinelistener.h + * @author Don Kjer + * @date 2012-07-09 + * @brief Wrap subset of LLPipeline API in event API + * + * $LicenseInfo:firstyear=2012&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$ + */ + +#if ! defined(LL_LLPIPELINELISTENER_H) +#define LL_LLPIPELINELISTENER_H + +#include "lleventapi.h" + +/// Listen on an LLEventPump with specified name for LLPipeline request events. +class LLPipelineListener: public LLEventAPI +{ +public: + LLPipelineListener(); +}; + +#endif /* ! defined(LL_LLPIPELINELISTENER_H) */ diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 8c40762865..c809ebde43 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -130,6 +130,11 @@ bool handle_go_to(); // Export to XML or Collada void handle_export_selected( void * ); +// Convert strings to internal types +U32 render_type_from_string(std::string render_type); +U32 feature_from_string(std::string feature); +U32 info_display_from_string(std::string info_display); + class LLViewerMenuHolderGL : public LLMenuHolderGL { public: diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cd4c7289a7..72cc6bfcd4 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -72,6 +72,7 @@ #include "llhudtext.h" #include "lllightconstants.h" #include "llmeshrepository.h" +#include "llpipelinelistener.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llsky.h" @@ -368,6 +369,8 @@ BOOL LLPipeline::sMemAllocationThrottled = FALSE; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; +// EventHost API LLPipeline listener. +static LLPipelineListener sPipelineListener; static LLCullResult* sCull = NULL; @@ -473,13 +476,13 @@ void LLPipeline::init() if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) { - mRenderDebugFeatureMask = 0x0; + clearAllRenderDebugFeatures(); } else { - mRenderDebugFeatureMask = 0xffffffff; // By default, all debugging features on + setAllRenderDebugFeatures(); // By default, all debugging features on } - mRenderDebugMask = 0; // All debug starts off + clearAllRenderDebugDisplays(); // All debug displays off if (gSavedSettings.getBOOL("DisableAllRenderTypes")) { @@ -6008,6 +6011,22 @@ void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value) } } +void LLPipeline::pushRenderDebugFeatureMask() +{ + mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); +} + +void LLPipeline::popRenderDebugFeatureMask() +{ + if (mRenderDebugFeatureStack.empty()) + { + llerrs << "Depleted render feature stack." << llendl; + } + + mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); + mRenderDebugFeatureStack.pop(); +} + // static void LLPipeline::setRenderScriptedBeacons(BOOL val) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 3536746eb1..16610b8c68 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -304,8 +304,10 @@ public: BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; } - - + void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } + void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } + void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffff; } + void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } BOOL hasRenderType(const U32 type) const; BOOL hasAnyRenderType(const U32 type, ...) const; @@ -321,6 +323,9 @@ public: void pushRenderTypeMask(); void popRenderTypeMask(); + void pushRenderDebugFeatureMask(); + void popRenderDebugFeatureMask(); + static void toggleRenderType(U32 type); // For UI control of render features @@ -609,6 +614,7 @@ protected: U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; + std::stack mRenderDebugFeatureStack; U32 mOldRenderDebugMask; -- cgit v1.2.3 From aafbf0d21301ccaf2e447a556d08e6686f519d4d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 11 Jul 2012 17:19:22 +0300 Subject: CHUI-203 FIXED Conversations floater resizing when it is opened with FUI Chat button. --- indra/newview/llimfloatercontainer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index e9144a4969..f54b3672e5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -393,7 +393,9 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); - setShape(floater_rect); + + // Set by_user = true so that reshaped rect is saved in user_settings. + setShape(floater_rect, true); updateResizeLimits(); -- cgit v1.2.3 From 64ad1aba304c50173195e15477c1882c5b6e7d37 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 11 Jul 2012 18:30:39 -0400 Subject: SH-3258 WIP initial work: refactoring appearance editing mode Added flags for appearance editing status as well as which textures we should be using at a time. Also refactored so we are not using camera state to track appearance editing mode. Need to add more handling for which textures we actually use. --- indra/newview/llagentcamera.cpp | 36 +++++++++++++-------------------- indra/newview/llmorphview.cpp | 2 -- indra/newview/llsidepanelappearance.cpp | 32 +++++++++++------------------ indra/newview/llvoavatar.cpp | 12 +++-------- indra/newview/llvoavatar.h | 2 ++ indra/newview/llvoavatarself.cpp | 29 +++++++++++++++++++++----- indra/newview/llvoavatarself.h | 4 ++-- 7 files changed, 57 insertions(+), 60 deletions(-) diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 751b73e1eb..a544909e66 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2251,7 +2251,7 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToCustomizeAvatar() { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) + if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) { return; } @@ -2275,29 +2275,21 @@ void LLAgentCamera::changeCameraToCustomizeAvatar() gFocusMgr.setKeyboardFocus( NULL ); gFocusMgr.setMouseCapture( NULL ); - LLVOAvatarSelf::onCustomizeStart(); - - if (isAgentAvatarValid()) - { - // Remove any pitch or rotation from the avatar - LLVector3 at = gAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - - gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); - gAgent.setCustomAnim(TRUE); - gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); - LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); + // Remove any pitch or rotation from the avatar + LLVector3 at = gAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); - if (turn_motion) - { - // delay camera animation long enough to play through turn animation - setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); - } + gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); + gAgent.setCustomAnim(TRUE); + gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - gAgentAvatarp->invalidateAll(); - gAgentAvatarp->updateMeshTextures(); + if (turn_motion) + { + // delay camera animation long enough to play through turn animation + setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); } } diff --git a/indra/newview/llmorphview.cpp b/indra/newview/llmorphview.cpp index eaa044cb59..252d1b78ea 100644 --- a/indra/newview/llmorphview.cpp +++ b/indra/newview/llmorphview.cpp @@ -99,8 +99,6 @@ void LLMorphView::initialize() //----------------------------------------------------------------------------- void LLMorphView::shutdown() { - LLVOAvatarSelf::onCustomizeEnd(); - if (isAgentAvatarValid()) { gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..9267444534 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -206,12 +206,9 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) } // Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar // when editing its physics. - const BOOL disable_camera_motion = LLWearableType::getDisableCameraSwitch(wearable_ptr->getType()); - if (!gAgentCamera.cameraCustomizeAvatar() && - !disable_camera_motion && - gSavedSettings.getBOOL("AppearanceCameraMovement")) + if (!gAgentCamera.cameraCustomizeAvatar()) { - gAgentCamera.changeCameraToCustomizeAvatar(); + LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); } if (is_wearable_edit_visible) { @@ -283,7 +280,7 @@ void LLSidepanelAppearance::onEditAppearanceButtonClicked() { if (gAgentWearables.areWearablesLoaded()) { - gAgentCamera.changeCameraToCustomizeAvatar(); + LLVOAvatarSelf::onCustomizeStart(); } } @@ -371,15 +368,14 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam if (visible) { mOutfitEdit->onOpen(LLSD()); - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); } - else if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) + else { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. + { + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); + } } } @@ -405,10 +401,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we if (visible) { - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); mEditWearable->setWearable(wearable, disable_camera_switch); mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency } @@ -416,10 +409,9 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we { // Save changes if closing. mEditWearable->saveChanges(); - if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); } } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d48d79f807..6bcb0c6882 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -692,8 +692,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar")), - mLastRezzedStatus(-1) - + mLastRezzedStatus(-1), + mIsEditingAppearance(FALSE), + mUseLocalAppearance(FALSE) { LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune @@ -7336,13 +7337,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); - // ! BACKWARDS COMPATIBILITY ! - // Non-self avatars will no longer have component textures - if (!isSelf()) - { - releaseComponentTextures(); - } - // parse visual params S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6fb56a4c0b..3ad13d2edb 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -702,6 +702,8 @@ private: BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; F32 mLastAppearanceBlendTime; + BOOL mIsEditingAppearance; + BOOL mUseLocalAppearance; //-------------------------------------------------------------------- // Clothing colors (convenience functions to access visual parameters) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index ecc616fa67..5355651692 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2705,19 +2705,38 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const // static -void LLVOAvatarSelf::onCustomizeStart() +void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) { - // We're no longer doing any baking or invalidating on entering - // appearance editing mode. Leaving function in place in case - // further changes require us to do something at this point - Nyx + if (isAgentAvatarValid()) + { + gAgentAvatarp->mIsEditingAppearance = true; + gAgentAvatarp->mUseLocalAppearance = true; + + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToCustomizeAvatar(); + } + + gAgentAvatarp->invalidateAll(); + gAgentAvatarp->updateMeshTextures(); + } } // static -void LLVOAvatarSelf::onCustomizeEnd() +void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch) { + gAgentAvatarp->mIsEditingAppearance = false; if (isAgentAvatarValid()) { gAgentAvatarp->invalidateAll(); + + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToDefault(); + gAgentCamera.resetView(); + } + + LLAppearanceMgr::instance().updateAppearanceFromCOF(); } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 543891ca63..5354f18679 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -330,8 +330,8 @@ private: **/ public: - static void onCustomizeStart(); - static void onCustomizeEnd(); + static void onCustomizeStart(bool disable_camera_switch = false); + static void onCustomizeEnd(bool disable_camera_switch = false); //-------------------------------------------------------------------- // Visibility -- cgit v1.2.3 From f0e34ebcd61ee998efa681a211545a7335d60c97 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 11 Jul 2012 23:58:11 +0000 Subject: Adding --skip-gridargs argument to secondlife wrapper script on linux. --- indra/newview/linux_tools/wrapper.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 20936c6460..fa9ce703a8 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -117,18 +117,32 @@ export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" # Simply embedding $( Date: Thu, 12 Jul 2012 16:36:01 +0300 Subject: CHUI-199 FIXED Save positioning of conversations between sessions --- indra/newview/llimconversation.cpp | 33 ++++++++++++++++++---- indra/newview/llimconversation.h | 1 + indra/newview/llimfloatercontainer.cpp | 19 ------------- indra/newview/llimfloatercontainer.h | 1 - .../skins/default/xui/en/floater_im_session.xml | 1 + 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 3c6c5c3898..4774cc2d5a 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -219,16 +219,39 @@ void LLIMConversation::updateHeaderAndToolbar() { bool is_hosted = getHost() != NULL; - if (is_hosted) + if (mWasHosted != is_hosted) { - for (S32 i = 0; i < BUTTON_COUNT; i++) + mWasHosted = is_hosted; + LLView* floater_contents = getChild("contents_view"); + LLRect contents_rect = floater_contents->getRect(); + + if (is_hosted) { - if (mButtons[i]) + for (S32 i = 0; i < BUTTON_COUNT; i++) { - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } } + + // we don't show the header when the floater is hosted, so reshape floater contents + // to occupy the header space. + LLRect floater_rect = getRect(); + contents_rect.setOriginAndSize( + contents_rect.mLeft, + contents_rect.mBottom, + floater_rect.getWidth(), + floater_rect.getHeight()); } + else + { + // reduce the floater contents height by header height + contents_rect.mTop -= getHeaderHeight(); + } + + floater_contents->setShape(contents_rect); } // Participant list should be visible only in torn off floaters. diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 682779a44b..19d1e523f0 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -91,6 +91,7 @@ protected: bool mIsNearbyChat; bool mIsP2PChat; + bool mWasHosted; LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f54b3672e5..bf0fc2f6c0 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -154,12 +154,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, // Add a conversation list item in the left pane addConversationListItem(floaterp->getTitle(), session_id, floaterp); - LLView* floater_contents = floaterp->getChild("contents_view"); - - // we don't show the header when the floater is hosted, - // so reshape floater contents to occupy the header space - floater_contents->setShape(floaterp->getRect()); - LLIconCtrl* icon = 0; if(gAgent.isInGroup(session_id, TRUE)) @@ -185,19 +179,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, mTabContainer->setTabImage(floaterp, icon); } -// virtual -void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) -{ - LLMultiFloater::removeFloater(floaterp); - - LLRect contents_rect = floaterp->getRect(); - - // reduce the floater contents height by header height - contents_rect.mTop -= floaterp->getHeaderHeight(); - - LLView* floater_contents = floaterp->getChild("contents_view"); - floater_contents->setShape(contents_rect); -} void LLIMFloaterContainer::onCloseFloater(LLUUID& id) { diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 0d988b5b73..b624b7558a 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -220,7 +220,6 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - /*virtual*/ void removeFloater(LLFloater* floaterp); /*virtual*/ void tabClose(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 32eb4ebdae..95f6708e96 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,6 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" + save_rect="true" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From 6681b47d4f75433ef409ca3eaa0ea1e10161cc80 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Jul 2012 11:09:27 -0400 Subject: SH-3267 WIP --- indra/newview/llappearancemgr.cpp | 13 +++++++++++++ indra/newview/llappearancemgr.h | 1 + 2 files changed, 14 insertions(+) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 480a8e0d73..04c4220afd 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -925,6 +925,18 @@ const LLUUID LLAppearanceMgr::getCOF() const return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); } +S32 LLAppearanceMgr::getCOFVersion() const +{ + LLViewerInventoryCategory *cof = gInventory.getCategory(getCOF()); + if (cof) + { + return cof->getVersion(); + } + else + { + return LLViewerInventoryCategory::VERSION_UNKNOWN; + } +} const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() { @@ -2611,6 +2623,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() if (!url.empty()) { LLSD body; + body["cof_version"] = getCOFVersion(); LLHTTPClient::post(url, body, new RequestAgentUpdateAppearanceResponder); } else diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 46457f1dce..954820c154 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -93,6 +93,7 @@ public: // Find the Current Outfit folder. const LLUUID getCOF() const; + S32 getCOFVersion() const; // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); -- cgit v1.2.3 From af7de5dd9373a5a15c4d5ea107782e50eb3ce62c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 12 Jul 2012 19:06:29 +0300 Subject: CHUI-170 Workaround for the permanently showing of the nearbychat's name in a conversations list when that floater is torn-off --- indra/newview/llnearbychat.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 384762549a..1c81cdc4bc 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -363,6 +363,9 @@ void LLNearbyChat::addToHost() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); if (im_box) { + // Make sure the Nearby Chat is present in the conversations list + im_box->addConversationListItem(getTitle(), getKey(), this); + if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { im_box->addFloater(this, TRUE, LLTabContainer::END); -- cgit v1.2.3 From 27c7b259b417d5843422e8bd4e8e480a186e44f4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Jul 2012 18:24:23 -0400 Subject: SH-3267 WIP --- indra/llprimitive/llprimitive.cpp | 107 +++++++++++++++++++++++++++++++++++++- indra/llprimitive/llprimitive.h | 31 ++++++++++- indra/newview/llappearancemgr.cpp | 8 ++- indra/newview/llappearancemgr.h | 2 + indra/newview/llvoavatar.cpp | 20 ++++++- 5 files changed, 162 insertions(+), 6 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index c766d8a43c..0388e2c020 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1228,11 +1228,113 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const return FALSE; } -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, bool fake_images) +S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images, + LLTEContents& tec) { - return(unpackTEMessage(mesgsys,block_name,-1,fake_images)); + tec.fake_images = fake_images; + + S32 retval = 0; + + if (block_num < 0) + { + tec.size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); + } + else + { + tec.size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); + } + + if (tec.size == 0) + { + return retval; + } + + if (block_num < 0) + { + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER); + } + else + { + mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER); + } + + tec.face_count = getNumTEs(); + + U8 *cur_ptr = tec.packed_buffer; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8); + cur_ptr++; + cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8); + + retval = 1; + return retval; +} + +S32 LLPrimitive::unpackParsedTEMessage(LLTEContents& tec) +{ + S32 retval = 0; + + LLColor4 color; + LLColor4U coloru; + for (U32 i = 0; i < tec.face_count; i++) + { + LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; + if (tec.fake_images & (req_id != IMG_DEFAULT) && (req_id != IMG_DEFAULT_AVATAR) && (req_id != IMG_INVISIBLE)) + { + retval |= setTETexture(i, IMG_CHECKERBOARD_RGBA); + } + else + { + retval |= setTETexture(i, req_id); + } + retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]); + retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, tec.bump[i]); + retval |= setTEMediaTexGen(i, tec.media_flags[i]); + retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF); + coloru = LLColor4U(tec.colors + 4*i); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; + + retval |= setTEColor(i, color); + + } + + return retval; +} + +S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images) +{ + LLTEContents tec; + S32 retval = parseTEMessage(mesgsys, block_name, block_num, fake_images, tec); + if (!retval) + return retval; + return unpackParsedTEMessage(tec); } +#if 0 S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images) { // use a negative block_num to indicate a single-block read (a non-variable block) @@ -1339,6 +1441,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam return retval; } +#endif S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 1e985221c0..19ef3faf3f 100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -289,6 +289,34 @@ public: }; +struct LLTEContents +{ + LLTEContents() + { + } + + static const U32 MAX_TES = 32; + + U8 image_data[MAX_TES*16]; + U8 colors[MAX_TES*4]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; + U8 glow[MAX_TES]; + + static const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + + U32 size; + U32 face_count; + + bool fake_images; +}; + class LLPrimitive : public LLXform { public: @@ -360,9 +388,10 @@ public: S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, bool fake_images = false); S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images = false); // Variable num of blocks BOOL unpackTEMessage(LLDataPacker &dp); + S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images,LLTEContents& tec); + S32 unpackParsedTEMessage(LLTEContents& tec); #ifdef CHECK_FOR_FINITE inline void setPosition(const LLVector3& pos); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 04c4220afd..eb31358000 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2623,8 +2623,11 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() if (!url.empty()) { LLSD body; - body["cof_version"] = getCOFVersion(); + S32 cof_version = getCOFVersion(); + body["cof_version"] = cof_version; LLHTTPClient::post(url, body, new RequestAgentUpdateAppearanceResponder); + llassert(cof_version >= mLastUpdateRequestCOFVersion); + mLastUpdateRequestCOFVersion = cof_version; } else { @@ -2842,7 +2845,8 @@ LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), mOutfitIsDirty(false), mOutfitLocked(false), - mIsInUpdateAppearanceFromCOF(false) + mIsInUpdateAppearanceFromCOF(false), + mLastUpdateRequestCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 954820c154..45291419c7 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -95,6 +95,8 @@ public: const LLUUID getCOF() const; S32 getCOFVersion() const; + S32 mLastUpdateRequestCOFVersion; + // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); bool getBaseOutfitName(std::string &name); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6bcb0c6882..f85b59b8c6 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7309,9 +7309,27 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData, FALSE); + LLTEContents tec; + parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, FALSE, tec); // dumpAvatarTEs( "POST processAvatarAppearance()" ); + // Check for stale update. + if (isSelf() && LLAppearanceMgr::instance().useServerTextureBaking()) + { + // Extract COF Version field hacked into local texture id. + LLUUID texture_id = ((LLUUID*)tec.image_data)[0]; + S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion; + S32 *s_words = (S32*) texture_id.mData; + S32 this_update_cof_version = s_words[0]; + if (this_update_cof_version < last_update_request_cof_version) + { + llwarns << "Stale appearance update, wanted version " << last_update_request_cof_version + << ", got " << this_update_cof_version << llendl; + return; + } + } + unpackParsedTEMessage(tec); + // prevent the overwriting of valid baked textures with invalid baked textures for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) { -- cgit v1.2.3 From 5a473a42a63d3277c65bb3bc96e49f020508cfe8 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 13 Jul 2012 02:54:48 +0000 Subject: Remove MaxFPS limit during login, teleports, and logout. --- indra/newview/llappviewer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f5dce58758..8210a41a78 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1492,7 +1492,12 @@ bool LLAppViewer::mainLoop() // Limit FPS F32 max_fps = gSavedSettings.getF32("MaxFPS"); - if (max_fps > F_APPROXIMATELY_ZERO) + // Only limit FPS when we are actually rendering something. Otherwise + // logins, logouts and teleports take much longer to complete. + if (max_fps > F_APPROXIMATELY_ZERO && + LLStartUp::getStartupState() == STATE_STARTED && + !gTeleportDisplay && + !logoutRequestSent()) { // Sleep a while to limit frame rate. F32 min_frame_time = 1.f / max_fps; -- cgit v1.2.3 From 7f7a9b7cbae153b00b8a77d3d662257bf6152912 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Fri, 13 Jul 2012 20:06:35 +0300 Subject: CHUI-205 FIXED conversations selection in the conversations list. Each conversation item is added to the folder view which lists all conversations. --- indra/newview/llimfloatercontainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index bf0fc2f6c0..4f626cb5d2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -438,6 +438,9 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI LLFolderViewItem* widget = createConversationItemWidget(item); mConversationsWidgets[floaterp] = widget; + // Add a new conversation widget to the root folder of a folder view. + mConversationsRoot->addItem(widget); + // Add it to the UI widget->setVisible(TRUE); mConversationsListPanel->addChild(widget); @@ -460,7 +463,7 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; - delete widget; + widget->destroyView(); } // Suppress the conversation items and widgets from their respective maps -- cgit v1.2.3 From 56277fa43c6f6491d356c6fb8a0a0275d4cd00fc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 13 Jul 2012 20:24:44 +0300 Subject: CHUI-206 FIXED Viewer crash when selecting to cut inventory item, then selecting to cut another inventory item --- indra/newview/llfolderviewmodelinventory.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d23b4af8cb..dff1e1be90 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -158,22 +158,20 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite if (item->getLastFilterGeneration() < filter_generation) { + // recursive application of the filter for child items + item->filter( filter ); + if (item->getLastFilterGeneration() >= must_pass_generation && !item->passedFilter(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - item->filter(filter); if (item->passedFilter()) { llerrs << "Invalid shortcut in inventory filtering!" << llendl; } item->setPassedFilter(false, false, filter_generation); } - else - { - item->filter( filter ); - } } // track latest generation to pass any child items, for each folder up to root -- cgit v1.2.3 From 8fd35a0a084303073bc40580d69c797c073fb4dc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 13 Jul 2012 16:30:33 +0300 Subject: CHUI-207 FIXED cancellation of removal of the object that has already been removed --- indra/newview/llinventorypanel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 0aa67cddca..ed370e9add 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -533,7 +533,6 @@ void LLInventoryPanel::modelChanged(U32 mask) // Remove the item's UI. removeItemID(viewmodel_item->getUUID()); view_item->destroyView(); - removeItemID(viewmodel_item->getUUID()); } } } -- cgit v1.2.3 From 409be9dcc4e372385f0fb0de274a4b17913bd124 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Jul 2012 16:59:57 -0400 Subject: SH-3267 WIP - extract cof version from avatar appearance message, use to reject stale updates --- indra/llprimitive/llprimitive.cpp | 131 ++------------------------------------ indra/llprimitive/llprimitive.h | 18 +++--- indra/newview/llappearancemgr.cpp | 20 +++--- indra/newview/llvoavatar.cpp | 8 ++- 4 files changed, 31 insertions(+), 146 deletions(-) diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 0388e2c020..97a382634a 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1228,11 +1228,8 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const return FALSE; } -S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images, - LLTEContents& tec) +S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec) { - tec.fake_images = fake_images; - S32 retval = 0; if (block_num < 0) @@ -1285,7 +1282,7 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name return retval; } -S32 LLPrimitive::unpackParsedTEMessage(LLTEContents& tec) +S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec) { S32 retval = 0; @@ -1294,14 +1291,7 @@ S32 LLPrimitive::unpackParsedTEMessage(LLTEContents& tec) for (U32 i = 0; i < tec.face_count; i++) { LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; - if (tec.fake_images & (req_id != IMG_DEFAULT) && (req_id != IMG_DEFAULT_AVATAR) && (req_id != IMG_INVISIBLE)) - { - retval |= setTETexture(i, IMG_CHECKERBOARD_RGBA); - } - else - { - retval |= setTETexture(i, req_id); - } + retval |= setTETexture(i, req_id); retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]); retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF); retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); @@ -1325,123 +1315,14 @@ S32 LLPrimitive::unpackParsedTEMessage(LLTEContents& tec) return retval; } -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images) +S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num) { LLTEContents tec; - S32 retval = parseTEMessage(mesgsys, block_name, block_num, fake_images, tec); + S32 retval = parseTEMessage(mesgsys, block_name, block_num, tec); if (!retval) return retval; - return unpackParsedTEMessage(tec); -} - -#if 0 -S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images) -{ - // use a negative block_num to indicate a single-block read (a non-variable block) - S32 retval = 0; - const U32 MAX_TES = 32; - - // Avoid construction of 32 UUIDs per call. JC - - U8 image_data[MAX_TES*16]; - U8 colors[MAX_TES*4]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; - U8 glow[MAX_TES]; - - const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; - U8 *cur_ptr = packed_buffer; - - U32 size; - U32 face_count = 0; - - if (block_num < 0) - { - size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); - } - else - { - size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); - } - - if (size == 0) - { - return retval; - } - - if (block_num < 0) - { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, 0, MAX_TE_BUFFER); - } - else - { - mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, block_num, MAX_TE_BUFFER); - } - - face_count = getNumTEs(); - - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8); - cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8); - - LLColor4 color; - LLColor4U coloru; - for (U32 i = 0; i < face_count; i++) - { - LLUUID& req_id = ((LLUUID*)image_data)[i]; - if (fake_images & (req_id != IMG_DEFAULT) && (req_id != IMG_DEFAULT_AVATAR) && (req_id != IMG_INVISIBLE)) - { - retval |= setTETexture(i, IMG_CHECKERBOARD_RGBA); - } - else - { - retval |= setTETexture(i, req_id); - } - retval |= setTEScale(i, scale_s[i], scale_t[i]); - retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); - retval |= setTEBumpShinyFullbright(i, bump[i]); - retval |= setTEMediaTexGen(i, media_flags[i]); - retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); - coloru = LLColor4U(colors + 4*i); - - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) - // as all zeros. However, the subtraction and addition must be done in unsigned - // byte space, not in float space, otherwise off-by-one errors occur. JC - color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f; - color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f; - color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f; - color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; - - retval |= setTEColor(i, color); - - } - - return retval; + return applyParsedTEMessage(tec); } -#endif S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 19ef3faf3f..d9333140a3 100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -289,12 +289,14 @@ public: }; +// This code is not naming-standards compliant. Leaving it like this for +// now to make the connection to code in +// BOOL packTEMessage(LLDataPacker &dp) const; +// more obvious. This should be refactored to remove the duplication, at which +// point we can fix the names as well. +// - Vir struct LLTEContents { - LLTEContents() - { - } - static const U32 MAX_TES = 32; U8 image_data[MAX_TES*16]; @@ -313,8 +315,6 @@ struct LLTEContents U32 size; U32 face_count; - - bool fake_images; }; class LLPrimitive : public LLXform @@ -388,10 +388,10 @@ public: S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys) const; BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images = false); // Variable num of blocks + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks BOOL unpackTEMessage(LLDataPacker &dp); - S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, bool fake_images,LLTEContents& tec); - S32 unpackParsedTEMessage(LLTEContents& tec); + S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec); + S32 applyParsedTEMessage(LLTEContents& tec); #ifdef CHECK_FOR_FINITE inline void setPosition(const LLVector3& pos); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index eb31358000..e27a21f7fd 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2619,20 +2619,22 @@ public: void LLAppearanceMgr::requestServerAppearanceUpdate() { - std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); - if (!url.empty()) + if (!gAgent.getRegion()) { - LLSD body; - S32 cof_version = getCOFVersion(); - body["cof_version"] = cof_version; - LLHTTPClient::post(url, body, new RequestAgentUpdateAppearanceResponder); - llassert(cof_version >= mLastUpdateRequestCOFVersion); - mLastUpdateRequestCOFVersion = cof_version; + llwarns << "Region not set, cannot request server appearance update" << llendl; } - else + std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); + if (url.empty()) { llwarns << "no cap for UpdateAvatarAppearance" << llendl; } + + LLSD body; + S32 cof_version = getCOFVersion(); + body["cof_version"] = cof_version; + LLHTTPClient::post(url, body, new RequestAgentUpdateAppearanceResponder); + llassert(cof_version >= mLastUpdateRequestCOFVersion); + mLastUpdateRequestCOFVersion = cof_version; } class LLShowCreatedOutfit: public LLInventoryCallback diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f85b59b8c6..e686948fa2 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7310,7 +7310,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); LLTEContents tec; - parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, FALSE, tec); + parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, tec); // dumpAvatarTEs( "POST processAvatarAppearance()" ); // Check for stale update. @@ -7321,14 +7321,16 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion; S32 *s_words = (S32*) texture_id.mData; S32 this_update_cof_version = s_words[0]; - if (this_update_cof_version < last_update_request_cof_version) + if ((this_update_cof_version > 0) && + (this_update_cof_version < last_update_request_cof_version)) { llwarns << "Stale appearance update, wanted version " << last_update_request_cof_version << ", got " << this_update_cof_version << llendl; return; } + ((LLUUID*)tec.image_data)[0].setNull(); } - unpackParsedTEMessage(tec); + applyParsedTEMessage(tec); // prevent the overwriting of valid baked textures with invalid baked textures for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) -- cgit v1.2.3 From 3679631887f0acec0b0d180525a56d318692a0e2 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 16 Jul 2012 17:29:01 -0400 Subject: SH-3261 WIP Updated texture switching code Updated texture switching code to use the proper request URL, even if reverting to a "last known good" baked texture UUID. Viewer should now switch to a locally-generated composite on entering appearance mode, and should remain using such until a new appearance message is received. Still to do: handling adjacent regions with varying support for the new system, fixing switch back to server-generated bakes. --- indra/newview/llvoavatar.cpp | 71 ++++++++++++++++++++++------------------ indra/newview/llvoavatar.h | 4 +-- indra/newview/llvoavatarself.cpp | 5 +++ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6bcb0c6882..9c5998b976 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -688,7 +688,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), - mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar")), @@ -2371,15 +2370,10 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) // to redirect certain avatar texture requests to different sims. if (isIndexBakedTexture((ETextureIndex)te)) { - std::string url = gSavedSettings.getString("AgentAppearanceServiceURL"); - if (LLAppearanceMgr::instance().useServerTextureBaking() && !url.empty()) + const std::string url = getImageURL(te,uuid); + if (!url.empty()) { - const LLVOAvatarDictionary::TextureEntry* texture_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)te); - if (texture_entry != NULL) - { - url += "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); - return setTETextureCore(te, uuid, url); - } + return setTETextureCore(te, uuid, url); } LLHost target_host = getObjectHost(); @@ -4152,7 +4146,7 @@ void LLVOAvatar::updateVisibility() // private bool LLVOAvatar::shouldAlphaMask() { - const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked + const bool should_alpha_mask = !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked && !LLDrawPoolAvatar::sSkipTransparent; return should_alpha_mask; @@ -4726,6 +4720,20 @@ void LLVOAvatar::setTexEntry(const U8 index, const LLTextureEntry &te) setTE(index, te); } +const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) +{ + std::string url = ""; + if (LLAppearanceMgr::instance().useServerTextureBaking() && !gSavedSettings.getString("AgentAppearanceServiceURL").empty()) + { + const LLVOAvatarDictionary::TextureEntry* texture_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)te); + if (texture_entry != NULL) + { + url = gSavedSettings.getString("AgentAppearanceServiceURL") + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); + } + } + return url; +} + //----------------------------------------------------------------------------- // resolveHeight() //----------------------------------------------------------------------------- @@ -6658,7 +6666,6 @@ void LLVOAvatar::updateMeshTextures() } } - const BOOL self_customizing = isSelf() && gAgentCamera.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures const BOOL other_culled = !isSelf() && mCulled; LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; BOOL paused = FALSE; @@ -6698,36 +6705,39 @@ void LLVOAvatar::updateMeshTextures() { use_lkg_baked_layer[i] = (!is_layer_baked[i] && mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); - if (mBakedTextureDatas[i].mTexLayerSet) - { - mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); - } } } - - // Turn on alpha masking correctly for yourself and other avatars on 1.23+ - mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR]; - - // Baked textures should be requested from the sim this avatar is on. JC - const LLHost target_host = getObjectHost(); - if (!target_host.isOk()) - { - llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; - } for (U32 i=0; i < mBakedTextureDatas.size(); i++) { - if (use_lkg_baked_layer[i] && !self_customizing ) + if (use_lkg_baked_layer[i] && !mUseLocalAppearance ) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host ); + LLViewerFetchedTexture* baked_img; + const std::string url = getImageURL(i, mBakedTextureDatas[i].mLastTextureIndex); + if (!url.empty()) + { + baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureIndex); + } + else + { + // Baked textures should be requested from the sim this avatar is on. JC + const LLHost target_host = getObjectHost(); + if (!target_host.isOk()) + { + llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; + } + + baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host ); + } + mBakedTextureDatas[i].mIsUsed = TRUE; for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img ); } } - else if (!self_customizing && is_layer_baked[i]) + else if (!mUseLocalAppearance && is_layer_baked[i]) { LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex ) @@ -6747,8 +6757,7 @@ void LLVOAvatar::updateMeshTextures() src_callback_list, paused ); } } - else if (mBakedTextureDatas[i].mTexLayerSet - && !other_culled) + else if (mBakedTextureDatas[i].mTexLayerSet && mUseLocalAppearance) { mBakedTextureDatas[i].mTexLayerSet->createComposite(); mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE ); @@ -6763,7 +6772,7 @@ void LLVOAvatar::updateMeshTextures() // set texture and color of hair manually if we are not using a baked image. // This can happen while loading hair for yourself, or for clients that did not // bake a hair texture. Still needed for yourself after 1.22 is depricated. - if (!is_layer_baked[BAKED_HAIR] || self_customizing) + if (!is_layer_baked[BAKED_HAIR] || mIsEditingAppearance) { const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 3ad13d2edb..2b999891f9 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -217,9 +217,6 @@ public: private: //aligned members LLVector4a mImpostorExtents[2]; -private: - BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients - //-------------------------------------------------------------------- // Updates //-------------------------------------------------------------------- @@ -603,6 +600,7 @@ protected: private: virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index); virtual LLViewerTexture* getImage(const U8 te, const U32 index) const; + const std::string getImageURL(const U8 te, const LLUUID &uuid); virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; virtual void setTexEntry(const U8 index, const LLTextureEntry &te); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 5355651692..e715a0d2f1 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2726,6 +2726,11 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch) { gAgentAvatarp->mIsEditingAppearance = false; + if (!LLAppearanceMgr::instance().useServerTextureBaking()) + { + gAgentAvatarp->mUseLocalAppearance = false; + } + if (isAgentAvatarValid()) { gAgentAvatarp->invalidateAll(); -- cgit v1.2.3 From b3ca0b09dcbe6189d6b1f6d0439b0d9d6f575007 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Tue, 17 Jul 2012 16:43:48 +0300 Subject: Fixed positioning of conversations into container --- indra/newview/llimconversation.cpp | 51 ++++++++++++++++++++++++-------------- indra/newview/llimconversation.h | 3 +++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 4774cc2d5a..ec7e0ee6cb 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -43,6 +43,7 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) , mIsP2PChat(false) + , mWasHosted(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) @@ -80,6 +81,8 @@ LLIMConversation::~LLIMConversation() BOOL LLIMConversation::postBuild() { + BOOL result; + mCloseBtn = getChild("close_btn"); mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); @@ -103,6 +106,7 @@ BOOL LLIMConversation::postBuild() } buildParticipantList(); + updateHeaderAndToolbar(); if (isChatMultiTab()) @@ -111,13 +115,14 @@ BOOL LLIMConversation::postBuild() { setCanClose(FALSE); } - return LLFloater::postBuild(); + result = LLFloater::postBuild(); } else { - return LLDockableFloater::postBuild(); + result = LLDockableFloater::postBuild(); } + return result; } void LLIMConversation::draw() @@ -215,7 +220,7 @@ bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } -void LLIMConversation::updateHeaderAndToolbar() +void LLIMConversation::hideOrShowTitle() { bool is_hosted = getHost() != NULL; @@ -227,23 +232,9 @@ void LLIMConversation::updateHeaderAndToolbar() if (is_hosted) { - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - if (mButtons[i]) - { - // Hide the standard header buttons in a docked IM floater. - mButtons[i]->setVisible(false); - } - } - // we don't show the header when the floater is hosted, so reshape floater contents // to occupy the header space. - LLRect floater_rect = getRect(); - contents_rect.setOriginAndSize( - contents_rect.mLeft, - contents_rect.mBottom, - floater_rect.getWidth(), - floater_rect.getHeight()); + contents_rect.mTop += getHeaderHeight(); } else { @@ -253,6 +244,30 @@ void LLIMConversation::updateHeaderAndToolbar() floater_contents->setShape(contents_rect); } +} + +void LLIMConversation::hideAllStandardButtons() +{ + for (S32 i = 0; i < BUTTON_COUNT; i++) + { + if (mButtons[i]) + { + // Hide the standard header buttons in a docked IM floater. + mButtons[i]->setVisible(false); + } + } +} + +void LLIMConversation::updateHeaderAndToolbar() +{ + bool is_hosted = getHost() != NULL; + + if (is_hosted) + { + hideAllStandardButtons(); + } + + hideOrShowTitle(); // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 19d1e523f0..e6b4f534cc 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -89,6 +89,9 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); + void hideOrShowTitle(); + void hideAllStandardButtons(); + bool mIsNearbyChat; bool mIsP2PChat; bool mWasHosted; -- cgit v1.2.3 From d2801da16f9ce6addf6d34b3532a574e24f5d9be Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Tue, 17 Jul 2012 14:34:35 -0400 Subject: SH-3258 WIP revert to server-generated textures After exiting appearance mode, next server-generated appearance message should over-ride the locally-generated textures. --- indra/newview/llvoavatar.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 236cc1b089..d953a4b99e 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4581,6 +4581,7 @@ void LLVOAvatar::updateTextures() if (isIndexBakedTexture((ETextureIndex)texture_index) && imagep->getID() != IMG_DEFAULT_AVATAR && imagep->getID() != IMG_INVISIBLE + && !LLAppearanceMgr::instance().useServerTextureBaking() && !imagep->getTargetHost().isOk()) { LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " @@ -7363,7 +7364,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } setCompositeUpdatesEnabled( FALSE ); - mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); // parse visual params @@ -7475,6 +7475,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // If all of the avatars are completely baked, release the global image caches to conserve memory. LLVOAvatar::cullAvatarsByPixelArea(); + if (isSelf() && LLAppearanceMgr::instance().useServerTextureBaking()) + { + mUseLocalAppearance = false; + } + + updateMeshTextures(); + // llinfos << "processAvatarAppearance end " << mID << llendl; } -- cgit v1.2.3 From ec4d1a2450807afcff5c0f0ebf651c9e67f1b310 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 17 Jul 2012 12:07:25 -0700 Subject: CHUI-234 : Fix crashers in landmarks panel --- indra/newview/llpanellandmarks.cpp | 2 +- indra/newview/llplacesinventorypanel.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index faef923338..4bbab52e5a 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -651,7 +651,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI // Start background fetch, mostly for My Inventory and Library if (expanded) { - const LLUUID &cat_id = mCurrentSelectedList->getRootFolderID(); + const LLUUID &cat_id = inventory_list->getRootFolderID(); // Just because the category itself has been fetched, doesn't mean its child folders have. /* if (!gInventory.isCategoryComplete(cat_id)) diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index d95d5eac19..65d9691902 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -93,6 +93,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par p.parent_panel = this; p.allow_multiselect = mAllowMultiSelect; p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller + p.view_model = &mInventoryViewModel; mFolderRoot = LLUICtrlFactory::create(p); } -- cgit v1.2.3 From 15f6f877f923ecc85489c0159ca62deb02de1201 Mon Sep 17 00:00:00 2001 From: merov_linden Date: Thu, 19 Jul 2012 03:57:24 +0100 Subject: CHUI-236 : WIP : Modify the handling of FT_ROOT_INVENTORY which was creating havoc in LLInventoryModel instantiation. Still, some of those hack will have to come back on. --- indra/newview/llinventorymodel.cpp | 37 ++++++++++++++++---------------- indra/newview/llplacesinventorypanel.cpp | 37 +------------------------------- 2 files changed, 20 insertions(+), 54 deletions(-) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9b0d12b353..3250d60179 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -210,7 +210,7 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons if (!cat) break; const LLFolderType::EType folder_type = cat->getPreferredType(); if (folder_type != LLFolderType::FT_NONE && - folder_type != LLFolderType::FT_ROOT_INVENTORY && +// folder_type != LLFolderType::FT_ROOT_INVENTORY && !LLFolderType::lookupIsEnsembleType(folder_type)) { return cat; @@ -380,11 +380,12 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe LLUUID rv = LLUUID::null; const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); - if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) - { - rv = root_id; - } - else if (root_id.notNull()) +// if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) +// { +// rv = root_id; +// } +// else if (root_id.notNull()) + if (root_id.notNull()) { cat_array_t* cats = NULL; cats = get_ptr_in_map(mParentChildCategoryTree, root_id); @@ -2026,11 +2027,11 @@ void LLInventoryModel::buildParentChildMap() { cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); } - else if(LLFolderType::FT_ROOT_INVENTORY == pref) - { +// else if(LLFolderType::FT_ROOT_INVENTORY == pref) +// { // it's the root - cat->setParent(LLUUID::null); - } +// cat->setParent(LLUUID::null); +// } else { // it's a protected folder. @@ -2160,14 +2161,14 @@ void LLInventoryModel::buildParentChildMap() if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) continue; - if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) - { - if(category->getUUID()!=mRootFolderID) - { - LLUUID& new_inv_root_folder_id = const_cast(mRootFolderID); - new_inv_root_folder_id = category->getUUID(); - } - } +// if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) +// { +// if(category->getUUID()!=mRootFolderID) +// { +// LLUUID& new_inv_root_folder_id = const_cast(mRootFolderID); +// new_inv_root_folder_id = category->getUUID(); +// } +// } } } diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 65d9691902..c46681f556 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -60,44 +60,9 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel() void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) { - // Determine the root folder in case specified, and - // build the views starting with that folder. - const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder); - - LLUUID root_id; - - if ("LIBRARY" == params.start_folder()) - { - root_id = gInventory.getLibraryRootFolderID(); - } - else - { - root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); - } - - LLRect folder_rect(0, - 0, - getRect().getWidth(), - 0); - LLPlacesFolderView::Params p; - p.name = getName(); - p.title = getLabel(); - p.rect = folder_rect; - p.listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, - LLAssetType::AT_CATEGORY, - LLInventoryType::IT_CATEGORY, - this, - &mInventoryViewModel, - NULL, - root_id); - p.parent_panel = this; - p.allow_multiselect = mAllowMultiSelect; - p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller - p.view_model = &mInventoryViewModel; - mFolderRoot = LLUICtrlFactory::create(p); + LLInventoryPanel::buildFolderView(params); } - // save current folder open state void LLPlacesInventoryPanel::saveFolderState() { -- cgit v1.2.3 From efa73d4975afda19ee5255d5cca33fa96fc21eb4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 19 Jul 2012 20:38:07 -0700 Subject: CHUI-236 : WIP : Places panel works for My Inventory but still empty lists for Favorites Bar, My Landmarks and Library. --- indra/newview/llinventorymodel.cpp | 37 ++++++++++++++++++------------------- indra/newview/llinventorypanel.cpp | 25 +++++++++++-------------- indra/newview/llinventorypanel.h | 1 - 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3250d60179..9b0d12b353 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -210,7 +210,7 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons if (!cat) break; const LLFolderType::EType folder_type = cat->getPreferredType(); if (folder_type != LLFolderType::FT_NONE && -// folder_type != LLFolderType::FT_ROOT_INVENTORY && + folder_type != LLFolderType::FT_ROOT_INVENTORY && !LLFolderType::lookupIsEnsembleType(folder_type)) { return cat; @@ -380,12 +380,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe LLUUID rv = LLUUID::null; const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); -// if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) -// { -// rv = root_id; -// } -// else if (root_id.notNull()) - if (root_id.notNull()) + if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) + { + rv = root_id; + } + else if (root_id.notNull()) { cat_array_t* cats = NULL; cats = get_ptr_in_map(mParentChildCategoryTree, root_id); @@ -2027,11 +2026,11 @@ void LLInventoryModel::buildParentChildMap() { cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); } -// else if(LLFolderType::FT_ROOT_INVENTORY == pref) -// { + else if(LLFolderType::FT_ROOT_INVENTORY == pref) + { // it's the root -// cat->setParent(LLUUID::null); -// } + cat->setParent(LLUUID::null); + } else { // it's a protected folder. @@ -2161,14 +2160,14 @@ void LLInventoryModel::buildParentChildMap() if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) continue; -// if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) -// { -// if(category->getUUID()!=mRootFolderID) -// { -// LLUUID& new_inv_root_folder_id = const_cast(mRootFolderID); -// new_inv_root_folder_id = category->getUUID(); -// } -// } + if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) + { + if(category->getUUID()!=mRootFolderID) + { + LLUUID& new_inv_root_folder_id = const_cast(mRootFolderID); + new_inv_root_folder_id = category->getUUID(); + } + } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index ed370e9add..340f851ed8 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -193,6 +193,15 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { + // Clear up the root view + // Note: This needs to be done *before* we build the new folder view + LLFolderViewItem* root_view = getItemByID(gInventory.getRootFolderID()); + if (root_view) + { + removeItemID(static_cast(root_view->getViewModelItem())->getUUID()); + root_view->destroyView(); + } + LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves @@ -228,6 +237,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { initializeViews(); } + gIdleCallbacks.addFunction(onIdle, (void*)this); if (mSortOrderSetting != INHERIT_SORT_ORDER) @@ -595,7 +605,7 @@ void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; - rebuildViewsFor(gInventory.getRootFolderID()); + buildNewViews(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(idle, this); @@ -622,19 +632,6 @@ void LLInventoryPanel::initializeViews() } } -LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ - // Destroy the old view for this ID so we can rebuild it. - LLFolderViewItem* old_view = getItemByID(id); - if (old_view) - { - old_view->destroyView(); - removeItemID(static_cast(old_view->getViewModelItem())->getUUID()); - } - - return buildNewViews(id); -} - LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix) { LLRect folder_rect(0, diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 465ccdd582..4fcc93b0c4 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -237,7 +237,6 @@ public: protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); - LLFolderViewItem* rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views. virtual void buildFolderView(const LLInventoryPanel::Params& params); LLFolderViewItem* buildNewViews(const LLUUID& id); -- cgit v1.2.3 From 6227a5c273efbe732c8068400d7e4b5486981bba Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 19 Jul 2012 19:16:36 +0300 Subject: CHUI-231, CHUI-233 [FIXED] - Modified and simplified algorithm of reshaping floater's body (content) and showing/hiding of the title for prevent of present and future issues with floater's repositioning --- indra/newview/llimconversation.cpp | 32 ++++++++-------------- indra/newview/llimconversation.h | 3 +- .../skins/default/xui/en/floater_im_session.xml | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ec7e0ee6cb..ec534b903d 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -43,7 +43,6 @@ const F32 REFRESH_INTERVAL = 0.2f; LLIMConversation::LLIMConversation(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id) , mIsP2PChat(false) - , mWasHosted(false) , mExpandCollapseBtn(NULL) , mTearOffBtn(NULL) , mCloseBtn(NULL) @@ -224,26 +223,17 @@ void LLIMConversation::hideOrShowTitle() { bool is_hosted = getHost() != NULL; - if (mWasHosted != is_hosted) - { - mWasHosted = is_hosted; - LLView* floater_contents = getChild("contents_view"); - LLRect contents_rect = floater_contents->getRect(); - - if (is_hosted) - { - // we don't show the header when the floater is hosted, so reshape floater contents - // to occupy the header space. - contents_rect.mTop += getHeaderHeight(); - } - else - { - // reduce the floater contents height by header height - contents_rect.mTop -= getHeaderHeight(); - } - - floater_contents->setShape(contents_rect); - } + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; + LLView* floater_contents = getChild("contents_view"); + + LLRect floater_rect = getLocalRect(); + S32 top_border_of_contents = floater_rect.mTop - (is_hosted? 0 : floater_header_size); + LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); + LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); + mDragHandle->setShape(handle_rect); + mDragHandle->setVisible(! is_hosted); + floater_contents->setShape(contents_rect); } void LLIMConversation::hideAllStandardButtons() diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index e6b4f534cc..c3dff96d5d 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -89,12 +89,11 @@ protected: void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); - void hideOrShowTitle(); + void hideOrShowTitle(); // toggle the floater's drag handle void hideAllStandardButtons(); bool mIsNearbyChat; bool mIsP2PChat; - bool mWasHosted; LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 95f6708e96..560e1be213 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,7 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" - save_rect="true" + save_rect="false" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From 7c9be0e3de6821478c71e4646f07fb112e0e572c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 19 Jul 2012 15:11:56 +0300 Subject: CHUI-229 [FIXED] Nearby chat conversation does not appear initially in conversation list if no other conversations are present --- indra/newview/llimfloater.cpp | 8 +++--- indra/newview/llimfloatercontainer.cpp | 48 ++++++++++++++++++---------------- indra/newview/llimfloatercontainer.h | 1 + indra/newview/llnearbychat.cpp | 8 +++--- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 23c97c5345..22ce3cd42b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -346,6 +346,10 @@ BOOL LLIMFloater::postBuild() initIMFloater(); + // Add a conversation list item in the left pane + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + im_box->addConversationListItem(getTitle(), getKey(), this); + return TRUE; } @@ -641,10 +645,6 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } - // Add a conversation list item in the left pane: nothing will be done if already in there - // but relevant clean up will be done to ensure consistency of the conversation list - floater_container->addConversationListItem(floater->getTitle(), session_id, floater); - floater->openFloater(floater->getKey()); } else diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4f626cb5d2..005794444b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -150,9 +150,6 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); LLUUID session_id = floaterp->getKey(); - - // Add a conversation list item in the left pane - addConversationListItem(floaterp->getTitle(), session_id, floaterp); LLIconCtrl* icon = 0; @@ -280,6 +277,8 @@ void LLIMFloaterContainer::draw() collapseMessagesPane(true); } LLFloater::draw(); + + repositioningWidgets(); } void LLIMFloaterContainer::tabClose() @@ -306,7 +305,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) LLFloaterReg::toggleInstanceOrBringToFront(name); } } - + // We need to show/hide all the associated conversations that have been torn off // (and therefore, are not longer managed by the multifloater), // so that they show/hide with the conversations manager. @@ -409,6 +408,23 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } } +void LLIMFloaterContainer::repositioningWidgets() +{ + LLRect panel_rect = mConversationsListPanel->getRect(); + S32 item_height = 16; + int index = 0; + for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + widget_it != mConversationsWidgets.end(); + widget_it++, ++index) + { + LLFolderViewItem* widget = widget_it->second; + widget->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + } +} + // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) { @@ -443,14 +459,11 @@ void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUI // Add it to the UI widget->setVisible(TRUE); + + repositioningWidgets(); + mConversationsListPanel->addChild(widget); - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - S32 index = mConversationsWidgets.size() - 1; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); + return; } @@ -470,18 +483,7 @@ void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool mConversationsItems.erase(floaterp); mConversationsWidgets.erase(floaterp); - // Reposition the leftover conversation items - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - int index = 0; - for (widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it, ++index) - { - LLFolderViewItem* widget = widget_it->second; - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - } + repositioningWidgets(); // Don't let the focus fall IW, select and refocus on the first conversation in the list if (change_focus) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index b624b7558a..a25ea0ab46 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -254,6 +254,7 @@ private: void collapseConversationsPane(bool collapse); void updateState(bool collapse, S32 delta_width); + void repositioningWidgets(); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 1c81cdc4bc..a21690bed8 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -158,7 +158,7 @@ BOOL LLNearbyChat::postBuild() enableResizeCtrls(true, true, false); - // title must be defined BEFORE call addToHost() because + // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list setTitle(getString("NearbyChatTitle")); @@ -186,6 +186,9 @@ BOOL LLNearbyChat::postBuild() loadHistory(); } + // added row in the conversations list when nearby chat is tear-off + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + im_box->addConversationListItem(getTitle(), LLSD(), this); return LLIMConversation::postBuild(); } @@ -363,9 +366,6 @@ void LLNearbyChat::addToHost() LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); if (im_box) { - // Make sure the Nearby Chat is present in the conversations list - im_box->addConversationListItem(getTitle(), getKey(), this); - if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { im_box->addFloater(this, TRUE, LLTabContainer::END); -- cgit v1.2.3 From 3ae21b429e67faf4ee32c9387c63a552b883a472 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 20 Jul 2012 17:16:22 +0300 Subject: CHUI-207 FIXED Emptying Lost and Found and Trash in inventory crashes viewer --- indra/newview/llinventorymodel.cpp | 23 +++++++++++++++++++++-- indra/newview/llinventorypanel.cpp | 13 ++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9b0d12b353..fe65b87afd 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1240,14 +1240,33 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) items, INCLUDE_TRASH); S32 count = items.count(); + + item_map_t::iterator item_map_end = mItemMap.end(); + cat_map_t::iterator cat_map_end = mCategoryMap.end(); + LLUUID uu_id; + for(S32 i = 0; i < count; ++i) { - deleteObject(items.get(i)->getUUID()); + uu_id = items.get(i)->getUUID(); + + // This check prevents the deletion of a previously deleted item. + // This is necessary because deletion is not done in a hierarchical + // order. The current item may have been already deleted as a child + // of its deleted parent. + if (mItemMap.find(uu_id) != item_map_end) + { + deleteObject(uu_id); + } } + count = categories.count(); for(S32 i = 0; i < count; ++i) { - deleteObject(categories.get(i)->getUUID()); + uu_id = categories.get(i)->getUUID(); + if (mCategoryMap.find(uu_id) != cat_map_end) + { + deleteObject(uu_id); + } } } } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 340f851ed8..6a7ee3b6a0 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -421,7 +421,14 @@ void LLInventoryPanel::modelChanged(U32 mask) // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. - LLFolderViewFolder* view_folder = dynamic_cast(view_item); + LLFolderViewFolder* view_folder = NULL; + + // Check requires as this item might have already been deleted + // as a child of its deleted parent. + if (model_item && view_item) + { + view_folder = dynamic_cast(view_item); + } ////////////////////////////// // LABEL Operation @@ -448,7 +455,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (mask & LLInventoryObserver::REBUILD) { handled = true; - if (model_item && view_item) + if (model_item && view_item && viewmodel_item) { view_item->destroyView(); removeItemID(viewmodel_item->getUUID()); @@ -538,7 +545,7 @@ void LLInventoryPanel::modelChanged(U32 mask) ////////////////////////////// // REMOVE Operation // This item has been removed from memory, but its associated UI element still exists. - else if (!model_item && view_item) + else if (!model_item && view_item && viewmodel_item) { // Remove the item's UI. removeItemID(viewmodel_item->getUUID()); -- cgit v1.2.3 From 176b7d82be3b48344e2a54f81402352273719108 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 23 Jul 2012 19:33:39 -0700 Subject: CHUI-227 FIX Teleport offers sent are not received cleaned up serialization of LLSD to param block so that it can round-trip also, optimized LLXMLNode and fixed an assert --- indra/llui/llnotifications.cpp | 10 +---- indra/llui/llsdparam.cpp | 33 +++++----------- indra/llxml/llxmlnode.cpp | 87 +++++++++--------------------------------- indra/llxml/llxmlnode.h | 5 +-- indra/llxuixml/llinitparam.cpp | 5 --- indra/llxuixml/llinitparam.h | 31 ++++++++++++--- indra/llxuixml/llxuiparser.cpp | 12 +++++- 7 files changed, 66 insertions(+), 117 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 48128e0b40..7e1e2c3c9b 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -223,14 +223,6 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica LLParamSDParser parser; parser.writeSD(mFormData, p.form_elements); - if (!mFormData.isArray() && !mFormData.isUndefined()) - { - // change existing contents to a one element array - LLSD new_llsd_array = LLSD::emptyArray(); - new_llsd_array.append(mFormData); - mFormData = new_llsd_array; - } - for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray(); it != end_it; ++it) @@ -516,7 +508,7 @@ LLSD LLNotification::asLLSD() p.id = mId; p.name = mTemplatep->mName; p.form_elements = getForm()->asLLSD(); - + p.substitutions = mSubstitutions; p.payload = mPayload; p.time_stamp = mTimestamp; diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 811e20e810..5a0d688f4f 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: { bool new_traversal = it->second; - LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; - - if (child_sd->isArray()) + LLSD* child_sd; + if (it->first.empty()) { + child_sd = sd_to_write; + if (child_sd->isUndefined()) + { + *child_sd = LLSD::emptyArray(); + } if (new_traversal) { // write to new element at end @@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: } else { - if (new_traversal - && child_sd->isDefined() - && !child_sd->isArray()) - { - // copy child contents into first element of an array - LLSD new_array = LLSD::emptyArray(); - new_array.append(*child_sd); - // assign array to slot that previously held the single value - *child_sd = new_array; - // return next element in that array - sd_to_write = &((*child_sd)[1]); - } - else - { - sd_to_write = child_sd; - } + sd_to_write = &(*sd_to_write)[it->first]; } it->second = false; } @@ -283,11 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI it != sd.endArray(); ++it) { - if (!stack.empty()) - { - stack.back().second = true; - } + stack.push_back(make_pair(std::string(), true)); readSDValues(cb, *it, stack); + stack.pop_back(); } } else if (sd.isUndefined()) diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 2ffb0d8503..45839595a0 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -259,7 +259,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) return FALSE; } -void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) +void LLXMLNode::addChild(LLXMLNodePtr& new_child) { if (new_child->mParent != NULL) { @@ -273,6 +273,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) new_child->mParent = this; if (new_child->mIsAttribute) { + LLXMLAttribList::iterator found_it = mAttributes.find(new_child->mName); + if (found_it != mAttributes.end()) + { + removeChild(found_it->second); + } mAttributes.insert(std::make_pair(new_child->mName, new_child)); } else @@ -285,49 +290,11 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) } mChildren->map.insert(std::make_pair(new_child->mName, new_child)); - // if after_child is specified, it damn well better be in the list of children - // for this node. I'm not going to assert that, because it would be expensive, - // but don't specify that parameter if you didn't get the value for it from the - // list of children of this node! - if (after_child.isNull()) - { - if (mChildren->tail != new_child) - { - mChildren->tail->mNext = new_child; - new_child->mPrev = mChildren->tail; - mChildren->tail = new_child; - } - } - // if after_child == parent, then put new_child at beginning - else if (after_child == this) - { - // add to front of list - new_child->mNext = mChildren->head; - if (mChildren->head) - { - mChildren->head->mPrev = new_child; - mChildren->head = new_child; - } - else // no children - { - mChildren->head = new_child; - mChildren->tail = new_child; - } - } - else + if (mChildren->tail != new_child) { - if (after_child->mNext.notNull()) - { - // if after_child was not the last item, fix up some pointers - after_child->mNext->mPrev = new_child; - new_child->mNext = after_child->mNext; - } - new_child->mPrev = after_child; - after_child->mNext = new_child; - if (mChildren->tail == after_child) - { - mChildren->tail = new_child; - } + mChildren->tail->mNext = new_child; + new_child->mPrev = mChildren->tail; + mChildren->tail = new_child; } } @@ -343,8 +310,9 @@ LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute) // virtual LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute) { - LLXMLNode* ret = new LLXMLNode(name, is_attribute); + LLXMLNodePtr ret(new LLXMLNode(name, is_attribute)); ret->mID.clear(); + addChild(ret); return ret; } @@ -358,11 +326,12 @@ BOOL LLXMLNode::deleteChild(LLXMLNode *child) return FALSE; } -void LLXMLNode::setParent(LLXMLNodePtr new_parent) +void LLXMLNode::setParent(LLXMLNodePtr& new_parent) { if (new_parent.notNull()) { - new_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + new_parent->addChild(this_ptr); } else { @@ -681,27 +650,6 @@ bool LLXMLNode::updateNode( return TRUE; } - -// static -LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node) -{ - if (!node || !update_node) - { - llwarns << "Node invalid" << llendl; - return node; - } - - LLXMLNodePtr cloned_node = update_node->deepCopy(); - node->mParent->addChild(cloned_node, node); // add after node - LLXMLNodePtr parent = node->mParent; - parent->removeChild(node); - parent->updateDefault(); - - return cloned_node; -} - - - // static bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree) { @@ -1198,7 +1146,7 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree) std::vector::iterator itor3; for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) { - (*itor3)->setParent(NULL); + (*itor3)->setParent(LLXMLNodePtr()); } } } @@ -2733,7 +2681,8 @@ void LLXMLNode::setName(LLStringTableEntry* name) mName = name; if (old_parent) { - old_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + old_parent->addChild(this_ptr); } } diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index e3da7169e7..ec486d7957 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -127,8 +127,8 @@ public: BOOL isNull(); BOOL deleteChild(LLXMLNode* child); - void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL)); - void setParent(LLXMLNodePtr new_parent); // reparent if necessary + void addChild(LLXMLNodePtr& new_child); + void setParent(LLXMLNodePtr& new_parent); // reparent if necessary // Serialization static bool parseFile( @@ -147,7 +147,6 @@ public: static bool updateNode( LLXMLNodePtr& node, LLXMLNodePtr& update_node); - static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node); static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector& paths); diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index 3c0d0aaa7e..bb160b3c0b 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -227,12 +227,7 @@ namespace LLInitParam if (serialize_func) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - // each param descriptor remembers its serial number - // so we can inspect the same param under different names - // and see that it has the same number - name_stack.push_back(std::make_pair("", true)); serialize_func(*param, parser, name_stack, diff_param); - name_stack.pop_back(); } } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index d44ccac6e4..606676be2c 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1317,10 +1317,18 @@ namespace LLInitParam static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast(param); value_t value; + + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + ++new_name_stack_range.first; + } + // no further names in stack, attempt to parse value now - if (name_stack_range.first == name_stack_range.second) + if (new_name_stack_range.first == new_name_stack_range.second) { // attempt to read value directly if (parser.readValue(value)) @@ -1353,14 +1361,14 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { std::string key = it->getValueName(); - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); if(key.empty()) // not parsed via name values, write out value directly @@ -1382,6 +1390,8 @@ namespace LLInitParam break; } } + + name_stack.pop_back(); } } @@ -1519,9 +1529,16 @@ namespace LLInitParam static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast(param); bool new_value = false; + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + new_value |= new_name_stack_range.first->second; + ++new_name_stack_range.first; + } if (new_name || typed_param.mValues.empty()) { new_value = true; @@ -1531,7 +1548,7 @@ namespace LLInitParam param_value_t& value = typed_param.mValues.back(); // attempt to parse block... - if(value.deserializeBlock(parser, name_stack_range, new_name)) + if(value.deserializeBlock(parser, new_name_stack_range, new_name)) { typed_param.setProvided(); return true; @@ -1564,13 +1581,13 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); std::string key = it->getValueName(); if (!key.empty()) @@ -1583,6 +1600,8 @@ namespace LLInitParam { it->serializeBlock(parser, name_stack, NULL); } + + name_stack.pop_back(); } } diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index 9cd88a1620..3ad5ad7d42 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -621,7 +621,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd"); // add to front of schema - mSchemaNode->addChild(nodep, mSchemaNode); + mSchemaNode->addChild(nodep); } for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); @@ -877,16 +877,24 @@ LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack) it = next_it) { ++next_it; + bool force_new_node = false; + if (it->first.empty()) { it->second = false; continue; } + if (next_it != stack.end() && next_it->first.empty() && next_it->second) + { + force_new_node = true; + } + + out_nodes_t::iterator found_it = mOutNodes.find(it->first); // node with this name not yet written - if (found_it == mOutNodes.end() || it->second) + if (found_it == mOutNodes.end() || it->second || force_new_node) { // make an attribute if we are the last element on the name stack bool is_attribute = next_it == stack.end(); -- cgit v1.2.3 From 0a28a63ce05755d22b09badc41bdd23d5baab1bb Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 24 Jul 2012 12:03:00 -0700 Subject: fix for gcc builds --- indra/llxml/llxmlnode.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 45839595a0..afb0d87da9 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -147,13 +147,15 @@ LLXMLNodePtr LLXMLNode::deepCopy() for (LLXMLChildList::iterator iter = mChildren->map.begin(); iter != mChildren->map.end(); ++iter) { - newnode->addChild(iter->second->deepCopy()); + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); } } for (LLXMLAttribList::iterator iter = mAttributes.begin(); iter != mAttributes.end(); ++iter) { - newnode->addChild(iter->second->deepCopy()); + LLXMLNodePtr temp_ptr_for_gcc(iter->second->deepCopy()); + newnode->addChild(temp_ptr_for_gcc); } return newnode; @@ -1146,7 +1148,8 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree) std::vector::iterator itor3; for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) { - (*itor3)->setParent(LLXMLNodePtr()); + LLXMLNodePtr ptr; + (*itor3)->setParent(ptr); } } } -- cgit v1.2.3 From f303eeccf705f677e48c5738e5119352fd86b31d Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 24 Jul 2012 22:47:35 +0300 Subject: CHUI-209 FIX for properly updating folder names in folder view after they have been renamed. The old display name should be cleared before refreshing the views for both items and folders in folder view, otherwise the old name will be used upon renaming. --- indra/newview/llinventorybridge.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b4a91ca0f7..9997d1720f 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -81,7 +81,7 @@ public: // LLInvFVBridge functionality //-------------------------------------------------------------------- virtual const LLUUID& getUUID() const { return mUUID; } - virtual void clearDisplayName() {} + virtual void clearDisplayName() { mDisplayName.clear(); } virtual void restoreItem() {} virtual void restoreToWorld() {} @@ -229,8 +229,6 @@ public: virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } - /*virtual*/ void clearDisplayName() { mDisplayName.clear(); } - LLViewerInventoryItem* getItem() const; protected: -- cgit v1.2.3 From decd8a435d8fb15bab52eec9e447b176e33eb5cf Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 24 Jul 2012 14:42:28 -0700 Subject: CHUI-211: Problem was due to a non-heap variable being deleted and then referenced later (which was found by ProductEngine). Also the crash occurred at a specifc location llpangelobjectinventory::reset() during a static_cast, so now using a dynamic_cast as a safeguard. --- indra/llui/llfolderview.cpp | 3 ++- indra/newview/llpanelobjectinventory.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8ade17b763..10729a3eae 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -266,7 +266,8 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - delete mViewModel; + //product engine bugfix, prevent deletion of non-heap data + //delete mViewModel; mViewModel = NULL; } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ca20051a51..937d3bb8c5 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1565,7 +1565,12 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create(p); // this ensures that we never say "searching..." or "no items found" //TODO RN: make this happen by manipulating filter object directly - static_cast(mFolders->getFolderViewModel()->getFilter())->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + LLInventoryFilter* inventoryFilter = dynamic_cast(mFolders->getFolderViewModel()->getFilter()); + if(inventoryFilter) + { + inventoryFilter->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + } + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) -- cgit v1.2.3 From 1736c7b74e5291b1fee91ae72ff52391ae7d946f Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 24 Jul 2012 15:19:18 -0700 Subject: Backed out changeset: a20e437a726c --- indra/newview/llfolderviewmodelinventory.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index dff1e1be90..d23b4af8cb 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -158,20 +158,22 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite if (item->getLastFilterGeneration() < filter_generation) { - // recursive application of the filter for child items - item->filter( filter ); - if (item->getLastFilterGeneration() >= must_pass_generation && !item->passedFilter(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done + item->filter(filter); if (item->passedFilter()) { llerrs << "Invalid shortcut in inventory filtering!" << llendl; } item->setPassedFilter(false, false, filter_generation); } + else + { + item->filter( filter ); + } } // track latest generation to pass any child items, for each folder up to root -- cgit v1.2.3 From 891a09561d4dff23836c8618d481a6cd2dd001de Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 24 Jul 2012 20:29:20 -0700 Subject: CHUI-206 FIX Viewer crash when selecting to cut inventory item, then selecting to cut another inventory item Seems to work now, without filtering de-optimization --- indra/llui/llfolderview.cpp | 2 +- indra/newview/llfolderviewmodelinventory.cpp | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8ade17b763..943e690948 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1123,7 +1123,7 @@ void LLFolderView::paste() LLFolderViewFolder* folder = dynamic_cast(item); if (folder == NULL) { - item = item->getParentFolder(); + folder = item->getParentFolder(); } folder_set.insert(folder); } diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d23b4af8cb..faf5b3e7ac 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -163,11 +163,6 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - item->filter(filter); - if (item->passedFilter()) - { - llerrs << "Invalid shortcut in inventory filtering!" << llendl; - } item->setPassedFilter(false, false, filter_generation); } else -- cgit v1.2.3 From de8cd534b985450f6d9ff9d2ad947a2a110f76a8 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 25 Jul 2012 16:16:06 +0300 Subject: CHUI-230 [FIXED] Torn off conversation window size resizes when viewer window is resized --- indra/newview/llnearbychat.cpp | 10 ---------- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a21690bed8..4e53082c05 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -391,17 +391,7 @@ void LLNearbyChat::onOpen(const LLSD& key) bool LLNearbyChat::applyRectControl() { - bool is_torn_off = getHost() == NULL; - - // Resize is limited to torn off floaters. - // A hosted floater is not resizable. - if (is_torn_off) - { - enableResizeCtrls(true); - } - setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); - return LLFloater::applyRectControl(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 560e1be213..95f6708e96 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -9,7 +9,7 @@ can_dock="false" can_minimize="true" can_close="true" - save_rect="false" + save_rect="true" visible="false" width="394" can_resize="true" -- cgit v1.2.3 From 020980fb4cd5f2cc18b56fa795c08c153a15bd4a Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 25 Jul 2012 15:22:13 -0400 Subject: SH-3258 WIP Adding new switching of new vs old appearance based on appearance message Not all appearance messages on a region will be new or old style at all times. Thus we're using a specific flag to mark the new appearance messages. --- indra/newview/llvoavatar.cpp | 41 ++++++++++++++++++++++++++++------------- indra/newview/llvoavatar.h | 1 + 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d953a4b99e..45c7a59b24 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -192,6 +192,8 @@ const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const S32 SERVER_GENERATED_APPEARANCE = 359949045; + const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); enum ERenderName @@ -693,7 +695,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar")), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), - mUseLocalAppearance(FALSE) + mUseLocalAppearance(FALSE), + mUseServerBakes(TRUE) { LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune @@ -4581,7 +4584,7 @@ void LLVOAvatar::updateTextures() if (isIndexBakedTexture((ETextureIndex)texture_index) && imagep->getID() != IMG_DEFAULT_AVATAR && imagep->getID() != IMG_INVISIBLE - && !LLAppearanceMgr::instance().useServerTextureBaking() + && !mUseServerBakes && !imagep->getTargetHost().isOk()) { LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " @@ -4676,10 +4679,10 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel //the texture pipeline will stop fetching this texture. imagep->resetTextureStats(); - if (!LLAppearanceMgr::instance().useServerTextureBaking()) - { - imagep->setCanUseHTTP(false); //turn off http fetching for baked textures. - } + // TODO: currently default to HTTP texture and fall back to UDP if cannot be found there. + // Once server messaging is in place, we should call setCanUseHTTP(false) for old style + // appearance requests + imagep->setCanUseHTTP(true); imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; @@ -4730,6 +4733,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) if (texture_entry != NULL) { url = gSavedSettings.getString("AgentAppearanceServiceURL") + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); + //llinfos << "baked texture url: " << url << llendl; } } return url; @@ -7323,14 +7327,25 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, tec); // dumpAvatarTEs( "POST processAvatarAppearance()" ); + // Extract COF Version field hacked into local texture id. + LLUUID flags_id = ((LLUUID*)tec.image_data)[0]; + S32 this_update_cof_version = (flags_id.mData[0] << 24) + (flags_id.mData[1] << 16) +(flags_id.mData[2] << 8) +flags_id.mData[3]; + S32 message_type = (flags_id.mData[4] << 24) + (flags_id.mData[5] << 16) +(flags_id.mData[6] << 8) +flags_id.mData[7]; + + if (message_type == SERVER_GENERATED_APPEARANCE) + { + mUseServerBakes = true; + } + else + { + mUseServerBakes = false; + } + + S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion; + // Check for stale update. - if (isSelf() && LLAppearanceMgr::instance().useServerTextureBaking()) + if (isSelf() && mUseServerBakes) { - // Extract COF Version field hacked into local texture id. - LLUUID texture_id = ((LLUUID*)tec.image_data)[0]; - S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion; - S32 *s_words = (S32*) texture_id.mData; - S32 this_update_cof_version = s_words[0]; if ((this_update_cof_version > 0) && (this_update_cof_version < last_update_request_cof_version)) { @@ -7475,7 +7490,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // If all of the avatars are completely baked, release the global image caches to conserve memory. LLVOAvatar::cullAvatarsByPixelArea(); - if (isSelf() && LLAppearanceMgr::instance().useServerTextureBaking()) + if (isSelf()) { mUseLocalAppearance = false; } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 2b999891f9..4283c0e017 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -702,6 +702,7 @@ private: F32 mLastAppearanceBlendTime; BOOL mIsEditingAppearance; BOOL mUseLocalAppearance; + BOOL mUseServerBakes; //-------------------------------------------------------------------- // Clothing colors (convenience functions to access visual parameters) -- cgit v1.2.3 From c4f59fd5882d8b019830292e9e5ed1d2480f73ef Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 25 Jul 2012 14:30:17 -0700 Subject: CHUI-239 FIX Viewer crash when opening object with contents --- indra/newview/llfloatertools.cpp | 4 ++-- indra/newview/llfolderviewmodelinventory.cpp | 10 +++++----- indra/newview/llfolderviewmodelinventory.h | 10 +++------- indra/newview/llinventorybridge.cpp | 5 ++--- indra/newview/llinventorypanel.h | 1 + indra/newview/llpanelobjectinventory.cpp | 8 ++++++-- indra/newview/llpanelobjectinventory.h | 2 ++ indra/newview/llplacesinventorybridge.cpp | 2 -- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 6978e6a430..43465d4209 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -660,8 +660,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mBtnEdit ->setToggleState( edit_visible ); mRadioGroupEdit->setVisible( edit_visible ); - bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); - getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); + //bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); + //getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); mBtnLink->setVisible(edit_visible); mBtnUnlink->setVisible(edit_visible); diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index dff1e1be90..e8135496d5 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -109,7 +109,7 @@ bool LLFolderViewModelInventory::contentsReady() void LLFolderViewModelItemInventory::requestSort() { LLFolderViewModelItemCommon::requestSort(); - if (mRootViewModel->getSorter().isByDate()) + if (mRootViewModel.getSorter().isByDate()) { // sort by date potentially affects parent folders which use a date // derived from newest item in them @@ -123,14 +123,14 @@ void LLFolderViewModelItemInventory::requestSort() bool LLFolderViewModelItemInventory::potentiallyVisible() { return passedFilter() // we've passed the filter - || getLastFilterGeneration() < mRootViewModel->getFilter()->getFirstSuccessGeneration() // or we don't know yet + || getLastFilterGeneration() < mRootViewModel.getFilter()->getFirstSuccessGeneration() // or we don't know yet || descendantsPassedFilter(); } bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) { - if (filter_generation < 0 && mRootViewModel) - filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) + filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter && mLastFilterGeneration >= filter_generation @@ -139,7 +139,7 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) { - if (filter_generation < 0) filter_generation = mRootViewModel->getFilter()->getFirstSuccessGeneration(); + if (filter_generation < 0) filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mMostFilteredDescendantGeneration >= filter_generation; } diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 12a977b28b..eb2a4bfdec 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -37,13 +37,9 @@ class LLFolderViewModelItemInventory : public LLFolderViewModelItemCommon { public: - LLFolderViewModelItemInventory() - : mRootViewModel(NULL) + LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model) + : mRootViewModel(root_view_model) {} - void setRootViewModel(class LLFolderViewModelInventory* root_view_model) - { - mRootViewModel = root_view_model; - } virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual void setCreationDate(time_t creation_date_utc) = 0; @@ -70,7 +66,7 @@ public: virtual LLToolDragAndDrop::ESource getDragSource() const = 0; protected: - class LLFolderViewModelInventory* mRootViewModel; + class LLFolderViewModelInventory& mRootViewModel; }; class LLInventorySort diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d17c25d9f3..9f1d4bdec9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -190,7 +190,8 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, mUUID(uuid), mRoot(root), mInvType(LLInventoryType::IT_NONE), - mIsLink(FALSE) + mIsLink(FALSE), + LLFolderViewModelItemInventory(inventory->getRootViewModel()) { mInventoryPanel = inventory->getInventoryPanelHandle(); const LLInventoryObject* obj = getInventoryObject(); @@ -1158,7 +1159,6 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, if (new_listener) { new_listener->mInvType = inv_type; - new_listener->setRootViewModel(view_model); } return new_listener; @@ -6484,7 +6484,6 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( && actual_asset_type != LLAssetType::AT_LINK_FOLDER) { new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - new_listener->setRootViewModel(view_model); } else { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 4fcc93b0c4..910325cdbc 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -104,6 +104,7 @@ public: public: LLInventoryModel* getModel() { return mInventory; } + LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } // LLView methods void draw(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 937d3bb8c5..9bd716e900 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -155,7 +155,8 @@ LLTaskInvFVBridge::LLTaskInvFVBridge( LLPanelObjectInventory* panel, const LLUUID& uuid, const std::string& name, - U32 flags): + U32 flags) +: LLFolderViewModelItemInventory(panel->getRootViewModel()), mUUID(uuid), mName(name), mPanel(panel), @@ -1915,7 +1916,10 @@ void LLPanelObjectInventory::idle(void* user_data) { LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; - + if (self->mFolders) + { + self->mFolders->update(); + } if (self->mInventoryNeedsUpdate) { self->updateInventory(); diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 7e857f8b31..593fb43b6d 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -56,6 +56,8 @@ public: virtual BOOL postBuild(); + LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } + void doToSelected(const LLSD& userdata); void refresh(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index af29ab7ea9..1a5f64e295 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -165,7 +165,6 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << llendl; } new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, root, uuid, flags); - new_listener->setRootViewModel(view_model); break; case LLAssetType::AT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) @@ -183,7 +182,6 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( break; } new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid); - new_listener->setRootViewModel(view_model); break; default: new_listener = LLInventoryFVBridgeBuilder::createBridge( -- cgit v1.2.3 From f6dfd6bf0f3ea0e9b5f56a939867353c393539d6 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 25 Jul 2012 18:20:54 -0700 Subject: CHUI-222 FIX Selecting None in inventory filters does not update until inventory selected --- indra/llui/llfolderview.cpp | 2 - indra/llui/llfolderviewitem.cpp | 11 +++-- indra/llui/llfolderviewmodel.h | 4 +- indra/newview/llfolderviewmodelinventory.cpp | 74 +++++++++++++--------------- indra/newview/llfolderviewmodelinventory.h | 4 +- indra/newview/llimfloatercontainer.h | 2 +- indra/newview/llpanelobjectinventory.cpp | 2 +- 7 files changed, 49 insertions(+), 50 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 10729a3eae..147af04f30 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -266,8 +266,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - //product engine bugfix, prevent deletion of non-heap data - //delete mViewModel; mViewModel = NULL; } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 741fc9c324..a356d587f9 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1543,11 +1543,14 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) void LLFolderViewFolder::requestArrange() { - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) + //if ( mLastArrangeGeneration != -1) { - mParentFolder->requestArrange(); + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } } } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 268ae8eea8..acdec53602 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -152,7 +152,7 @@ public: virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? - virtual bool filter( LLFolderViewFilter& filter) = 0; + virtual void filter( LLFolderViewFilter& filter) = 0; virtual bool passedFilter(S32 filter_generation = -1) = 0; virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0; virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) = 0; @@ -192,6 +192,7 @@ public: : mSortVersion(-1), mPassedFilter(true), mPassedFolderFilter(true), + mPrevPassedAllFilters(false), mFolderViewItem(NULL), mLastFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), @@ -232,6 +233,7 @@ protected: S32 mSortVersion; bool mPassedFilter; bool mPassedFolderFilter; + bool mPrevPassedAllFilters; S32 mLastFilterGeneration; S32 mMostFilteredDescendantGeneration; diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index e8135496d5..13ca73917b 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -133,8 +133,9 @@ bool LLFolderViewModelItemInventory::passedFilter(S32 filter_generation) filter_generation = mRootViewModel.getFilter()->getFirstSuccessGeneration(); return mPassedFolderFilter - && mLastFilterGeneration >= filter_generation - && (mPassedFilter || descendantsPassedFilter(filter_generation)); + && (descendantsPassedFilter(filter_generation) + || (mLastFilterGeneration >= filter_generation + && mPassedFilter)); } bool LLFolderViewModelItemInventory::descendantsPassedFilter(S32 filter_generation) @@ -148,30 +149,29 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, bool passed_fo mPassedFilter = passed; mPassedFolderFilter = passed_folder; mLastFilterGeneration = filter_generation; + + bool passed_filter_before = mPrevPassedAllFilters; + mPrevPassedAllFilters = passedFilter(filter_generation); + + if (passed_filter_before != mPrevPassedAllFilters) + { + //TODO RN: ensure this still happens, but without dependency on folderview + LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); + if (parent_folder) + { + parent_folder->requestArrange(); + } + } } -bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +void LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) { - bool passed_filter_before = item->passedFilter(); S32 filter_generation = filter.getCurrentGeneration(); - S32 must_pass_generation = filter.getFirstRequiredGeneration(); if (item->getLastFilterGeneration() < filter_generation) { // recursive application of the filter for child items item->filter( filter ); - - if (item->getLastFilterGeneration() >= must_pass_generation - && !item->passedFilter(must_pass_generation)) - { - // failed to pass an earlier filter that was a subset of the current one - // go ahead and flag this item as done - if (item->passedFilter()) - { - llerrs << "Invalid shortcut in inventory filtering!" << llendl; - } - item->setPassedFilter(false, false, filter_generation); - } } // track latest generation to pass any child items, for each folder up to root @@ -184,39 +184,36 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite view_model->mMostFilteredDescendantGeneration = filter_generation; view_model = static_cast(view_model->mParent); } - - return !passed_filter_before; - } - else // !item->passedfilter() - { - return passed_filter_before; } } -bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +void LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) { - bool changed = false; + const S32 filter_generation = filter.getCurrentGeneration(); + const S32 must_pass_generation = filter.getFirstRequiredGeneration(); + + if (getLastFilterGeneration() >= must_pass_generation + && !passedFilter(must_pass_generation)) + { + // failed to pass an earlier filter that was a subset of the current one + // go ahead and flag this item as done + setPassedFilter(false, false, filter_generation); + return; + } if(!mChildren.empty() - && (getLastFilterGeneration() < filter.getFirstRequiredGeneration() // haven't checked descendants against minimum required generation to pass - || descendantsPassedFilter(filter.getFirstRequiredGeneration()))) // or at least one descendant has passed the minimum requirement + && (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass + || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement { // now query children - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end() && filter.getFilterCount() > 0; + for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); + iter != end_iter && filter.getFilterCount() > 0; ++iter) { - changed |= filterChildItem((*iter), filter); + filterChildItem((*iter), filter); } } - if (changed) - { - //TODO RN: ensure this still happens, but without dependency on folderview - LLFolderViewFolder* folder = static_cast(mFolderViewItem); - folder->requestArrange(); - } - // if we didn't use all filter iterations // that means we filtered all of our descendants // so filter ourselves now @@ -229,11 +226,10 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) ? filter.checkFolder(this) : true; - setPassedFilter(passed_filter, passed_filter_folder, filter.getCurrentGeneration()); + setPassedFilter(passed_filter, passed_filter_folder, filter_generation); //TODO RN: create interface for string highlighting //mStringMatchOffset = filter.getStringMatchOffset(this); } - return changed; } LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index eb2a4bfdec..ab67c93897 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -59,8 +59,8 @@ public: virtual bool passedFilter(S32 filter_generation = -1); virtual bool descendantsPassedFilter(S32 filter_generation = -1); virtual void setPassedFilter(bool filtered, bool filtered_folder, S32 filter_generation); - virtual bool filter( LLFolderViewFilter& filter); - virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + virtual void filter( LLFolderViewFilter& filter); + virtual void filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; virtual LLToolDragAndDrop::ESource getDragSource() const = 0; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a25ea0ab46..7005ab7b6a 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -89,7 +89,7 @@ public: virtual bool hasChildren() const { return FALSE; } virtual bool potentiallyVisible() { return true; } - virtual bool filter( LLFolderViewFilter& filter) { return true; } + virtual void filter( LLFolderViewFilter& filter) { } virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } virtual void setPassedFilter(bool passed, bool passed_folder, S32 filter_generation) { } virtual bool passedFilter(S32 filter_generation = -1) { return true; } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 9bd716e900..4719191231 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1616,7 +1616,7 @@ void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object, iter != inventory->end(); ) { LLInventoryObject* item = *iter++; - LLFloaterProperties* floater = LLFloaterReg::findTypedInstance("properites", item->getUUID()); + LLFloaterProperties* floater = LLFloaterReg::findTypedInstance("properties", item->getUUID()); if(floater) { floater->refresh(); -- cgit v1.2.3 From 69b57d4ac075db855d88c2ff0e8c580e9e41ebf7 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 25 Jul 2012 19:54:39 -0700 Subject: CHUI-252 FIX Deleting an item from object contents in build tools crashes viewer also improved selection behavior for object contents when deleting/adding items --- indra/llui/llhandle.h | 13 +++---- indra/newview/llpanelobjectinventory.cpp | 64 ++++++++++++++++++++++++++------ indra/newview/llpanelobjectinventory.h | 7 ++++ 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h index 37c657dd92..680a1a7f1d 100644 --- a/indra/llui/llhandle.h +++ b/indra/llui/llhandle.h @@ -158,13 +158,6 @@ public: return mHandle; } -protected: - typedef LLHandle handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider - } - template LLHandle getDerivedHandle(typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) const { @@ -173,6 +166,12 @@ protected: return downcast_handle; } +protected: + typedef LLHandle handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider + } private: mutable LLRootHandle mHandle; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 4719191231..473b5d9479 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1535,6 +1535,8 @@ void LLPanelObjectInventory::clearContents() LLToolDragAndDrop::getInstance()->endDrag(); } + clearItemIDs(); + if( mScroller ) { // removes mFolders @@ -1550,8 +1552,6 @@ void LLPanelObjectInventory::reset() { clearContents(); - //setBorderVisible(FALSE); - mCommitCallbackRegistrar.pushScope(); // push local callbacks LLRect dummy_rect(0, 1, 1, 0); @@ -1631,15 +1631,20 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << llendl; // We're still interested in this task's inventory. + std::vector selected_item_ids; std::set selected_items; BOOL inventory_has_focus = FALSE; - if (mHaveInventory) + if (mHaveInventory && mFolders) { selected_items = mFolders->getSelectionList(); inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders); } - - reset(); + for (std::set::iterator it = selected_items.begin(), end_it = selected_items.end(); + it != end_it; + ++it) + { + selected_item_ids.push_back(static_cast((*it)->getViewModelItem())->getUUID()); + } LLViewerObject* objectp = gObjectList.findObject(mTaskUUID); if (objectp) @@ -1647,10 +1652,11 @@ void LLPanelObjectInventory::updateInventory() LLInventoryObject* inventory_root = objectp->getInventoryRoot(); LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); - mHaveInventory = TRUE; if (inventory_root && !contents.empty()) { + reset(); + createFolderViews(inventory_root, contents); mIsInventoryEmpty = FALSE; mFolders->setEnabled(TRUE); @@ -1660,6 +1666,8 @@ void LLPanelObjectInventory::updateInventory() // TODO: create an empty inventory mIsInventoryEmpty = TRUE; } + + mHaveInventory = TRUE; } else { @@ -1669,11 +1677,12 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set::iterator selection_it; - BOOL first_item = TRUE; - for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + std::vector::iterator selection_it; + bool first_item = true; + for (selection_it = selected_item_ids.begin(); selection_it != selected_item_ids.end(); ++selection_it) { - LLFolderViewItem* selected_item = (*selection_it); + LLFolderViewItem* selected_item = getItemByID(*selection_it); + if (selected_item) { //HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1689,7 +1698,10 @@ void LLPanelObjectInventory::updateInventory() } } - mFolders->requestArrange(); + if (mFolders) + { + mFolders->requestArrange(); + } mInventoryNeedsUpdate = FALSE; // Edit menu handler is set in onFocusReceived } @@ -1761,6 +1773,7 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li view = LLUICtrlFactory::create (params); } view->addToFolder(folder); + addItemID(obj->getUUID(), view); } } @@ -1944,3 +1957,32 @@ void LLPanelObjectInventory::onFocusReceived() LLPanel::onFocusReceived(); } + + +LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) +{ + std::map::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) + { + return map_it->second; + } + + return NULL; +} + +void LLPanelObjectInventory::removeItemID( const LLUUID& id ) +{ + mItemMap.erase(id); +} + +void LLPanelObjectInventory::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ + mItemMap[id] = itemp; +} + +void LLPanelObjectInventory::clearItemIDs() +{ + mItemMap.clear(); +} + diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 593fb43b6d..f497c695b3 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -88,8 +88,15 @@ protected: LLInventoryObject* parent, LLFolderViewFolder* folder); void clearContents(); + LLFolderViewItem* getItemByID(const LLUUID& id); + + void addItemID( const LLUUID& id, LLFolderViewItem* itemp ); + void removeItemID(const LLUUID& id); + void clearItemIDs(); private: + std::map mItemMap; + LLScrollContainer* mScroller; LLFolderView* mFolders; -- cgit v1.2.3 From 88f259f7c1aefea197ae8b6c49a79de09feebf5b Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 25 Jul 2012 20:08:17 -0700 Subject: optimization of LLSD param parsing --- indra/llui/llsdparam.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 5a0d688f4f..54c8389772 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -305,6 +305,12 @@ namespace LLInitParam // block param interface bool ParamValue::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) { + if (name_stack.first == name_stack.second + && p.readValue(mValue)) + { + return true; + } + LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); LLSD::String string; @@ -325,7 +331,11 @@ namespace LLInitParam void ParamValue::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { - // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + // attempt to write LLSD out directly + if (!p.writeValue(mValue, name_stack)) + { + // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + } } } -- cgit v1.2.3 From 779d982717098e608285b171ac06f5b9f43a94a0 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 26 Jul 2012 16:30:27 -0700 Subject: made Deprecated params write-only --- indra/llxuixml/llinitparam.h | 36 ++++++++++++++++++++++++++++++++---- indra/newview/llinventoryfilter.cpp | 2 +- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 606676be2c..71cd550693 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -2015,10 +2015,12 @@ namespace LLInitParam } }; - class Deprecated : public Param + // can appear in data files, but will ignored during parsing + // cannot read or write in code + class Ignored : public Param { public: - explicit Deprecated(const char* name) + explicit Ignored(const char* name) : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); @@ -2049,8 +2051,34 @@ namespace LLInitParam } }; - // different semantics for documentation purposes, but functionally identical - typedef Deprecated Ignored; + // can appear in data files, or be written to in code, but data will be ignored + // cannot be read in code + class Deprecated : public Ignored + { + public: + explicit Deprecated(const char* name) : Ignored(name) {} + + // dummy writer interfaces + template + Deprecated& operator =(const T& val) + { + // do nothing + return *this; + } + + template + DERIVED_BLOCK& operator()(const T& val) + { + // do nothing + return static_cast(Param::enclosingBlock()); + } + + template + void set(const T& val, bool flag_as_provided = true) + { + // do nothing + } + }; public: static BlockDescriptor& getBlockDescriptor() diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3f38d80a39..3e14faa55e 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -89,7 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. - const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;; + const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { return passed_clipboard; -- cgit v1.2.3 From 5221e48ef64d3965f6d4d3dbf0f937982230d11c Mon Sep 17 00:00:00 2001 From: Todd Stinson Date: Thu, 26 Jul 2012 17:26:27 -0700 Subject: CHUI-251: Resetting the object inventory panel after deleting the last object. --- indra/newview/llpanelobjectinventory.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 473b5d9479..fe1ff01bc2 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1653,13 +1653,16 @@ void LLPanelObjectInventory::updateInventory() LLInventoryObject::object_list_t contents; objectp->getInventoryContents(contents); - if (inventory_root && !contents.empty()) + if (inventory_root) { reset(); + mIsInventoryEmpty = contents.empty(); + if (!mIsInventoryEmpty) + { - createFolderViews(inventory_root, contents); - mIsInventoryEmpty = FALSE; - mFolders->setEnabled(TRUE); + createFolderViews(inventory_root, contents); + mFolders->setEnabled(TRUE); + } } else { -- cgit v1.2.3 From 1e65ba1f909604b027cb7dee5631f698a9f550a8 Mon Sep 17 00:00:00 2001 From: Todd Stinson Date: Thu, 26 Jul 2012 18:57:54 -0700 Subject: CHUI-251: Adding back in the root 'Contents' folder under the Build floater Content tab. --- indra/newview/llpanelobjectinventory.cpp | 25 +++++++++++++++++-------- indra/newview/skins/default/xui/en/strings.xml | 3 --- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index fe1ff01bc2..5887f4d244 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1656,13 +1656,9 @@ void LLPanelObjectInventory::updateInventory() if (inventory_root) { reset(); - mIsInventoryEmpty = contents.empty(); - if (!mIsInventoryEmpty) - { - - createFolderViews(inventory_root, contents); - mFolders->setEnabled(TRUE); - } + mIsInventoryEmpty = FALSE; + createFolderViews(inventory_root, contents); + mFolders->setEnabled(TRUE); } else { @@ -1725,7 +1721,20 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); if(bridge) { - createViewsForCategory(&contents, inventory_root, mFolders); + LLFolderViewFolder::Params p; + p.name = inventory_root->getName(); + p.tool_tip = p.name; + p.root = mFolders; + p.listener = bridge; + + LLFolderViewFolder* new_folder = LLUICtrlFactory::create(p); + new_folder->addToFolder(mFolders); + new_folder->toggleOpen(); + + if (!contents.empty()) + { + createViewsForCategory(&contents, inventory_root, new_folder); + } } } diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7790a382d9..fff892af68 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2447,9 +2447,6 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale Debits [weekday,datetime,utc] [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc] - - Contents - Acquired Items Cancel -- cgit v1.2.3 From e9f640a26fd6c9219ba28336231621e2ad2558fc Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 27 Jul 2012 17:36:41 +0300 Subject: CHUI-198 FIXED (Hitting minimize option on conversations floater closes floater, not minimize) - Removed code which was hiding floater on minimizing floater. --- indra/newview/llimfloatercontainer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 005794444b..c19683b1c2 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -257,8 +257,6 @@ void LLIMFloaterContainer::setMinimized(BOOL b) if (isMinimized() == b) return; LLMultiFloater::setMinimized(b); - // Hide minimized floater (see EXT-5315) - setVisible(!b); if (isMinimized()) return; -- cgit v1.2.3 From f82d0b171964a0b24ab0eca64febc0c1e3821138 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 27 Jul 2012 17:51:40 +0300 Subject: CHUI-204 FIXED (Conversations panel can be re-sized too small with all conversations torn off) - Increased min width of conversations panel by 10 pixels --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 8e434b5848..e5ef80e352 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -33,7 +33,7 @@ auto_resize="true" height="430" name="conversations_layout_panel" - min_dim="41" + min_dim="51" width="268"> Date: Fri, 27 Jul 2012 22:25:17 +0300 Subject: CHUI-151 FIXED (Implement conversation log) A brief explanation of what have been implemented. More information can be found in comments. 1. Created conversation history viewer (llfloaterconversationpreview) 2. Created LLConversation and LLConversationLog classes which represent and hold data of conversations (llconversationlog) 3. Created LLConversationLogList and LLConversationLogListItem which are the visual representation of LLConversationLog and LLConversation respectively 4. Created LLFloaterConversationLog - which holds and displays LLConversationLogList --- indra/newview/CMakeLists.txt | 10 + indra/newview/app_settings/settings.xml | 22 ++ indra/newview/llappviewer.cpp | 4 + indra/newview/llconversationlog.cpp | 336 ++++++++++++++++ indra/newview/llconversationlog.h | 164 ++++++++ indra/newview/llconversationloglist.cpp | 422 +++++++++++++++++++++ indra/newview/llconversationloglist.h | 143 +++++++ indra/newview/llconversationloglistitem.cpp | 157 ++++++++ indra/newview/llconversationloglistitem.h | 77 ++++ indra/newview/llfloaterconversationlog.cpp | 127 +++++++ indra/newview/llfloaterconversationlog.h | 61 +++ indra/newview/llfloaterconversationpreview.cpp | 112 ++++++ indra/newview/llfloaterconversationpreview.h | 51 +++ indra/newview/llimfloater.cpp | 12 + indra/newview/llimfloater.h | 6 + indra/newview/llimview.cpp | 17 +- indra/newview/llimview.h | 10 +- indra/newview/llstartup.cpp | 3 + indra/newview/llviewerfloaterreg.cpp | 4 + indra/newview/llviewermessage.cpp | 5 +- indra/newview/llvoicevivox.cpp | 1 + .../default/xui/en/floater_conversation_log.xml | 84 ++++ .../xui/en/floater_conversation_preview.xml | 53 +++ .../skins/default/xui/en/floater_im_container.xml | 1 + .../default/xui/en/menu_conversation_log_gear.xml | 134 +++++++ .../default/xui/en/menu_conversation_log_view.xml | 37 ++ .../skins/default/xui/en/menu_participant_view.xml | 16 + .../xui/en/panel_conversation_log_list_item.xml | 108 ++++++ 28 files changed, 2167 insertions(+), 10 deletions(-) create mode 100644 indra/newview/llconversationlog.cpp create mode 100644 indra/newview/llconversationlog.h create mode 100644 indra/newview/llconversationloglist.cpp create mode 100644 indra/newview/llconversationloglist.h create mode 100644 indra/newview/llconversationloglistitem.cpp create mode 100644 indra/newview/llconversationloglistitem.h create mode 100644 indra/newview/llfloaterconversationlog.cpp create mode 100644 indra/newview/llfloaterconversationlog.h create mode 100644 indra/newview/llfloaterconversationpreview.cpp create mode 100644 indra/newview/llfloaterconversationpreview.h create mode 100644 indra/newview/skins/default/xui/en/floater_conversation_log.xml create mode 100644 indra/newview/skins/default/xui/en/floater_conversation_preview.xml create mode 100644 indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml create mode 100644 indra/newview/skins/default/xui/en/menu_conversation_log_view.xml create mode 100644 indra/newview/skins/default/xui/en/menu_participant_view.xml create mode 100644 indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b31b99f47c..3fe1aec5ff 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -130,6 +130,9 @@ set(viewer_SOURCE_FILES llcommandlineparser.cpp llcompilequeue.cpp llconfirmationmanager.cpp + llconversationlog.cpp + llconversationloglist.cpp + llconversationloglistitem.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -185,6 +188,8 @@ set(viewer_SOURCE_FILES llfloaterbuyland.cpp llfloatercamera.cpp llfloatercolorpicker.cpp + llfloaterconversationlog.cpp + llfloaterconversationpreview.cpp llfloaterdeleteenvpreset.cpp llfloaterdestinations.cpp llfloaterdisplayname.cpp @@ -687,6 +692,9 @@ set(viewer_HEADER_FILES llcommandlineparser.h llcompilequeue.h llconfirmationmanager.h + llconversationlog.h + llconversationloglist.h + llconversationloglistitem.h llcurrencyuimanager.h llcylinder.h lldateutil.h @@ -742,6 +750,8 @@ set(viewer_HEADER_FILES llfloaterbuyland.h llfloatercamera.h llfloatercolorpicker.h + llfloaterconversationlog.h + llfloaterconversationpreview.h llfloaterdeleteenvpreset.h llfloaterdestinations.h llfloaterdisplayname.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index da3ff2d1ee..7a5abba971 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10004,6 +10004,28 @@ Value 2 + CallLogSortOrder + + Comment + Specifies sort order for Call Log (0 = by name, 1 = by date) + Persist + 1 + Type + U32 + Value + 2 + + SortFriendsFirst + + Comment + Specifies whether friends will be sorted first in Call Log + Persist + 1 + Type + Boolean + Value + 1 + ShowPGSearchAll Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1174d108d2..fe3a1ebf65 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -59,6 +59,7 @@ #include "llares.h" #include "llcurl.h" #include "llcalc.h" +#include "llconversationlog.h" #include "lltexturestats.h" #include "lltexturestats.h" #include "llviewerwindow.h" @@ -1757,6 +1758,9 @@ bool LLAppViewer::cleanup() // save mute list. gMuteList used to also be deleted here too. LLMuteList::getInstance()->cache(gAgent.getID()); + //save call log list + LLConversationLog::instance().cache(); + if (mPurgeOnExit) { llinfos << "Purging all cache files on exit" << llendflush; diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp new file mode 100644 index 0000000000..df9350407d --- /dev/null +++ b/indra/newview/llconversationlog.cpp @@ -0,0 +1,336 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&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 "llagent.h" +#include "llconversationlog.h" +#include "lltrans.h" + +struct Conversation_params +{ + Conversation_params(time_t time) + : mTime(time), + mTimestamp(LLConversation::createTimestamp(time)) + {} + + time_t mTime; + std::string mTimestamp; + SessionType mConversationType; + std::string mConversationName; + std::string mHistoryFileName; + LLUUID mSessionID; + LLUUID mParticipantID; + bool mIsVoice; + bool mHasOfflineIMs; +}; + +/************************************************************************/ +/* LLConversation implementation */ +/************************************************************************/ + +LLConversation::LLConversation(const Conversation_params& params) +: mTime(params.mTime), + mTimestamp(params.mTimestamp), + mConversationType(params.mConversationType), + mConversationName(params.mConversationName), + mHistoryFileName(params.mHistoryFileName), + mSessionID(params.mSessionID), + mParticipantID(params.mParticipantID), + mIsVoice(params.mIsVoice), + mHasOfflineIMs(params.mHasOfflineIMs) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLIMModel::LLIMSession& session) +: mTime(time_corrected()), + mTimestamp(createTimestamp(mTime)), + mConversationType(session.mSessionType), + mConversationName(session.mName), + mHistoryFileName(session.mHistoryFileName), + mSessionID(session.mSessionID), + mParticipantID(session.mOtherParticipantID), + mIsVoice(session.mStartedAsIMCall), + mHasOfflineIMs(session.mHasOfflineMessage) +{ + setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLConversation& conversation) +{ + mTime = conversation.getTime(); + mTimestamp = conversation.getTimestamp(); + mConversationType = conversation.getConversationType(); + mConversationName = conversation.getConversationName(); + mHistoryFileName = conversation.getHistoryFileName(); + mSessionID = conversation.getSessionID(); + mParticipantID = conversation.getParticipantID(); + mIsVoice = conversation.isVoice(); + mHasOfflineIMs = conversation.hasOfflineMessages(); + + setListenIMFloaterOpened(); +} + +LLConversation::~LLConversation() +{ + mIMFloaterShowedConnection.disconnect(); +} + +void LLConversation::onIMFloaterShown(const LLUUID& session_id) +{ + if (mSessionID == session_id) + { + mHasOfflineIMs = false; + } +} + +// static +const std::string LLConversation::createTimestamp(const time_t& utc_time) +{ + std::string timeStr; + LLSD substitution; + substitution["datetime"] = (S32) utc_time; + + timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" + +LLTrans::getString ("TimeDay")+"]/[" + +LLTrans::getString ("TimeYear")+"] [" + +LLTrans::getString ("TimeHour")+"]:[" + +LLTrans::getString ("TimeMin")+"]"; + + + LLStringUtil::format (timeStr, substitution); + return timeStr; +} + +void LLConversation::setListenIMFloaterOpened() +{ + LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + + bool has_offline_ims = !mIsVoice && mHasOfflineIMs; + bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + + // we don't need to listen for im floater with this conversation is opened + // if floater is already opened or this conversation doesn't have unread offline messages + if (has_offline_ims && !ims_are_read) + { + mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); + } +} +/************************************************************************/ +/* LLConversationLog implementation */ +/************************************************************************/ + +LLConversationLog::LLConversationLog() +{ + loadFromFile(getFileName()); + + LLIMMgr::instance().addSessionObserver(this); + LLAvatarTracker::instance().addObserver(this); +} +void LLConversationLog::logConversation(const LLConversation& conversation) +{ + mConversations.push_back(conversation); + notifyObservers(); +} + +void LLConversationLog::removeConversation(const LLConversation& conversation) +{ + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == conversation.getSessionID() && conv_it->getTime() == conversation.getTime()) + { + mConversations.erase(conv_it); + notifyObservers(); + return; + } + } +} + +const LLConversation* LLConversationLog::getConversation(const LLUUID& session_id) +{ + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) + { + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } + } + + return NULL; +} + +void LLConversationLog::addObserver(LLConversationLogObserver* observer) +{ + mObservers.insert(observer); +} + +void LLConversationLog::removeObserver(LLConversationLogObserver* observer) +{ + mObservers.erase(observer); +} + +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + if (session) + { + LLConversation conversation(*session); + LLConversationLog::instance().logConversation(conversation); + } +} + +// LLFriendObserver +void LLConversationLog::changed(U32 mask) +{ + if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) + { + notifyObservers(); + } +} + +void LLConversationLog::cache() +{ + saveToFile(getFileName()); +} + +std::string LLConversationLog::getFileName() +{ + std::string agent_id_string; + gAgent.getID().toString(agent_id_string); + + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".call_log"; +} + +bool LLConversationLog::saveToFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "wb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + std::string participant_id; + std::string conversation_id; + + conversations_vec_t::const_iterator conv_it = mConversations.begin(); + for (; conv_it != mConversations.end(); ++conv_it) + { + conv_it->getSessionID().toString(conversation_id); + conv_it->getParticipantID().toString(participant_id); + + // examples of two file entries + // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| + // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| + + fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", + (S32)conv_it->getTime(), + (S32)conv_it->getConversationType(), + (S32)conv_it->isVoice(), + (S32)conv_it->hasOfflineMessages(), + conv_it->getConversationName().c_str(), + participant_id.c_str(), + conversation_id.c_str(), + conv_it->getHistoryFileName().c_str()); + } + fclose(fp); + return true; +} +bool LLConversationLog::loadFromFile(const std::string& filename) +{ + if(!filename.size()) + { + llwarns << "Call log list filename is empty!" << llendl; + return false; + } + + LLFILE* fp = LLFile::fopen(filename, "rb"); + if (!fp) + { + llwarns << "Couldn't open call log list" << filename << llendl; + return false; + } + + char buffer[MAX_STRING]; + char conv_name_buffer[MAX_STRING]; + char part_id_buffer[MAX_STRING]; + char conv_id_buffer[MAX_STRING]; + char history_file_name[MAX_STRING]; + int is_voice; + int has_offline_ims; + int stype; + S32 time; + + while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) + { + conv_name_buffer[0] = '\0'; + part_id_buffer[0] = '\0'; + conv_id_buffer[0] = '\0'; + + sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", + &time, + &stype, + &is_voice, + &has_offline_ims, + conv_name_buffer, + part_id_buffer, + conv_id_buffer, + history_file_name); + + Conversation_params params(time); + params.mConversationType = (SessionType)stype; + params.mIsVoice = is_voice; + params.mHasOfflineIMs = has_offline_ims; + params.mConversationName = std::string(conv_name_buffer); + params.mParticipantID = LLUUID(part_id_buffer); + params.mSessionID = LLUUID(conv_id_buffer); + params.mHistoryFileName = std::string(history_file_name); + + LLConversation conversation(params); + mConversations.push_back(conversation); + } + fclose(fp); + + notifyObservers(); + return true; +} + +void LLConversationLog::notifyObservers() +{ + std::set::const_iterator iter = mObservers.begin(); + for (; iter != mObservers.end(); ++iter) + { + (*iter)->changed(); + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h new file mode 100644 index 0000000000..700472ca8b --- /dev/null +++ b/indra/newview/llconversationlog.h @@ -0,0 +1,164 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&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 LLCONVERSATIONLOG_H_ +#define LLCONVERSATIONLOG_H_ + +#include "llcallingcard.h" +#include "llimfloater.h" +#include "llimview.h" + +class LLConversationLogObserver; +class Conversation_params; + +typedef LLIMModel::LLIMSession::SType SessionType; + +/* + * This class represents a particular session(conversation) of any type(im/voice/p2p/group/...) by storing some of session's data. + * Each LLConversation object has a corresponding visual representation in a form of LLConversationLogListItem. + */ +class LLConversation +{ +public: + + LLConversation(const Conversation_params& params); + LLConversation(const LLIMModel::LLIMSession& session); + LLConversation(const LLConversation& conversation); + + ~LLConversation(); + + const SessionType& getConversationType() const { return mConversationType; } + const std::string& getConversationName() const { return mConversationName; } + const std::string& getHistoryFileName() const { return mHistoryFileName; } + const LLUUID& getSessionID() const { return mSessionID; } + const LLUUID& getParticipantID() const { return mParticipantID; } + const std::string& getTimestamp() const { return mTimestamp; } + const time_t& getTime() const { return mTime; } + bool isVoice() const { return mIsVoice; } + bool hasOfflineMessages() const { return mHasOfflineIMs; } + + /* + * Resets flag of unread offline message to false when im floater with this conversation is opened. + */ + void onIMFloaterShown(const LLUUID& session_id); + + /* + * returns string representation(in form of: mm/dd/yyyy hh:mm) of time when conversation was started + */ + static const std::string createTimestamp(const time_t& utc_time); + +private: + + /* + * If conversation has unread offline messages sets callback for opening LLIMFloater + * with this conversation. + */ + void setListenIMFloaterOpened(); + + boost::signals2::connection mIMFloaterShowedConnection; + + time_t mTime; // start time of conversation + SessionType mConversationType; + std::string mConversationName; + std::string mHistoryFileName; + LLUUID mSessionID; + LLUUID mParticipantID; + bool mIsVoice; + bool mHasOfflineIMs; + std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm +}; + +/** + * LLConversationLog stores all agent's conversations. + * This class is responsible for creating and storing LLConversation objects when im or voice session starts. + * Also this class saves/retrieves conversations to/from file. + * + * Also please note that it may be several conversations with the same sessionID stored in the conversation log. + * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. + */ + +class LLConversationLog : public LLSingleton, LLIMSessionObserver, LLFriendObserver +{ + friend class LLSingleton; +public: + + /** + * adds conversation to the conversation list and notifies observers + */ + void logConversation(const LLConversation& conversation); + void removeConversation(const LLConversation& conversation); + + /** + * Returns first conversation with matched session_id + */ + const LLConversation* getConversation(const LLUUID& session_id); + + void addObserver(LLConversationLogObserver* observer); + void removeObserver(LLConversationLogObserver* observer); + + const std::vector& getConversations() { return mConversations; } + + // LLIMSessionObserver triggers + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){} // Stub + virtual void sessionRemoved(const LLUUID& session_id){} // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){} // Stub + + // LLFriendObserver trigger + virtual void changed(U32 mask); + + /** + * public method which is called on viewer exit to save conversation log + */ + void cache(); + +private: + + LLConversationLog(); + void notifyObservers(); + + /** + * constructs file name in which conversations log will be saved + * file name template: agentID.call_log. + * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log + */ + std::string getFileName(); + + bool saveToFile(const std::string& filename); + bool loadFromFile(const std::string& filename); + + typedef std::vector conversations_vec_t; + std::vector mConversations; + std::set mObservers; +}; + +class LLConversationLogObserver +{ +public: + virtual ~LLConversationLogObserver(){} + virtual void changed() = 0; +}; + +#endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp new file mode 100644 index 0000000000..0433719a89 --- /dev/null +++ b/indra/newview/llconversationloglist.cpp @@ -0,0 +1,422 @@ +/** + * @file llconversationloglist.cpp + * + * $LicenseInfo:firstyear=2002&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 "llavataractions.h" +#include "llagent.h" +#include "llfloaterreg.h" +#include "llfloaterconversationpreview.h" +#include "llgroupactions.h" +#include "llconversationloglist.h" +#include "llconversationloglistitem.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register r("conversation_log_list"); + +static LLConversationLogListNameComparator NAME_COMPARATOR; +static LLConversationLogListDateComparator DATE_COMPARATOR; + +LLConversationLogList::LLConversationLogList(const Params& p) +: LLFlatListViewEx(p), + mIsDirty(true) +{ + LLConversationLog::instance().addObserver(this); + + // Set up context menu. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar check_registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add ("Calllog.Action", boost::bind(&LLConversationLogList::onCustomAction, this, _2)); + check_registrar.add ("Calllog.Check", boost::bind(&LLConversationLogList::isActionChecked,this, _2)); + enable_registrar.add("Calllog.Enable", boost::bind(&LLConversationLogList::isActionEnabled,this, _2)); + + LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_conversation_log_gear.xml", + gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); + if(context_menu) + { + mContextMenu = context_menu->getHandle(); + } + + mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst"); +} + +LLConversationLogList::~LLConversationLogList() +{ + if (mContextMenu.get()) + { + mContextMenu.get()->die(); + } + + LLConversationLog::instance().removeObserver(this); +} + +void LLConversationLogList::draw() +{ + if (mIsDirty) + { + refresh(); + } + LLFlatListViewEx::draw(); +} + +BOOL LLConversationLogList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + + LLToggleableMenu* context_menu = mContextMenu.get(); + { + context_menu->buildDrawLabels(); + if (context_menu && size()) + context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, context_menu, x, y); + } + + return handled; +} + +void LLConversationLogList::setNameFilter(const std::string& filter) +{ + std::string filter_upper = filter; + LLStringUtil::toUpper(filter_upper); + if (mNameFilter != filter_upper) + { + mNameFilter = filter_upper; + setDirty(); + } +} + +bool LLConversationLogList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ + LLStringUtil::toUpper(haystack); + return haystack.find(needle_upper) != std::string::npos; +} + +void LLConversationLogList::sortByName() +{ + setComparator(&NAME_COMPARATOR); + sort(); +} + +void LLConversationLogList::sortByDate() +{ + setComparator(&DATE_COMPARATOR); + sort(); +} + +void LLConversationLogList::toggleSortFriendsOnTop() +{ + mIsFriendsOnTop = !mIsFriendsOnTop; + gSavedSettings.setBOOL("SortFriendsFirst", mIsFriendsOnTop); + sort(); +} + +void LLConversationLogList::changed() +{ + refresh(); +} + +void LLConversationLogList::addNewItem(const LLConversation* conversation) +{ + LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); + if (!mNameFilter.empty()) + { + item->highlightNameDate(mNameFilter); + } + addItem(item, conversation->getSessionID(), ADD_TOP); +} + +void LLConversationLogList::refresh() +{ + rebuildList(); + sort(); + + mIsDirty = false; +} + +void LLConversationLogList::rebuildList() +{ + clear(); + + bool have_filter = !mNameFilter.empty(); + + const std::vector& conversations = LLConversationLog::instance().getConversations(); + std::vector::const_iterator iter = conversations.begin(); + + for (; iter != conversations.end(); ++iter) + { + bool not_found = have_filter && !findInsensitive(iter->getConversationName(), mNameFilter) && !findInsensitive(iter->getTimestamp(), mNameFilter); + if (not_found) + continue; + + addNewItem(&*iter); + } +} + +void LLConversationLogList::onCustomAction(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + + if ("im" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::startIM(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::startIM(selected_id); + break; + + default: + break; + } + } + else if ("call" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::startCall(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::startCall(selected_id); + break; + + default: + break; + } + } + else if ("view_profile" == command_name) + { + switch (stype) + { + case LLIMModel::LLIMSession::P2P_SESSION: + LLAvatarActions::showProfile(selected_id); + break; + + case LLIMModel::LLIMSession::GROUP_SESSION: + LLGroupActions::show(selected_id); + break; + + default: + break; + } + } + else if ("chat_history" == command_name) + { + const LLUUID& session_id = getSelectedConversation()->getSessionID(); + LLFloaterReg::showInstance("preview_conversation", session_id, true); + } + else if ("offer_teleport" == command_name) + { + LLAvatarActions::offerTeleport(selected_id); + } + else if("add_rem_friend" == command_name) + { + if (LLAvatarActions::isFriend(selected_id)) + { + LLAvatarActions::removeFriendDialog(selected_id); + } + else + { + LLAvatarActions::requestFriendshipDialog(selected_id); + } + } + else if ("invite_to_group" == command_name) + { + LLAvatarActions::inviteToGroup(selected_id); + } + else if ("show_on_map" == command_name) + { + LLAvatarActions::showOnMap(selected_id); + } + else if ("share" == command_name) + { + LLAvatarActions::share(selected_id); + } + else if ("pay" == command_name) + { + LLAvatarActions::pay(selected_id); + } + else if ("block" == command_name) + { + LLAvatarActions::toggleBlock(selected_id); + } +} + +bool LLConversationLogList::isActionEnabled(const LLSD& userdata) +{ + if (numSelected() != 1) + { + return false; + } + + const std::string command_name = userdata.asString(); + + LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + + bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype; + bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; + + if ("can_im" == command_name || "can_view_profile" == command_name) + { + return is_p2p || is_group; + } + else if ("can_view_chat_history" == command_name) + { + return true; + } + else if ("can_call" == command_name) + { + return (is_p2p || is_group) && LLAvatarActions::canCall(); + } + else if ("add_rem_friend" == command_name || + "can_invite_to_group" == command_name || + "can_share" == command_name || + "can_block" == command_name || + "can_pay" == command_name) + { + return is_p2p; + } + else if("can_offer_teleport" == command_name) + { + return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); + } + else if ("can_show_on_map") + { + return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); + } + + return false; +} + +bool LLConversationLogList::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); + + if ("is_blocked" == command_name) + { + return is_p2p && LLAvatarActions::isBlocked(selected_id); + } + else if ("is_friend" == command_name) + { + return is_p2p && LLAvatarActions::isFriend(selected_id); + } + + return false; +} + +LLIMModel::LLIMSession::SType LLConversationLogList::getSelectedSessionType() +{ + const LLConversationLogListItem* item = getSelectedConversationPanel(); + + if (item) + { + return item->getConversation()->getConversationType(); + } + + return LLIMModel::LLIMSession::NONE_SESSION; +} + +const LLConversationLogListItem* LLConversationLogList::getSelectedConversationPanel() +{ + LLPanel* panel = LLFlatListViewEx::getSelectedItem(); + LLConversationLogListItem* conv_panel = dynamic_cast(panel); + + return conv_panel; +} + +const LLConversation* LLConversationLogList::getSelectedConversation() +{ + const LLConversationLogListItem* panel = getSelectedConversationPanel(); + + if (panel) + { + return panel->getConversation(); + } + + return NULL; +} + +bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ + const LLConversationLogListItem* conversation_item1 = dynamic_cast(item1); + const LLConversationLogListItem* conversation_item2 = dynamic_cast(item2); + + if (!conversation_item1 || !conversation_item2) + { + llerror("conversation_item1 and conversation_item2 cannot be null", 0); + return true; + } + + return doCompare(conversation_item1, conversation_item2); +} + +bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ + std::string name1 = conversation1->getConversation()->getConversationName(); + std::string name2 = conversation2->getConversation()->getConversationName(); + const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); + const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); + if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + { + return LLAvatarActions::isFriend(id1); + } + + return name1 < name2; +} + +bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ + time_t date1 = conversation1->getConversation()->getTime(); + time_t date2 = conversation2->getConversation()->getTime(); + const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); + const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + + bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); + if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) + { + return LLAvatarActions::isFriend(id1); + } + + return date1 > date2; +} diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h new file mode 100644 index 0000000000..dff34a74c6 --- /dev/null +++ b/indra/newview/llconversationloglist.h @@ -0,0 +1,143 @@ +/** + * @file llconversationloglist.h + * + * $LicenseInfo:firstyear=2002&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 LLCONVERSATIONLOGLIST_H_ +#define LLCONVERSATIONLOGLIST_H_ + +#include "llconversationlog.h" +#include "llflatlistview.h" +#include "lltoggleablemenu.h" + +class LLConversationLogListItem; + +/** + * List of all agent's conversations. I.e. history of conversations. + * This list represents contents of the LLConversationLog. + * Each change in LLConversationLog leads to rebuilding this list, so + * it's always in actual state. + */ + +class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver +{ + LOG_CLASS(LLConversationLogList); +public: + struct Params : public LLInitParam::Block + { + Params(){}; + }; + + LLConversationLogList(const Params& p); + virtual ~LLConversationLogList(); + + virtual void draw(); + + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + LLToggleableMenu* getContextMenu() const { return mContextMenu.get(); } + + void addNewItem(const LLConversation* conversation); + void setNameFilter(const std::string& filter); + void sortByName(); + void sortByDate(); + void toggleSortFriendsOnTop(); + bool getSortFriendsOnTop() const { return mIsFriendsOnTop; } + + /** + * Changes from LLConversationLogObserver + */ + virtual void changed(); + +private: + + void setDirty(bool dirty = true) { mIsDirty = dirty; } + void refresh(); + + /** + * Clears list and re-adds items from LLConverstationLog + * If filter is not empty re-adds items which match the filter + */ + void rebuildList(); + + bool findInsensitive(std::string haystack, const std::string& needle_upper); + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLIMModel::LLIMSession::SType getSelectedSessionType(); + const LLConversationLogListItem* getSelectedConversationPanel(); + const LLConversation* getSelectedConversation(); + + LLHandle mContextMenu; + bool mIsDirty; + bool mIsFriendsOnTop; + std::string mNameFilter; +}; + +/** + * Abstract comparator for ConversationLogList items + */ +class LLConversationLogListItemComparator : public LLFlatListView::ItemComparator +{ + LOG_CLASS(LLConversationLogListItemComparator); + +public: + LLConversationLogListItemComparator() {}; + virtual ~LLConversationLogListItemComparator() {}; + + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const = 0; +}; + +class LLConversationLogListNameComparator : public LLConversationLogListItemComparator +{ + LOG_CLASS(LLConversationLogListNameComparator); + +public: + LLConversationLogListNameComparator() {}; + virtual ~LLConversationLogListNameComparator() {}; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +class LLConversationLogListDateComparator : public LLConversationLogListItemComparator +{ + LOG_CLASS(LLConversationLogListDateComparator); + +public: + LLConversationLogListDateComparator() {}; + virtual ~LLConversationLogListDateComparator() {}; + +protected: + + virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +#endif /* LLCONVERSATIONLOGLIST_H_ */ diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp new file mode 100644 index 0000000000..fc2e757864 --- /dev/null +++ b/indra/newview/llconversationloglistitem.cpp @@ -0,0 +1,157 @@ +/** + * @file llconversationloglistitem.cpp + * + * $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" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llconversationlog.h" +#include "llconversationloglistitem.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" + +LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conversation) +: LLPanel(), + mConversation(conversation), + mConversationName(NULL), + mConversationDate(NULL) +{ + buildFromFile("panel_conversation_log_list_item.xml"); + + LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); + + bool has_offline_ims = !mConversation->isVoice() && mConversation->hasOfflineMessages(); + bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + + if (has_offline_ims && !ims_are_read) + { + mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); + } +} + +LLConversationLogListItem::~LLConversationLogListItem() +{ + mIMFloaterShowedConnection.disconnect(); +} + +BOOL LLConversationLogListItem::postBuild() +{ + initIcons(); + + // set conversation name + mConversationName = getChild("conversation_name"); + mConversationName->setValue(mConversation->getConversationName()); + + // set conversation date and time + mConversationDate = getChild("date_time"); + mConversationDate->setValue(mConversation->getTimestamp()); + + getChild("delete_btn")->setClickedCallback(boost::bind(&LLConversationLogListItem::onRemoveBtnClicked, this)); + + return TRUE; +} + +void LLConversationLogListItem::initIcons() +{ + switch (mConversation->getConversationType()) + { + case LLIMModel::LLIMSession::P2P_SESSION: + case LLIMModel::LLIMSession::ADHOC_SESSION: + { + LLAvatarIconCtrl* avatar_icon = getChild("avatar_icon"); + avatar_icon->setVisible(TRUE); + avatar_icon->setValue(mConversation->getParticipantID()); + break; + } + case LLIMModel::LLIMSession::GROUP_SESSION: + { + LLGroupIconCtrl* group_icon = getChild("group_icon"); + group_icon->setVisible(TRUE); + group_icon->setValue(mConversation->getSessionID()); + break; + } + default: + break; + } + + if (mConversation->isVoice()) + { + getChild("voice_session_icon")->setVisible(TRUE); + } + else + { + if (mConversation->hasOfflineMessages()) + { + getChild("unread_ims_icon")->setVisible(TRUE); + } + } +} + +void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(true); + LLPanel::onMouseEnter(x, y, mask); +} + +void LLConversationLogListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + getChildView("hovered_icon")->setVisible(false); + LLPanel::onMouseLeave(x, y, mask); +} + +void LLConversationLogListItem::setValue(const LLSD& value) +{ + if (!value.isMap() || !value.has("selected")) + { + return; + } + + getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLConversationLogListItem::onIMFloaterShown(const LLUUID& session_id) +{ + if (mConversation->getSessionID() == session_id) + { + getChild("unread_ims_icon")->setVisible(FALSE); + } +} + +void LLConversationLogListItem::onRemoveBtnClicked() +{ + LLConversationLog::instance().removeConversation(*mConversation); +} + +void LLConversationLogListItem::highlightNameDate(const std::string& highlited_text) +{ + LLStyle::Params params; + LLTextUtil::textboxSetHighlightedVal(mConversationName, params, mConversation->getConversationName(), highlited_text); + LLTextUtil::textboxSetHighlightedVal(mConversationDate, params, mConversation->getTimestamp(), highlited_text); +} diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h new file mode 100644 index 0000000000..deba7d4563 --- /dev/null +++ b/indra/newview/llconversationloglistitem.h @@ -0,0 +1,77 @@ +/** + * @file llconversationloglistitem.h + * + * $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 LLCONVERSATIONLOGLISTITEM_H_ +#define LLCONVERSATIONLOGLISTITEM_H_ + +#include "llimfloater.h" +#include "llpanel.h" + +class LLTextBox; +class LLConversation; + +/** + * This class is a visual representation of LLConversation, each of which is LLConversationLog entry. + * LLConversationLogList consists of these LLConversationLogListItems. + * LLConversationLogListItem consists of: + * conversaion_type_icon + * conversaion_name + * conversaion_date + * Also LLConversationLogListItem holds pointer to its LLConversationLog. + */ + +class LLConversationLogListItem : public LLPanel +{ +public: + LLConversationLogListItem(const LLConversation* conversation); + virtual ~LLConversationLogListItem(); + + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + + virtual void setValue(const LLSD& value); + + virtual BOOL postBuild(); + + void onIMFloaterShown(const LLUUID& session_id); + void onRemoveBtnClicked(); + + const LLConversation* getConversation() const { return mConversation; } + + void highlightNameDate(const std::string& highlited_text); + +private: + + void initIcons(); + + const LLConversation* mConversation; + + LLTextBox* mConversationName; + LLTextBox* mConversationDate; + + boost::signals2::connection mIMFloaterShowedConnection; +}; + +#endif /* LLCONVERSATIONLOGITEM_H_ */ diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp new file mode 100644 index 0000000000..569ba12ed6 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.cpp @@ -0,0 +1,127 @@ +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $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 "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +: LLFloater(key), + mConversationLogList(NULL) +{ + mCommitCallbackRegistrar.add("CallLog.Action", boost::bind(&LLFloaterConversationLog::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("CallLog.Check", boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ + mConversationLogList = getChild("conversation_log_list"); + + switch (gSavedSettings.getU32("CallLogSortOrder")) + { + case E_SORT_BY_NAME: + mConversationLogList->sortByName(); + break; + + case E_SORT_BY_DATE: + mConversationLogList->sortByDate(); + break; + } + + // Use the context menu of the Conversation list for the Conversation tab gear menu. + LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); + if (conversations_gear_menu) + { + getChild("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); + } + + getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + + return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ + std::string filter = search_string; + LLStringUtil::trimHead(filter); + + mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + if ("sort_by_name" == command_name) + { + mConversationLogList->sortByName(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); + } + else if ("sort_by_date" == command_name) + { + mConversationLogList->sortByDate(); + gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); + } + else if ("sort_friends_on_top" == command_name) + { + mConversationLogList->toggleSortFriendsOnTop(); + } +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ + return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + + U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + + if ("sort_by_name" == command_name) + { + return sort_order == E_SORT_BY_NAME; + } + else if ("sort_by_date" == command_name) + { + return sort_order == E_SORT_BY_DATE; + } + else if ("sort_friends_on_top" == command_name) + { + return gSavedSettings.getBOOL("SortFriendsFirst"); + } + + return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h new file mode 100644 index 0000000000..40dd266663 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.h @@ -0,0 +1,61 @@ +/** + * @file llfloaterconversationlog.h + * + * $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_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + + typedef enum e_sort_oder{ + E_SORT_BY_NAME = 0, + E_SORT_BY_DATE = 1, + } ESortOrder; + + LLFloaterConversationLog(const LLSD& key); + virtual ~LLFloaterConversationLog(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + + void onFilterEdit(const std::string& search_string); + +private: + + void onCustomAction (const LLSD& userdata); + bool isActionEnabled(const LLSD& userdata); + bool isActionChecked(const LLSD& userdata); + + LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp new file mode 100644 index 0000000000..e8554bb066 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -0,0 +1,112 @@ +/** + * @file llfloaterconversationpreview.cpp + * + * $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 "llconversationlog.h" +#include "llfloaterconversationpreview.h" +#include "llimview.h" +#include "lllineeditor.h" + +LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) +: LLFloater(session_id), + mChatHistory(NULL), + mSessionID(session_id.asUUID()) +{} + +BOOL LLFloaterConversationPreview::postBuild() +{ + mChatHistory = getChild("chat_history"); + + const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); + if (conv) + { + std::string name = conv->getConversationName(); + LLStringUtil::format_map_t args; + args["[NAME]"] = name; + std::string title = getString("Title", args); + setTitle(title); + + getChild("description")->setValue(name); + } + + return LLFloater::postBuild(); +} + +void LLFloaterConversationPreview::draw() +{ + LLFloater::draw(); +} + +void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +{ + const LLConversation* conv = LLConversationLog::instance().getConversation(session_id); + if (!conv) + { + return; + } + std::list messages; + std::string file = conv->getHistoryFileName(); + LLLogChat::loadAllHistory(file, messages); + + if (messages.size()) + { + std::ostringstream message; + std::list::const_iterator iter = messages.begin(); + for (; iter != messages.end(); ++iter) + { + LLSD msg = *iter; + + std::string time = msg["time"].asString(); + LLUUID from_id = msg["from_id"].asUUID(); + std::string from = msg["from"].asString(); + std::string message = msg["message"].asString(); + bool is_history = msg["is_history"].asBoolean(); + + LLChat chat; + chat.mFromID = from_id; + chat.mSessionID = session_id; + chat.mFromName = from; + chat.mTimeStr = time; + chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + chat.mText = message; + + appendMessage(chat); + } + } +} + +void LLFloaterConversationPreview::appendMessage(const LLChat& chat) +{ + if (!chat.mMuted) + { + LLSD args; + args["use_plain_text_chat_history"] = true; + args["show_time"] = true; + args["show_names_for_p2p_conv"] = true; + + mChatHistory->appendMessage(chat); + } +} diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h new file mode 100644 index 0000000000..cfc7c34485 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.h @@ -0,0 +1,51 @@ +/** + * @file llfloaterconversationpreview.h + * + * $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 LLFLOATERCONVERSATIONPREVIEW_H_ +#define LLFLOATERCONVERSATIONPREVIEW_H_ + +#include "llchathistory.h" +#include "llfloater.h" + +class LLFloaterConversationPreview : public LLFloater +{ +public: + + LLFloaterConversationPreview(const LLSD& session_id); + virtual ~LLFloaterConversationPreview(){}; + + virtual BOOL postBuild(); + + virtual void draw(); + virtual void onOpen(const LLSD& session_id); + +private: + void appendMessage(const LLChat& chat); + + LLChatHistory* mChatHistory; + LLUUID mSessionID; +}; + +#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 22ce3cd42b..f1d7d1c04f 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -59,6 +59,8 @@ #include "llviewerchat.h" #include "llnotificationmanager.h" +floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; + LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLIMConversation(session_id), mLastMessageIndex(-1), @@ -765,6 +767,11 @@ void LLIMFloater::setVisible(BOOL visible) chiclet->setToggleState(false); } } + + if (visible) + { + sIMFloaterShowedSignal(mSessionID); + } } BOOL LLIMFloater::getVisible() @@ -1334,3 +1341,8 @@ void LLIMFloater::addToHost(const LLUUID& session_id) } } } + +boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) +{ + return LLIMFloater::sIMFloaterShowedSignal.connect(cb); +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 2ac11ded20..7e45cf42c2 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -44,6 +44,8 @@ class LLChatHistory; class LLInventoryItem; class LLInventoryCategory; +typedef boost::signals2::signal floater_showed_signal_t; + /** * Individual IM window that appears at the bottom of the screen, * optionally "docked" to the bottom tray. @@ -125,7 +127,11 @@ public: bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } + static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); + static floater_showed_signal_t sIMFloaterShowedSignal; + private: + // process focus events to set a currently active session /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdbb7c7cca..c66c0cd865 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -175,10 +175,11 @@ LLIMModel::LLIMModel() addNewMsgCallback(boost::bind(&toast_callback, _1)); } -LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) : mSessionID(session_id), mName(name), mType(type), + mHasOfflineMessage(has_offline_msg), mParticipantUnreadMessageCount(0), mNumUnread(0), mOtherParticipantID(other_participant_id), @@ -375,6 +376,8 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES break; } } + default: + break; } // Update speakers list when connected if (LLVoiceChannel::STATE_CONNECTED == new_state) @@ -676,7 +679,7 @@ void LLIMModel::testMessages() //session name should not be empty bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, - const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) + const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) { if (name.empty()) { @@ -690,7 +693,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co return false; } - LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice); + LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg); mId2SessionMap[session_id] = session; // When notifying observer, name of session is used instead of "name", because they may not be the @@ -702,10 +705,10 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co } -bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice) +bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg) { uuid_vec_t no_ids; - return newSession(session_id, name, type, other_participant_id, no_ids, voice); + return newSession(session_id, name, type, other_participant_id, no_ids, voice, has_offline_msg); } bool LLIMModel::clearSession(const LLUUID& session_id) @@ -2398,6 +2401,7 @@ void LLIMMgr::addMessage( const LLUUID& target_id, const std::string& from, const std::string& msg, + bool is_offline_msg, const std::string& session_name, EInstantMessage dialog, U32 parent_estate_id, @@ -2423,7 +2427,7 @@ void LLIMMgr::addMessage( bool new_session = !hasSession(new_session_id); if (new_session) { - LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id); + LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); // When we get a new IM, and if you are a god, display a bit // of information about the source. This is to help liaisons @@ -3315,6 +3319,7 @@ public: from_id, name, buffer, + IM_OFFLINE == offline, std::string((char*)&bin_bucket[0]), IM_SESSION_INVITE, message_params["parent_estate_id"].asInteger(), diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 80bf315aa8..fa9d20ca53 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -70,10 +70,11 @@ public: GROUP_SESSION, ADHOC_SESSION, AVALINE_SESSION, + NONE_SESSION, } SType; LLIMSession(const LLUUID& session_id, const std::string& name, - const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice); + const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg); virtual ~LLIMSession(); void sessionInitReplyReceived(const LLUUID& new_session_id); @@ -133,6 +134,8 @@ public: //if IM session is created for a voice call bool mStartedAsIMCall; + bool mHasOfflineMessage; + private: void onAdHocNameCache(const LLAvatarName& av_name); @@ -181,10 +184,10 @@ public: * @param name session name should not be empty, will return false if empty */ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, - const uuid_vec_t& ids, bool voice = false); + const uuid_vec_t& ids, bool voice = false, bool has_offline_msg = false); bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, - const LLUUID& other_participant_id, bool voice = false); + const LLUUID& other_participant_id, bool voice = false, bool has_offline_msg = false); /** * Remove all session data associated with a session specified by session_id @@ -325,6 +328,7 @@ public: const LLUUID& target_id, const std::string& from, const std::string& msg, + bool is_offline_msg = false, const std::string& session_name = LLStringUtil::null, EInstantMessage dialog = IM_NOTHING_SPECIAL, U32 parent_estate_id = 0, diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 65fd6d7019..4cf6ff55a4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -94,6 +94,7 @@ #include "llcallingcard.h" #include "llconsole.h" #include "llcontainerview.h" +#include "llconversationlog.h" #include "lldebugview.h" #include "lldrawable.h" #include "lleventnotifier.h" @@ -1266,6 +1267,8 @@ bool idle_startup() display_startup(); LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); + LLConversationLog::getInstance(); + return FALSE; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index bf12b08321..5c662af875 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,8 @@ #include "llfloaterbump.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" +#include "llfloaterconversationlog.h" +#include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" #include "llfloaterdisplayname.h" #include "llfloatereditdaycycle.h" @@ -188,6 +190,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -253,6 +256,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); + LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 03c113ecb3..20887f7832 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2396,6 +2396,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, LLStringUtil::null, dialog, parent_estate_id, @@ -2435,7 +2436,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) if (!gIMMgr->isNonFriendSessionNotified(session_id)) { std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); - gIMMgr->addMessage(session_id, from_id, name, message); + gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline); gIMMgr->addNotifiedNonFriendSessionID(session_id); } @@ -2448,6 +2449,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, LLStringUtil::null, dialog, parent_estate_id, @@ -2788,6 +2790,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) from_id, name, buffer, + IM_OFFLINE == offline, ll_safe_string((char*)binary_bucket), IM_SESSION_INVITE, parent_estate_id, diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index df1d3f2955..f4c88403a5 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -4072,6 +4072,7 @@ void LLVivoxVoiceClient::messageEvent( session->mCallerID, session->mName.c_str(), message.c_str(), + false, LLStringUtil::null, // default arg IM_NOTHING_SPECIAL, // default arg 0, // default arg diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml new file mode 100644 index 0000000000..1c5800e25f --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml new file mode 100644 index 0000000000..27b744aefb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -0,0 +1,53 @@ + + + + CONVERSATION: [NAME] + + + Description: + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e5ef80e352..e8ef3c1df9 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -56,6 +56,7 @@ image_overlay="Conv_toolbar_sort" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" + menu_filename="menu_participant_view.xml" layout="topleft" left="10" name="sort_btn" diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml new file mode 100644 index 0000000000..b8d0eef956 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml new file mode 100644 index 0000000000..4ab8cb4f7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml new file mode 100644 index 0000000000..6401b0e3b7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml new file mode 100644 index 0000000000..3c98e32e7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + -- cgit v1.2.3 From 11e9f66e6217c22373f5d47518f6d1f9885f1793 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 28 Aug 2012 12:41:57 -0700 Subject: BUILDFIX: Correcting a linux build error. --- indra/newview/llfloaterconversationpreview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 2c34029c5c..ae6f1441eb 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -88,8 +88,13 @@ void LLFloaterConversationPreview::showHistory() int delta = 0; if (mCurrentPage) { - double num_of_pages = (double)mMessages.size() / mPageSize; - delta = (ceil(num_of_pages) - num_of_pages) * mPageSize; + // stinson 08/28/2012 : This operation could be simplified using integer math with the mod (%) operator. + // e.g. The following code should give the same output. + // int remainder = mMessages.size() % mPageSize; + // delta = (remainder == 0) ? 0 : (mPageSize - remainder); + // Though without examining further, the remainder might be a more appropriate value. + double num_of_pages = static_cast(mMessages.size()) / static_cast(mPageSize); + delta = static_cast((ceil(num_of_pages) - num_of_pages) * static_cast(mPageSize)); } std::advance(iter, (mCurrentPage * mPageSize) - delta); -- cgit v1.2.3 From 051bc99573d7c571cea0e2e1df332c1e5e97ff19 Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Tue, 28 Aug 2012 20:08:17 +0300 Subject: CHUI-287 FIX IM toast panel is closed upon mouse up and doesn't pass the mouse click that activates "click to walk". --- indra/newview/lltoastimpanel.cpp | 4 ++-- indra/newview/lltoastimpanel.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index e0cb200ef5..75e6e3d13a 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -104,9 +104,9 @@ LLToastIMPanel::~LLToastIMPanel() } //virtual -BOOL LLToastIMPanel::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLToastIMPanel::handleMouseUp(S32 x, S32 y, MASK mask) { - if (LLPanel::handleMouseDown(x,y,mask) == FALSE) + if (LLPanel::handleMouseUp(x,y,mask) == FALSE) { mNotification->respond(mNotification->getResponseTemplate()); } diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 279dd69bc7..3eb11fb3bc 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -52,7 +52,7 @@ public: LLToastIMPanel(LLToastIMPanel::Params &p); virtual ~LLToastIMPanel(); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); private: void showInspector(); -- cgit v1.2.3 From a6bdef648014ec1c7424b2bd307b3453cc5c786c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 28 Aug 2012 17:59:10 -0400 Subject: Force rebake now calls requestServerAppearanceUpdate() if supported --- indra/newview/llviewermenu.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 24bed93f04..3c0136c258 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7620,6 +7620,10 @@ void handle_rebake_textures(void*) // Slam pending upload count to "unstick" things bool slam_for_debug = true; gAgentAvatarp->forceBakeAllTextures(slam_for_debug); + if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) + { + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } } void toggle_visibility(void* user_data) -- cgit v1.2.3 From c4638d1dca7f3292d7ce48ddb2f5598f86282c88 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Aug 2012 19:09:57 -0700 Subject: CHUI-280 : WIP : Implement update of LLConversationModel in LLParticipantList --- indra/llui/llfolderviewmodel.h | 9 +++ indra/newview/llconversationmodel.cpp | 47 ++++++++++++- indra/newview/llconversationmodel.h | 31 ++++++++- indra/newview/llparticipantlist.cpp | 125 ++++++++++++++++++++++------------ 4 files changed, 163 insertions(+), 49 deletions(-) diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 41660c6e1e..16d9c86fd7 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -262,6 +262,15 @@ public: child->setParent(NULL); dirtyFilter(); } + + virtual void clearChildren() + { + // As this is cleaning the whole list of children wholesale, we do need to delete the pointed objects + // This is different and not equivalent to calling removeChild() on each child + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + mChildren.clear(); + dirtyFilter(); + } void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a5c0244bd4..9b353809db 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -88,7 +88,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL // LLConversationItemSession::LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : - LLConversationItem(display_name,uuid,root_view_model) + LLConversationItem(display_name,uuid,root_view_model), + mIsLoaded(false) { } @@ -97,12 +98,54 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde { } +void LLConversationItemSession::addParticipant(LLConversationItemParticipant* item) +{ + addChild(item); + mIsLoaded = true; +} + +void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* item) +{ + removeChild(item); +} + +void LLConversationItemSession::clearParticipants() +{ + clearChildren(); + mIsLoaded = false; +} + +LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) +{ + // This is *not* a general tree parsing algorithm. It assumes that a session contains only + // items (LLConversationItemParticipant) that have themselve no children. + LLConversationItemParticipant* participant = NULL; + child_list_t::iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + participant = dynamic_cast(*iter); + if (participant->hasSameValue(participant_id)) + { + break; + } + } + return (iter == mChildren.end() ? NULL : participant); +} + +void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_id, bool is_muted) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + participant->setIsMuted(is_muted); +} + // // LLConversationItemParticipant // LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : - LLConversationItem(display_name,uuid,root_view_model) + LLConversationItem(display_name,uuid,root_view_model), + mIsMuted(false), + mIsModerator(false) { } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1a63230e41..484c0feb36 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -33,6 +33,8 @@ // Implementation of conversations list class LLConversationItem; +class LLConversationItemSession; +class LLConversationItemParticipant; typedef std::map conversations_items_map; typedef std::map conversations_widgets_map; @@ -100,9 +102,10 @@ public: // bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } -private: - std::string mName; - const LLUUID mUUID; + +protected: + std::string mName; // Name of the session or the participant + LLUUID mUUID; // UUID of the session or the participant }; class LLConversationItemSession : public LLConversationItem @@ -111,6 +114,19 @@ public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} + + void setSessionID(const LLUUID& session_id) { mUUID = session_id; } + void addParticipant(LLConversationItemParticipant* item); + void removeParticipant(LLConversationItemParticipant* item); + void clearParticipants(); + LLConversationItemParticipant* findParticipant(const LLUUID& participant_id); + + void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); + + bool isLoaded() { return mIsLoaded; } + +private: + bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; class LLConversationItemParticipant : public LLConversationItem @@ -119,6 +135,15 @@ public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemParticipant() {} + + bool isMuted() { return mIsMuted; } + bool isModerator() {return mIsModerator; } + void setIsMuted(bool is_muted) { mIsMuted = is_muted; } + void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + +private: + bool mIsMuted; // default is false + bool mIsModerator; // default is false }; // We don't want to ever filter conversations but we need to declare that class to create a conversation view model. diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 552ae196dd..6511b0a1a6 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -29,6 +29,8 @@ // common includes #include "lltrans.h" #include "llavataractions.h" +#include "llavatarnamecache.h" +#include "llavatarname.h" #include "llagent.h" #include "llimview.h" @@ -226,29 +228,34 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); - mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; - mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); - mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); - mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); - // Set onAvatarListDoubleClicked as default on_return action. - mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); - - if (use_context_menu) - { - //mParticipantListMenu = new LLParticipantListMenu(*this); - //mAvatarList->setContextMenu(mParticipantListMenu); - mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); - } - else + setSessionID(mSpeakerMgr->getSessionID()); + + if (mAvatarList) { - mAvatarList->setContextMenu(NULL); - } + mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); + LL_DEBUGS("SpeakingIndicator") << "Set session for speaking indicators: " << mSpeakerMgr->getSessionID() << LL_ENDL; + mAvatarList->setSessionID(mSpeakerMgr->getSessionID()); + mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); + mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); + // Set onAvatarListDoubleClicked as default on_return action. + mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + + if (use_context_menu) + { + //mParticipantListMenu = new LLParticipantListMenu(*this); + //mAvatarList->setContextMenu(mParticipantListMenu); + mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + } + else + { + mAvatarList->setContextMenu(NULL); + } - if (use_context_menu && can_toggle_icons) - { - mAvatarList->setShowIcons("ParticipantListShowIcons"); - mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); + if (use_context_menu && can_toggle_icons) + { + mAvatarList->setShowIcons("ParticipantListShowIcons"); + mAvatarListToggleIconsConnection = gSavedSettings.getControl("ParticipantListShowIcons")->getSignal()->connect(boost::bind(&LLAvatarList::toggleIcons, mAvatarList)); + } } //Lets fill avatarList with existing speakers @@ -396,6 +403,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); } } @@ -415,30 +423,39 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) */ void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) { - LLPanel* item = mAvatarList->getItemByValue(participant_id); - - if (NULL == item) + if (mAvatarList) { - LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; - return; - } + LLPanel* item = mAvatarList->getItemByValue(participant_id); - if (typeid(*item) == typeid(LLAvalineListItem)) - { - LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; - // item representing an Avaline caller has a correct type already. - return; - } + if (NULL == item) + { + LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL; + return; + } - LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; + if (typeid(*item) == typeid(LLAvalineListItem)) + { + LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL; + // item representing an Avaline caller has a correct type already. + return; + } - // remove UUID from LLAvatarList::mIDs to be able add it again. - uuid_vec_t& ids = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); - ids.erase(pos); + LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL; - // remove item directly - mAvatarList->removeItem(item); + // remove UUID from LLAvatarList::mIDs to be able add it again. + uuid_vec_t& ids = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id); + ids.erase(pos); + + // remove item directly + mAvatarList->removeItem(item); + } + + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + removeParticipant(participant); + } // re-add avaline caller with a correct class instance. addAvatarIDExceptAgent(participant_id); @@ -562,6 +579,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer event // update UI on confirmation of moderator mutes if (event->getValue().asString() == "voice") { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); } return true; @@ -601,21 +619,40 @@ void LLParticipantList::sort() void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { if (mExcludeAgent && gAgent.getID() == avatar_id) return; - if (mAvatarList->contains(avatar_id)) return; + if (mAvatarList && mAvatarList->contains(avatar_id)) return; bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); + LLConversationItemParticipant* participant = NULL; + if (is_avatar) { - mAvatarList->getIDs().push_back(avatar_id); - mAvatarList->setDirty(); + // Create a participant view model instance and add it to the linked list + LLAvatarName avatar_name; + bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); + participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); + if ( mAvatarList) + { + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); + } } else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); - mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); + // Create a participant view model instance and add it to the linked list + participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); + if ( mAvatarList) + { + mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); + } mAvalineUpdater->watchAvalineCaller(avatar_id); } + + // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. + // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) + addParticipant(participant); + adjustParticipant(avatar_id); } -- cgit v1.2.3 From ad070b9155e2fddfc746319003253248ceb0eba3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 28 Aug 2012 23:13:10 -0700 Subject: CHUI-280 : Implement all LLConversationModel updates in LLParticipantList. Allow mAvatarList to be NULL. --- indra/newview/llconversationmodel.cpp | 31 +++++- indra/newview/llconversationmodel.h | 6 +- indra/newview/llparticipantlist.cpp | 193 +++++++++++++++++++--------------- 3 files changed, 137 insertions(+), 93 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 9b353809db..dbf5ac6e03 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -98,15 +98,24 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde { } -void LLConversationItemSession::addParticipant(LLConversationItemParticipant* item) +void LLConversationItemSession::addParticipant(LLConversationItemParticipant* participant) { - addChild(item); + addChild(participant); mIsLoaded = true; } -void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* item) +void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { - removeChild(item); + removeChild(participant); +} + +void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + removeParticipant(participant); + } } void LLConversationItemSession::clearParticipants() @@ -135,7 +144,19 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_id, bool is_muted) { LLConversationItemParticipant* participant = findParticipant(participant_id); - participant->setIsMuted(is_muted); + if (participant) + { + participant->setIsMuted(is_muted); + } +} + +void LLConversationItemSession::setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator) +{ + LLConversationItemParticipant* participant = findParticipant(participant_id); + if (participant) + { + participant->setIsModerator(is_moderator); + } } // diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 484c0feb36..aa79e5aeb0 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -116,12 +116,14 @@ public: virtual ~LLConversationItemSession() {} void setSessionID(const LLUUID& session_id) { mUUID = session_id; } - void addParticipant(LLConversationItemParticipant* item); - void removeParticipant(LLConversationItemParticipant* item); + void addParticipant(LLConversationItemParticipant* participant); + void removeParticipant(LLConversationItemParticipant* participant); + void removeParticipant(const LLUUID& participant_id); void clearParticipants(); LLConversationItemParticipant* findParticipant(const LLUUID& participant_id); void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted); + void setParticipantIsModerator(const LLUUID& participant_id, bool is_moderator); bool isLoaded() { return mIsLoaded; } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6511b0a1a6..35c1a34a26 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -52,11 +52,14 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; // helper function to update AvatarList Item's indicator in the voice participant list static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) { - LLAvatarListItem* item = dynamic_cast(avatar_list->getItemByValue(avatar_uuid)); - if (item) + if (avatar_list) { - LLOutputMonitorCtrl* indicator = item->getChild("speaking_indicator"); - indicator->setIsMuted(is_muted); + LLAvatarListItem* item = dynamic_cast(avatar_list->getItemByValue(avatar_uuid)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild("speaking_indicator"); + indicator->setIsMuted(is_muted); + } } } @@ -281,10 +284,13 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLParticipantList::~LLParticipantList() { - mAvatarListDoubleClickConnection.disconnect(); - mAvatarListRefreshConnection.disconnect(); - mAvatarListReturnConnection.disconnect(); - mAvatarListToggleIconsConnection.disconnect(); + if (mAvatarList) + { + mAvatarListDoubleClickConnection.disconnect(); + mAvatarListRefreshConnection.disconnect(); + mAvatarListReturnConnection.disconnect(); + mAvatarListToggleIconsConnection.disconnect(); + } // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged() // See ticket EXT-3427 @@ -300,16 +306,22 @@ LLParticipantList::~LLParticipantList() mParticipantListMenu = NULL; } - mAvatarList->setContextMenu(NULL); - mAvatarList->setComparator(NULL); + if (mAvatarList) + { + mAvatarList->setContextMenu(NULL); + mAvatarList->setComparator(NULL); + } delete mAvalineUpdater; } void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) { - mAvatarList->setSpeakingIndicatorsVisible(visible); -}; + if (mAvatarList) + { + mAvatarList->setSpeakingIndicatorsVisible(visible); + } +} void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) { @@ -330,82 +342,81 @@ void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { LLAvatarList* list = dynamic_cast(ctrl); - if (list) + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + const std::size_t moderator_indicator_len = moderator_indicator.length(); + + // Firstly remove moderators indicator + std::set::const_iterator + moderator_list_it = mModeratorToRemoveList.begin(), + moderator_list_end = mModeratorToRemoveList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) { - const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); - const std::size_t moderator_indicator_len = moderator_indicator.length(); - - // Firstly remove moderators indicator - std::set::const_iterator - moderator_list_it = mModeratorToRemoveList.begin(), - moderator_list_end = mModeratorToRemoveList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + LLAvatarListItem* item = (list ? dynamic_cast (list->getItemByValue(*moderator_list_it)) : NULL); + if ( item ) { - LLAvatarListItem* item = dynamic_cast (list->getItemByValue(*moderator_list_it)); - if ( item ) + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found != std::string::npos) { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found != std::string::npos) - { - name.erase(found, moderator_indicator_len); - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found != tooltip.npos) - { - tooltip.erase(found, moderator_indicator_len); - item->setAvatarToolTip(tooltip); - } + name.erase(found, moderator_indicator_len); + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found != tooltip.npos) + { + tooltip.erase(found, moderator_indicator_len); + item->setAvatarToolTip(tooltip); } } + setParticipantIsModerator(*moderator_list_it,false); + } - mModeratorToRemoveList.clear(); + mModeratorToRemoveList.clear(); - // Add moderators indicator - moderator_list_it = mModeratorList.begin(); - moderator_list_end = mModeratorList.end(); - for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + // Add moderators indicator + moderator_list_it = mModeratorList.begin(); + moderator_list_end = mModeratorList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = (list ? dynamic_cast (list->getItemByValue(*moderator_list_it)) : NULL); + if ( item ) { - LLAvatarListItem* item = dynamic_cast (list->getItemByValue(*moderator_list_it)); - if ( item ) + std::string name = item->getAvatarName(); + std::string tooltip = item->getAvatarToolTip(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) { - std::string name = item->getAvatarName(); - std::string tooltip = item->getAvatarToolTip(); - size_t found = name.find(moderator_indicator); - if (found == std::string::npos) - { - name += " "; - name += moderator_indicator; - item->setAvatarName(name); - } - found = tooltip.find(moderator_indicator); - if (found == std::string::npos) - { - tooltip += " "; - tooltip += moderator_indicator; - item->setAvatarToolTip(tooltip); - } + name += " "; + name += moderator_indicator; + item->setAvatarName(name); + } + found = tooltip.find(moderator_indicator); + if (found == std::string::npos) + { + tooltip += " "; + tooltip += moderator_indicator; + item->setAvatarToolTip(tooltip); } } + setParticipantIsModerator(*moderator_list_it,true); + } - // update voice mute state of all items. See EXT-7235 - LLSpeakerMgr::speaker_list_t speaker_list; + // update voice mute state of all items. See EXT-7235 + LLSpeakerMgr::speaker_list_t speaker_list; - // Use also participants which are not in voice session now (the second arg is TRUE). - // They can already have mModeratorMutedVoice set from the previous voice session - // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. - mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); - for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) - { - const LLPointer& speakerp = *it; + // Use also participants which are not in voice session now (the second arg is TRUE). + // They can already have mModeratorMutedVoice set from the previous voice session + // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. + mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); + for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) + { + const LLPointer& speakerp = *it; - if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) - { - setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); - update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); - } + if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + { + setParticipantIsMuted(speakerp->mID, speakerp->mModeratorMutedVoice); + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); } } } @@ -506,7 +517,7 @@ bool LLParticipantList::isHovered() { S32 x, y; LLUI::getMousePositionScreen(&x, &y); - return mAvatarList->calcScreenRect().pointInRect(x, y); + return (mAvatarList ? mAvatarList->calcScreenRect().pointInRect(x, y) : false); } bool LLParticipantList::onAddItemEvent(LLPointer event, const LLSD& userdata) @@ -525,21 +536,30 @@ bool LLParticipantList::onAddItemEvent(LLPointer event, co bool LLParticipantList::onRemoveItemEvent(LLPointer event, const LLSD& userdata) { - uuid_vec_t& group_members = mAvatarList->getIDs(); - uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()); - if(pos != group_members.end()) + LLUUID avatar_id = event->getValue().asUUID(); + if (mAvatarList) { - group_members.erase(pos); - mAvatarList->setDirty(); + uuid_vec_t& group_members = mAvatarList->getIDs(); + uuid_vec_t::iterator pos = std::find(group_members.begin(), group_members.end(), avatar_id); + if(pos != group_members.end()) + { + group_members.erase(pos); + mAvatarList->setDirty(); + } } + removeParticipant(avatar_id); return true; } bool LLParticipantList::onClearListEvent(LLPointer event, const LLSD& userdata) { - uuid_vec_t& group_members = mAvatarList->getIDs(); - group_members.clear(); - mAvatarList->setDirty(); + if (mAvatarList) + { + uuid_vec_t& group_members = mAvatarList->getIDs(); + group_members.clear(); + mAvatarList->setDirty(); + } + clearParticipants(); return true; } @@ -587,6 +607,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer event void LLParticipantList::sort() { + // *TODO : Merov : Need to plan for sort() for LLConversationModel if ( !mAvatarList ) return; @@ -631,7 +652,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); - if ( mAvatarList) + if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); mAvatarList->setDirty(); @@ -642,7 +663,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); // Create a participant view model instance and add it to the linked list participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); - if ( mAvatarList) + if (mAvatarList) { mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name); } @@ -808,7 +829,7 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl; return; } - LLAvatarListItem* item = dynamic_cast(mParent.mAvatarList->getItemByValue(speaker_id)); + LLAvatarListItem* item = (mParent.mAvatarList ? dynamic_cast(mParent.mAvatarList->getItemByValue(speaker_id)) : NULL); if (NULL == item) return; name = item->getAvatarName(); -- cgit v1.2.3 From ca7abc4c3be9310f4e5fec00b7d6ffadaba58ff0 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 29 Aug 2012 10:07:55 -0700 Subject: CHUI-280 : Add print out debug methods --- indra/newview/llconversationmodel.cpp | 16 ++++++++++++++++ indra/newview/llconversationmodel.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index dbf5ac6e03..d7f9093a4a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -159,6 +159,18 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip } } +void LLConversationItemSession::dumpDebugData() +{ + llinfos << "Merov debug : session, uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; + LLConversationItemParticipant* participant = NULL; + child_list_t::iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + participant = dynamic_cast(*iter); + participant->dumpDebugData(); + } +} + // // LLConversationItemParticipant // @@ -175,4 +187,8 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, { } +void LLConversationItemParticipant::dumpDebugData() +{ + llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; +} // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index aa79e5aeb0..af3756c45d 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -127,6 +127,8 @@ public: bool isLoaded() { return mIsLoaded; } + void dumpDebugData(); + private: bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; @@ -143,6 +145,8 @@ public: void setIsMuted(bool is_muted) { mIsMuted = is_muted; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + void dumpDebugData(); + private: bool mIsMuted; // default is false bool mIsModerator; // default is false -- cgit v1.2.3 From 9e1b5bcd2cf40e9efe381f7fea7d855924b0f11c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 29 Aug 2012 18:20:29 -0400 Subject: SH-3312 FIX - closing floater with outfit edit now has same behavior as explicitly leaving outfit edit with backarrow --- indra/newview/llfloatersidepanelcontainer.cpp | 22 ++++++++++++++++++++++ indra/newview/llfloatersidepanelcontainer.h | 2 ++ 2 files changed, 24 insertions(+) mode change 100644 => 100755 indra/newview/llfloatersidepanelcontainer.cpp mode change 100644 => 100755 indra/newview/llfloatersidepanelcontainer.h diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp old mode 100644 new mode 100755 index 5385977d95..3c966a073f --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -32,6 +32,8 @@ // newview includes #include "llsidetraypanelcontainer.h" #include "lltransientfloatermgr.h" +#include "llpaneloutfitedit.h" +#include "llsidepanelappearance.h" //static const std::string LLFloaterSidePanelContainer::sMainPanelName("main_panel"); @@ -54,6 +56,26 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key) getChild(sMainPanelName)->onOpen(key); } +void LLFloaterSidePanelContainer::onClickCloseBtn() +{ + llinfos << "close clicked" << llendl; + + LLPanelOutfitEdit* panel_outfit_edit = + dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); + if (panel_outfit_edit && panel_outfit_edit->getVisible()) + { + LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); + if (parent == this) + { + LLSidepanelAppearance* panel_appearance = + dynamic_cast(getPanel("appearance")); + panel_appearance->showOutfitsInventoryPanel(); + } + } + + LLFloater::onClickCloseBtn(); +} + LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) { LLView* view = findChildView(panel_name, true); diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h old mode 100644 new mode 100755 index 10d85867ce..491723471f --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -51,6 +51,8 @@ public: /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClickCloseBtn(); + LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); static void showPanel(const std::string& floater_name, const LLSD& key); -- cgit v1.2.3 From 9ff67f4a040fae53f28aa981309bce2356df1445 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 29 Aug 2012 18:27:21 -0700 Subject: CHUI-285 : WIP : Get the conversation floater to use the same LLParticipantList as the IM and call dialog --- indra/newview/llconversationmodel.h | 4 ++-- indra/newview/llimfloatercontainer.cpp | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index af3756c45d..1a2e09dfab 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -59,8 +59,8 @@ public: virtual LLPointer getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } - virtual BOOL isItemRenameable() const { return FALSE; } - virtual BOOL renameItem(const std::string& new_name) { return FALSE; } + virtual BOOL isItemRenameable() const { return TRUE; } + virtual BOOL renameItem(const std::string& new_name) { mName = new_name; return TRUE; } virtual BOOL isItemMovable( void ) const { return FALSE; } virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index a3f5e357c9..55cbf0b266 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -456,7 +456,9 @@ void LLIMFloaterContainer::repositioningWidgets() // CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { - std::string display_name = uuid.isNull()? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); + bool is_nearby_chat = uuid.isNull(); + + std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatTitle") : LLIMModel::instance().getName(uuid); // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) // Note: this happens often, when reattaching a torn off conversation for instance @@ -470,8 +472,21 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) // and nothing wrong will happen removing it if it doesn't exist removeConversationListItem(uuid,false); - // Create a conversation item - LLConversationItem* item = new LLConversationItemSession(display_name, uuid, getRootViewModel()); + // Create a conversation session model + LLConversationItem* item = NULL; + LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); + if (speaker_manager) + { + item = new LLParticipantList(speaker_manager, NULL, getRootViewModel(), true, false); + } + if (!item) + { + llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; + return; + } + // *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? + item->renameItem(display_name); + mConversationsItems[uuid] = item; // Create a widget from it -- cgit v1.2.3 From be61b5be2f4089e12ca25ca1ece13bd0fdaea543 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 29 Aug 2012 19:18:25 -0700 Subject: CHUI-305: Problem: The 'resident picker' had multiple parents and due to the design of the resident picker it can have only one parent. Having multiple parents caused both parents to fight for depth ordering...which caused the flickering. Resolution: Now multiple 'resident pickers' can exist and they are coupled to the floater that spawned then. Meaning that when the parent floater closes, the 'resident picker' floater will also close. In addition, a shadow frustum eminates from the button that opened the 'resident picker'. --- indra/llui/llfloater.cpp | 7 +++ indra/newview/llavataractions.cpp | 10 +++- indra/newview/llavataractions.h | 3 +- indra/newview/llfloateravatarpicker.cpp | 79 ++++++++++++++++++++++++++++++-- indra/newview/llfloateravatarpicker.h | 9 +++- indra/newview/llfloatercolorpicker.cpp | 2 +- indra/newview/llfloatergodtools.cpp | 6 ++- indra/newview/llfloaterland.cpp | 12 +++-- indra/newview/llfloaterregioninfo.cpp | 26 +++++++++-- indra/newview/llfloaterreporter.cpp | 7 ++- indra/newview/llfloatersellland.cpp | 3 +- indra/newview/llimfloater.cpp | 6 ++- indra/newview/llimfloatercontainer.cpp | 4 +- indra/newview/llinventorypanel.cpp | 2 +- indra/newview/llpanelblockedlist.cpp | 26 +++++++++-- indra/newview/llpanelblockedlist.h | 2 + indra/newview/llpanelgroupinvite.cpp | 6 ++- indra/newview/llpanelmaininventory.cpp | 2 +- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llpanelpeople.cpp | 20 +++++++- indra/newview/llpanelpeople.h | 3 ++ indra/newview/llsidepanelinventory.cpp | 2 +- 22 files changed, 201 insertions(+), 38 deletions(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8145d6d347..52812dc050 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -713,6 +713,13 @@ void LLFloater::closeFloater(bool app_quitting) make_ui_sound("UISndWindowClose"); } + //If floater is a dependent, remove it from parent (dependee) + LLFloater* dependee = mDependeeHandle.get(); + if (dependee) + { + dependee->removeDependentFloater(this); + } + // now close dependent floater for(handle_set_iter_t dependent_it = mDependents.begin(); dependent_it != mDependents.end(); ) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 93e8b9ca40..9a0c517ee0 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -744,12 +744,13 @@ std::set LLAvatarActions::getInventorySelectedUUIDs() } //static -void LLAvatarActions::shareWithAvatars() +void LLAvatarActions::shareWithAvatars(LLPanel * panel) { using namespace action_give_inventory; + LLFloater* root_floater = gFloaterView->getParentFloater(panel); LLFloaterAvatarPicker* picker = - LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE); + LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE, FALSE, root_floater->getName()); if (!picker) { return; @@ -757,6 +758,11 @@ void LLAvatarActions::shareWithAvatars() picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable)); picker->openFriendsTab(); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } LLNotificationsUtil::add("ShareNotification"); } diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 259e87c336..9d9ce966b5 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -37,6 +37,7 @@ class LLAvatarName; class LLInventoryPanel; class LLFloater; +class LLPanel; /** * Friend-related actions (add, remove, offer teleport, etc) @@ -117,7 +118,7 @@ public: /** * Share items with the picked avatars. */ - static void shareWithAvatars(); + static void shareWithAvatars(LLPanel * panel); /** * Block/unblock the avatar. diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 47acdf7057..4ac022e350 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -49,6 +49,8 @@ #include "llscrolllistcell.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" +#include "llfocusmgr.h" +#include "lldraghandle.h" #include "message.h" //#include "llsdserialize.h" @@ -56,14 +58,20 @@ //put it back as a member once the legacy path is out? static std::map sAvatarNameMap; +const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; +const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +const F32 CONTEXT_FADE_TIME = 0.08f; + LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect, - BOOL skip_agent) + BOOL skip_agent, + const std::string& name, + LLView * frustumOrigin) { // *TODO: Use a key to allow this not to be an effective singleton LLFloaterAvatarPicker* floater = - LLFloaterReg::showTypedInstance("avatar_picker"); + LLFloaterReg::showTypedInstance("avatar_picker", LLSD(name)); if (!floater) { llwarns << "Cannot instantiate avatar picker" << llendl; @@ -85,6 +93,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, floater->getChild("cancel_btn")->setLabel(close_string); } + if(frustumOrigin) + { + floater->mFrustumOrigin = frustumOrigin->getHandle(); + } + return floater; } @@ -93,7 +106,8 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE) + mCloseOnSelect(FALSE), + mContextConeOpacity ( 0.f ) { mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); } @@ -340,8 +354,67 @@ void LLFloaterAvatarPicker::populateFriend() friends_scroller->sortByColumnIndex(0, TRUE); } +void LLFloaterAvatarPicker::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, CONTEXT_CONE_IN_ALPHA * 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, CONTEXT_CONE_OUT_ALPHA * 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, CONTEXT_CONE_OUT_ALPHA * 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, CONTEXT_CONE_IN_ALPHA * 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, CONTEXT_CONE_OUT_ALPHA * 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, CONTEXT_CONE_IN_ALPHA * 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, CONTEXT_CONE_OUT_ALPHA * 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, CONTEXT_CONE_IN_ALPHA * 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(CONTEXT_FADE_TIME)); + } + else + { + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + } + } +} + void LLFloaterAvatarPicker::draw() { + drawFrustum(); + // sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars). // lets check this via mOkButtonValidateSignal callback periodically. static LLFrameTimer timer; diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 7067cd7b3e..46b685ad02 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -34,7 +34,7 @@ class LLAvatarName; class LLScrollListCtrl; -class LLFloaterAvatarPicker : public LLFloater +class LLFloaterAvatarPicker :public LLFloater { public: typedef boost::signals2::signal validate_signal_t; @@ -46,7 +46,9 @@ public: static LLFloaterAvatarPicker* show(select_callback_t callback, BOOL allow_multiple = FALSE, BOOL closeOnSelect = FALSE, - BOOL skip_agent = FALSE); + BOOL skip_agent = FALSE, + const std::string& name = "", + LLView * frustumOrigin = NULL); LLFloaterAvatarPicker(const LLSD& key); virtual ~LLFloaterAvatarPicker(); @@ -86,6 +88,7 @@ private: void setAllowMultiple(BOOL allow_multiple); LLScrollListCtrl* getActiveList(); + void drawFrustum(); virtual void draw(); virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -94,6 +97,8 @@ private: BOOL mNearMeListComplete; BOOL mCloseOnSelect; BOOL mExcludeAgentFromSearchResults; + LLHandle mFrustumOrigin; + F32 mContextConeOpacity; validate_signal_t mOkButtonValidateSignal; select_callback_t mSelectionCallback; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 05d73c2416..1cebdcffca 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -486,7 +486,7 @@ void LLFloaterColorPicker::draw() mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this); // draw context cone connecting color picker with color swatch in parent floater LLRect local_rect = getLocalRect(); - if (gFocusMgr.childHasKeyboardFocus(this) && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f) + if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLEnable(GL_CULL_FACE); diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index fb905eae11..51745fb191 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1123,11 +1123,13 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2)); + LLView * button = getChildView("Set Target"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2), FALSE, FALSE, FALSE, root_floater->getName(), button); // grandparent is a floater, which can have a dependent if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 55f3d548ec..64336b5cf7 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2733,11 +2733,13 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandAccess::onClickAddAccess() { + LLView * button = getChildView("add_allowed"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } @@ -2782,11 +2784,13 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) // static void LLPanelLandAccess::onClickAddBanned() { + LLView * button = getChildView("add_banned"); + LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)); + boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index fe29bb38c7..4aebd9a4f4 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -648,7 +648,7 @@ void LLPanelRegionGeneralInfo::onClickKick() // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -924,7 +924,12 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() void LLPanelRegionDebugInfo::onClickChooseAvatar() { - LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, parent_floater->getName()); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } @@ -1471,7 +1476,7 @@ void LLPanelEstateInfo::onClickKickUser() // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1646,8 +1651,21 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res } LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); + //Get parent floater name + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; + const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; + // avatar picker yes multi-select, yes close-on-select - LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), TRUE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), + TRUE, TRUE, FALSE, parent_floater_name); + + //Allows the closed parent floater to close the child floater (avatar picker) + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } + return false; } diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 3ec1e372eb..206bcb2c7e 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -285,10 +285,13 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) void LLFloaterReporter::onClickSelectAbuser() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ); + LLView * button = getChildView("select_abuser", TRUE); + + LLFloater * root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(this)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 64c0dfa023..2ac82c553b 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -392,7 +392,8 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) void LLFloaterSellLandUI::doSelectAgent() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE); + LLView * button = getChildView("sell_to_select_agent"); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE, FALSE, this->getName(), button); // grandparent is a floater, in order to set up dependency if (picker) { diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 1c6445610f..732a204ddf 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -359,7 +359,9 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); + LLView * button = getChildView("toolbar_panel")->getChildView("add_btn"); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); if (!picker) { return; @@ -367,7 +369,7 @@ void LLIMFloater::onAddButtonClicked() // Need to disable 'ok' button when selected users are already in conversation. picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); - LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) { root_floater->addDependentFloater(picker); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4d0bd623f8..bfe4afe80b 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -415,8 +415,10 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) void LLIMFloaterContainer::onAddButtonClicked() { - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE); + LLView * button = getChildView("conversations_pane_buttons_expanded")->getChildView("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); + if (picker && root_floater) { root_floater->addDependentFloater(picker); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 03dfada77c..2a84616ddf 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -147,7 +147,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2)); mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); } diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 35cda14f8d..8d03930699 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -66,10 +66,19 @@ LLPanelBlockedList::LLPanelBlockedList() mEnableCallbackRegistrar.add("Block.Check", boost::bind(&LLPanelBlockedList::isActionChecked, this, _2)); } +void LLPanelBlockedList::removePicker() +{ + if(mPicker.get()) + { + mPicker.get()->closeFloater(); + } +} + BOOL LLPanelBlockedList::postBuild() { mBlockedList = getChild("blocked"); mBlockedList->setCommitOnSelectionChange(TRUE); + this->setVisibleCallback(boost::bind(&LLPanelBlockedList::removePicker, this)); switch (gSavedSettings.getU32("BlockPeopleSortOrder")) { @@ -185,11 +194,18 @@ void LLPanelBlockedList::blockResidentByName() { const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select); - - // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed? - // old Floater dependency is not enable in panel - // addDependentFloater(picker); + + LLView * button = getChildView("plus_btn", TRUE); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker * picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), + allow_multiple, close_on_select, FALSE, root_floater->getName(), button); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } + + mPicker = picker->getHandle(); } void LLPanelBlockedList::blockObjectByName() diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 332349dfc0..07f0437656 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -61,6 +61,7 @@ private: E_SORT_BY_TYPE = 1, } ESortOrder; + void removePicker(); void updateButtons(); // UI callbacks @@ -78,6 +79,7 @@ private: private: LLBlockList* mBlockedList; + LLHandle mPicker; }; //----------------------------------------------------------------------------- diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 00dd206571..290e38ee1f 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -301,11 +301,13 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 + LLView * button = panelp->getChildView("add_button"); + LLFloater * root_floater = gFloaterView->getParentFloater(panelp); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE); + boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); if (picker) { - gFloaterView->getParentFloater(panelp)->addDependentFloater(picker); + root_floater->addDependentFloater(picker); } } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index eb3877da5a..35cb3d59c5 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -118,7 +118,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 82956beb3d..de12826452 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1498,7 +1498,7 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&do_nothing)); mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&do_nothing)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&do_nothing)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars)); + mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); } // Destroys the object diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 260de40eef..14045df42e 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -556,6 +556,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL } } + +void LLPanelPeople::removePicker() +{ + if(mPicker.get()) + { + mPicker.get()->closeFloater(); + } +} + BOOL LLPanelPeople::postBuild() { getChild("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); @@ -571,6 +580,7 @@ BOOL LLPanelPeople::postBuild() LLPanel* friends_tab = getChild(FRIENDS_TAB_NAME); // updater is active only if panel is visible to user. friends_tab->setVisibleCallback(boost::bind(&Updater::setActive, mFriendListUpdater, _2)); + friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::removePicker, this)); mOnlineFriendList = friends_tab->getChild("avatars_online"); mAllFriendList = friends_tab->getChild("avatars_all"); mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online")); @@ -1079,8 +1089,12 @@ bool LLPanelPeople::isItemsFreeOfFriends(const uuid_vec_t& uuids) void LLPanelPeople::onAddFriendWizButtonClicked() { + LLPanel* cur_panel = mTabContainer->getCurrentPanel(); + LLView * button = cur_panel->getChildView("friends_add_btn", TRUE); + // Show add friend wizard. - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); if (!picker) { return; @@ -1088,11 +1102,13 @@ void LLPanelPeople::onAddFriendWizButtonClicked() // Need to disable 'ok' button when friend occurs in selection picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); - LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) { root_floater->addDependentFloater(picker); } + + mPicker = picker->getHandle(); } void LLPanelPeople::onDeleteFriendButtonClicked() diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index da27f83074..4740964dee 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -68,6 +68,8 @@ private: E_SORT_BY_RECENT_SPEAKERS = 4, } ESortOrder; + void removePicker(); + // methods indirectly called by the updaters void updateFriendListHelpText(); void updateFriendList(); @@ -139,6 +141,7 @@ private: Updater* mNearbyListUpdater; Updater* mRecentListUpdater; Updater* mButtonsUpdater; + LLHandle< LLFloater > mPicker; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index acb232c77f..8915bb2fef 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -448,7 +448,7 @@ void LLSidepanelInventory::onInfoButtonClicked() void LLSidepanelInventory::onShareButtonClicked() { - LLAvatarActions::shareWithAvatars(); + LLAvatarActions::shareWithAvatars(this); } void LLSidepanelInventory::onShopButtonClicked() -- cgit v1.2.3 From 825cc7873251ad90720ab40221d689abed7b2ac8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 30 Aug 2012 17:36:03 -0400 Subject: log appearance update requests and results --- indra/newview/llappearancemgr.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2864338ef5..f71d9c7704 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2651,7 +2651,18 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { public: - RequestAgentUpdateAppearanceResponder() {} + RequestAgentUpdateAppearanceResponder() + { + llinfos << "request created" << llendl; + } + + // Successful completion. + /* virtual */ void result(const LLSD& content) + { + llinfos << "request OK" << llendl; + } + + // Error /*virtual*/ void error(U32 status, const std::string& reason) { llwarns << "appearance update request failed, reason: " << reason << llendl; -- cgit v1.2.3 From d67c295d8bb6cfd58655bf961dcf835157abb3e7 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 30 Aug 2012 16:20:27 -0700 Subject: CHUI-305: Minor changes after code review. Using templated findChild() instead of getChildView(). Also using settings.xml to store common custom variables. --- indra/newview/app_settings/settings.xml | 33 +++++++++++++++++++++++++++++++ indra/newview/llavataractions.cpp | 2 +- indra/newview/llavataractions.h | 4 ++-- indra/newview/llfloateravatarpicker.cpp | 35 ++++++++++++++++++--------------- indra/newview/llfloateravatarpicker.h | 3 +++ indra/newview/llfloatercolorpicker.cpp | 34 ++++++++++++++++++-------------- indra/newview/llfloatercolorpicker.h | 4 ++++ indra/newview/llfloatergodtools.cpp | 2 +- indra/newview/llfloaterland.cpp | 4 ++-- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llfloatersellland.cpp | 2 +- indra/newview/llimfloater.cpp | 2 +- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llpanelblockedlist.cpp | 2 +- indra/newview/llpanelgroupinvite.cpp | 2 +- indra/newview/llpanelpeople.cpp | 2 +- 16 files changed, 91 insertions(+), 44 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ab1ea6bdbc..b98fea7032 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1639,6 +1639,39 @@ Value + ContextConeInAlpha + + Comment + Cone In Alpha + Persist + 0 + Type + F32 + Value + 0.0 + + ContextConeOutAlpha + + Comment + Cone Out Alpha + Persist + 0 + Type + F32 + Value + 1.0 + + ContextConeFadeTime + + Comment + Cone Fade Time + Persist + 0 + Type + F32 + Value + .08 + ConversationHistoryPageSize Comment diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 9a0c517ee0..42a0376774 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -744,7 +744,7 @@ std::set LLAvatarActions::getInventorySelectedUUIDs() } //static -void LLAvatarActions::shareWithAvatars(LLPanel * panel) +void LLAvatarActions::shareWithAvatars(LLView * panel) { using namespace action_give_inventory; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 9d9ce966b5..473b9cecc3 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -37,7 +37,7 @@ class LLAvatarName; class LLInventoryPanel; class LLFloater; -class LLPanel; +class LLView; /** * Friend-related actions (add, remove, offer teleport, etc) @@ -118,7 +118,7 @@ public: /** * Share items with the picked avatars. */ - static void shareWithAvatars(LLPanel * panel); + static void shareWithAvatars(LLView * panel); /** * Block/unblock the avatar. diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 4ac022e350..3d6441553d 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -58,10 +58,6 @@ //put it back as a member once the legacy path is out? static std::map sAvatarNameMap; -const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_FADE_TIME = 0.08f; - LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect, @@ -106,10 +102,17 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE), - mContextConeOpacity ( 0.f ) + mCloseOnSelect(FALSE),a + mContextConeOpacity (0.f), + mContextConeInAlpha(0.f), + mContextConeOutAlpha(0.f), + mContextConeFadeTime(0.f) { mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); + + mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); + mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); + mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } BOOL LLFloaterAvatarPicker::postBuild() @@ -369,31 +372,31 @@ void LLFloaterAvatarPicker::drawFrustum() LLGLEnable(GL_CULL_FACE); gGL.begin(LLRender::QUADS); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + 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); } @@ -402,11 +405,11 @@ void LLFloaterAvatarPicker::drawFrustum() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } } } diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 46b685ad02..ed3e51c56f 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -99,6 +99,9 @@ private: BOOL mExcludeAgentFromSearchResults; LLHandle mFrustumOrigin; F32 mContextConeOpacity; + F32 mContextConeInAlpha; + F32 mContextConeOutAlpha; + F32 mContextConeFadeTime; validate_signal_t mOkButtonValidateSignal; select_callback_t mSelectionCallback; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 1cebdcffca..3c230bc58c 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -62,10 +62,6 @@ #include #include -const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_FADE_TIME = 0.08f; - ////////////////////////////////////////////////////////////////////////////// // // Class LLFloaterColorPicker @@ -105,7 +101,10 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mSwatch ( swatch ), mActive ( TRUE ), mCanApplyImmediately ( show_apply_immediate ), - mContextConeOpacity ( 0.f ) + mContextConeOpacity ( 0.f ), + mContextConeInAlpha ( 0.f ), + mContextConeOutAlpha ( 0.f ), + mContextConeFadeTime ( 0.f ) { buildFromFile ( "floater_color_picker.xml"); @@ -117,6 +116,10 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mApplyImmediateCheck->setEnabled(FALSE); mApplyImmediateCheck->set(FALSE); } + + mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); + mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); + mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } LLFloaterColorPicker::~LLFloaterColorPicker() @@ -492,31 +495,31 @@ void LLFloaterColorPicker::draw() LLGLEnable(GL_CULL_FACE); gGL.begin(LLRender::QUADS); { - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); - gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity); + 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, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity); + gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity); gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom); gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom); } @@ -525,11 +528,12 @@ void LLFloaterColorPicker::draw() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), + LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); } mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index 8e387c4f7c..bab0617712 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -189,6 +189,10 @@ class LLFloaterColorPicker LLButton* mPipetteBtn; F32 mContextConeOpacity; + F32 mContextConeInAlpha; + F32 mContextConeOutAlpha; + F32 mContextConeFadeTime; + }; #endif // LL_LLFLOATERCOLORPICKER_H diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index 51745fb191..38abdcc830 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1123,7 +1123,7 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { - LLView * button = getChildView("Set Target"); + LLView * button = findChild("Set Target"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2), FALSE, FALSE, FALSE, root_floater->getName(), button); // grandparent is a floater, which can have a dependent diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 64336b5cf7..4fc6684e8e 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2733,7 +2733,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) void LLPanelLandAccess::onClickAddAccess() { - LLView * button = getChildView("add_allowed"); + LLView * button = findChild("add_allowed"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); @@ -2784,7 +2784,7 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) // static void LLPanelLandAccess::onClickAddBanned() { - LLView * button = getChildView("add_banned"); + LLView * button = findChild("add_banned"); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1), FALSE, FALSE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 206bcb2c7e..cf2481f99a 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -285,7 +285,7 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) void LLFloaterReporter::onClickSelectAbuser() { - LLView * button = getChildView("select_abuser", TRUE); + LLView * button = findChild("select_abuser", TRUE); LLFloater * root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 2ac82c553b..484ecbcd04 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -392,7 +392,7 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) void LLFloaterSellLandUI::doSelectAgent() { - LLView * button = getChildView("sell_to_select_agent"); + LLView * button = findChild("sell_to_select_agent"); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE, FALSE, this->getName(), button); // grandparent is a floater, in order to set up dependency if (picker) diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 732a204ddf..a601561c62 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -359,7 +359,7 @@ BOOL LLIMFloater::postBuild() void LLIMFloater::onAddButtonClicked() { - LLView * button = getChildView("toolbar_panel")->getChildView("add_btn"); + LLView * button = findChild("toolbar_panel")->findChild("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE, FALSE, root_floater->getName(), button); if (!picker) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index fe00f70a28..d382b61921 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -415,7 +415,7 @@ void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) void LLIMFloaterContainer::onAddButtonClicked() { - LLView * button = getChildView("conversations_pane_buttons_expanded")->getChildView("add_btn"); + LLView * button = findChild("conversations_pane_buttons_expanded")->findChild("add_btn"); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE, TRUE, root_floater->getName(), button); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 8d03930699..7612af8f5e 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -195,7 +195,7 @@ void LLPanelBlockedList::blockResidentByName() const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - LLView * button = getChildView("plus_btn", TRUE); + LLView * button = findChild("plus_btn", TRUE); LLFloater* root_floater = gFloaterView->getParentFloater(this); LLFloaterAvatarPicker * picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 290e38ee1f..36bd5d9b77 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -301,7 +301,7 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 - LLView * button = panelp->getChildView("add_button"); + LLView * button = panelp->findChild("add_button"); LLFloater * root_floater = gFloaterView->getParentFloater(panelp); LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 14045df42e..90e857265d 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1090,7 +1090,7 @@ bool LLPanelPeople::isItemsFreeOfFriends(const uuid_vec_t& uuids) void LLPanelPeople::onAddFriendWizButtonClicked() { LLPanel* cur_panel = mTabContainer->getCurrentPanel(); - LLView * button = cur_panel->getChildView("friends_add_btn", TRUE); + LLView * button = cur_panel->findChild("friends_add_btn", TRUE); // Show add friend wizard. LLFloater* root_floater = gFloaterView->getParentFloater(this); -- cgit v1.2.3 From 1aadf94fe44036d6012eb7d4f8a0b9288a719f37 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 30 Aug 2012 17:24:19 -0700 Subject: CHUI-305: Now the Region/Estate floater displays the frustum shadow when opening the Resident Picker. --- indra/newview/llfloateravatarpicker.cpp | 2 +- indra/newview/llfloaterregioninfo.cpp | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 3d6441553d..2152de1035 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -102,7 +102,7 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), mNearMeListComplete(FALSE), - mCloseOnSelect(FALSE),a + mCloseOnSelect(FALSE), mContextConeOpacity (0.f), mContextConeInAlpha(0.f), mContextConeOutAlpha(0.f), diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4aebd9a4f4..e6b76159a1 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -647,8 +647,10 @@ void LLPanelRegionGeneralInfo::onClickKick() // this depends on the grandparent view being a floater // in order to set up floater dependency + LLView * button = findChild("kick_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -924,8 +926,10 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() void LLPanelRegionDebugInfo::onClickChooseAvatar() { + LLView * button = findChild("choose_avatar_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1475,8 +1479,10 @@ void LLPanelEstateInfo::onClickKickUser() { // this depends on the grandparent view being a floater // in order to set up floater dependency + LLView * button = findChild("kick_user_from_estate_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName()); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), + FALSE, TRUE, FALSE, parent_floater->getName(), button); if (child_floater) { parent_floater->addDependentFloater(child_floater); @@ -1656,9 +1662,27 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; + //Determine the button that triggered opening of the avatar picker + //(so that a shadow frustum from the button to the avatar picker can be created) + LLView * button = NULL; + switch(change_info->mOperationFlag) + { + case ESTATE_ACCESS_ALLOWED_AGENT_ADD: + button = panel->findChild("add_allowed_avatar_btn"); + break; + + case ESTATE_ACCESS_BANNED_AGENT_ADD: + button = panel->findChild("add_banned_avatar_btn"); + break; + + case ESTATE_ACCESS_MANAGER_ADD: + button = panel->findChild("add_estate_manager_btn"); + break; + } + // avatar picker yes multi-select, yes close-on-select LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), - TRUE, TRUE, FALSE, parent_floater_name); + TRUE, TRUE, FALSE, parent_floater_name, button); //Allows the closed parent floater to close the child floater (avatar picker) if (child_floater) -- cgit v1.2.3 From ab37263a5cda14227724181c771ac1d3ef55f467 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 30 Aug 2012 21:34:48 -0700 Subject: CHUI-285 : LLIMFloaterContainer is now using LLParticipantList fully --- indra/llui/llfolderviewmodel.h | 11 +++-- indra/newview/llimfloatercontainer.cpp | 85 +++++++++++++++++++++++++++++++--- indra/newview/llimfloatercontainer.h | 4 +- indra/newview/llparticipantlist.cpp | 13 ++++-- 4 files changed, 99 insertions(+), 14 deletions(-) diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 16d9c86fd7..22bfc4dfb4 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -209,6 +209,7 @@ protected: }; + class LLFolderViewModelItemCommon : public LLFolderViewModelItem { public: @@ -249,6 +250,8 @@ public: std::string::size_type getFilterStringOffset(); std::string::size_type getFilterStringSize(); + typedef std::list child_list_t; + virtual void addChild(LLFolderViewModelItem* child) { mChildren.push_back(child); @@ -271,7 +274,11 @@ public: mChildren.clear(); dirtyFilter(); } - + + child_list_t::const_iterator getChildrenBegin() const { return mChildren.begin(); } + child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } + child_list_t::size_type getChildrenCount() const { return mChildren.size(); } + void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { mPassedFilter = passed; @@ -325,8 +332,6 @@ protected: S32 mLastFolderFilterGeneration; S32 mMostFilteredDescendantGeneration; - - typedef std::list child_list_t; child_list_t mChildren; LLFolderViewModelItem* mParent; LLFolderViewModelInterface& mRootViewModel; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 55cbf0b266..aa85e5023d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -442,14 +442,36 @@ void LLIMFloaterContainer::repositioningWidgets() int index = 0; for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); - widget_it++, ++index) + widget_it++) { - LLFolderViewItem* widget = widget_it->second; + LLFolderViewFolder* widget = dynamic_cast(widget_it->second); widget->setVisible(TRUE); widget->setRect(LLRect(0, panel_rect.getHeight() - item_height*index, panel_rect.getWidth(), panel_rect.getHeight() - item_height*(index+1))); + index++; + // Reposition the children as well + // Merov : This is highly suspiscious but gets the debug hack to work. This needs to be revised though. + if (widget->getItemsCount() != 0) + { + BOOL is_open = widget->isOpen(); + widget->setOpen(TRUE); + LLFolderViewFolder::items_t::const_iterator current = widget->getItemsBegin(); + LLFolderViewFolder::items_t::const_iterator end = widget->getItemsEnd(); + while (current != end) + { + LLFolderViewItem* item = (*current); + item->setVisible(TRUE); + item->setRect(LLRect(0, + panel_rect.getHeight() - item_height*index, + panel_rect.getWidth(), + panel_rect.getHeight() - item_height*(index+1))); + index++; + current++; + } + widget->setOpen(is_open); + } } } @@ -490,19 +512,51 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) mConversationsItems[uuid] = item; // Create a widget from it - LLFolderViewItem* widget = createConversationItemWidget(item); + LLConversationViewSession* widget = createConversationItemWidget(item); mConversationsWidgets[uuid] = widget; - // Add a new conversation widget to the root folder of a folder view. + // Add a new conversation widget to the root folder of the folder view widget->addToFolder(mConversationsRoot); // Add it to the UI + mConversationsListPanel->addChild(widget); widget->setVisible(TRUE); + + // Create the participants widgets now + // Note: usually, we do not get an updated avatar list at that point + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); + llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl; + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast(*current_participant_model); + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + current_participant_model++; + } + // Debugging hack : uncomment to force the creation of a dummy participant + // This hack is to be eventually deleted + if (item->getChildrenCount() == 0) + { + llinfos << "Merov debug : create dummy participant" << llendl; + // Create a dummy participant : we let that leak but that's just for debugging... + std::string name("Debug Test : "); + name += display_name; + LLUUID test_id; + test_id.generate(name); + LLConversationItemParticipant* participant_model = new LLConversationItemParticipant(name, test_id, getRootViewModel()); + // Create the dummy widget + LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(widget); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + } + // End debugging hack repositioningWidgets(); - mConversationsListPanel->addChild(widget); - return; } @@ -537,7 +591,7 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c } } -LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) +LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) { LLConversationViewSession::Params params; @@ -554,4 +608,21 @@ LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversat return LLUICtrlFactory::create(params); } +LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) +{ + LLConversationViewSession::Params params; + + params.name = item->getDisplayName(); + //params.icon = bridge->getIcon(); + //params.icon_open = bridge->getOpenIcon(); + //params.creation_date = bridge->getCreationDate(); + params.root = mConversationsRoot; + params.listener = item; + params.rect = LLRect (0, 0, 0, 0); + params.tool_tip = params.name; + params.container = this; + + return LLUICtrlFactory::create(params); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index d6dda8ea2d..300a820a26 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -37,6 +37,7 @@ #include "llgroupmgr.h" #include "lltrans.h" #include "llconversationmodel.h" +#include "llconversationview.h" class LLButton; class LLLayoutPanel; @@ -113,7 +114,8 @@ public: void addConversationListItem(const LLUUID& uuid); private: - LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); + LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); // Conversation list data LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 35c1a34a26..fa3432fc89 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -648,10 +648,10 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) if (is_avatar) { - // Create a participant view model instance and add it to the linked list + // Create a participant view model instance LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); - participant = new LLConversationItemParticipant(!has_name ? "Avatar" : avatar_name.mDisplayName , avatar_id, mRootViewModel); + participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); @@ -661,7 +661,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) else { std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); - // Create a participant view model instance and add it to the linked list + // Create a participant view model instance participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); if (mAvatarList) { @@ -672,6 +672,13 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) + + // *TODO : Merov : need to update the online/offline status of the participant. + // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) + + llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl; + + // Add the participant model to the session's children list addParticipant(participant); adjustParticipant(avatar_id); -- cgit v1.2.3 From dab6788c42260135d298b619ff92a71838bba2b8 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 31 Aug 2012 11:57:36 +0300 Subject: CHUI-157 FIXED (Implement menu bar for conversation floater) - Added View Nearby chat history option - Also replaced menu item "Add Friend / Remove" with two separate menus: Add Friend and Remove Friend. So if user is a Friend the Remove Friend option would be shown there. If the user is not a friend, the Add Friend option would be shown. --- indra/newview/llconversationloglist.cpp | 17 ++++++--- indra/newview/llfloaterconversationlog.cpp | 5 +++ indra/newview/llfloaterconversationpreview.cpp | 40 ++++++++++++---------- indra/newview/llfloaterconversationpreview.h | 2 +- .../default/xui/en/menu_conversation_log_gear.xml | 28 +++++++++------ .../default/xui/en/menu_conversation_log_view.xml | 8 +++++ 6 files changed, 66 insertions(+), 34 deletions(-) diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 257ec082a5..94be9055bd 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -241,15 +241,18 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata) { LLAvatarActions::offerTeleport(selected_id); } - else if("add_rem_friend" == command_name) + else if("add_friend" == command_name) { - if (LLAvatarActions::isFriend(selected_id)) + if (!LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::removeFriendDialog(selected_id); + LLAvatarActions::requestFriendshipDialog(selected_id); } - else + } + else if("remove_friend" == command_name) + { + if (LLAvatarActions::isFriend(selected_id)) { - LLAvatarActions::requestFriendshipDialog(selected_id); + LLAvatarActions::removeFriendDialog(selected_id); } } else if ("invite_to_group" == command_name) @@ -336,6 +339,10 @@ bool LLConversationLogList::isActionChecked(const LLSD& userdata) { return is_p2p && LLAvatarActions::isFriend(selected_id); } + else if ("is_not_friend" == command_name) + { + return is_p2p && !LLAvatarActions::isFriend(selected_id); + } return false; } diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index c77a9e74bb..4375ce5726 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -28,6 +28,7 @@ #include "llconversationloglist.h" #include "llfiltereditor.h" #include "llfloaterconversationlog.h" +#include "llfloaterreg.h" #include "llmenubutton.h" LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) @@ -97,6 +98,10 @@ void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) { mConversationLogList->toggleSortFriendsOnTop(); } + else if ("view_nearby_chat_history" == command_name) + { + LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); + } } bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index ae6f1441eb..7083fb987d 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "lltrans.h" LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), @@ -44,20 +45,28 @@ BOOL LLFloaterConversationPreview::postBuild() getChild("more_history")->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); - if (conv) - { - std::string name = conv->getConversationName(); - LLStringUtil::format_map_t args; - args["[NAME]"] = name; - std::string title = getString("Title", args); - setTitle(title); + std::string name; + std::string file; - getChild("description")->setValue(name); + if (mSessionID != LLUUID::null && conv) + { + name = conv->getConversationName(); + file = conv->getHistoryFileName(); + } + else + { + name = LLTrans::getString("NearbyChatTitle"); + file = "chat"; } - std::string file = conv->getHistoryFileName(); - LLLogChat::loadChatHistory(file, mMessages, true); + LLStringUtil::format_map_t args; + args["[NAME]"] = name; + std::string title = getString("Title", args); + setTitle(title); + + getChild("description")->setValue(name); + LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; return LLFloater::postBuild(); @@ -68,7 +77,7 @@ void LLFloaterConversationPreview::draw() LLFloater::draw(); } -void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +void LLFloaterConversationPreview::onOpen(const LLSD& key) { showHistory(); } @@ -88,13 +97,8 @@ void LLFloaterConversationPreview::showHistory() int delta = 0; if (mCurrentPage) { - // stinson 08/28/2012 : This operation could be simplified using integer math with the mod (%) operator. - // e.g. The following code should give the same output. - // int remainder = mMessages.size() % mPageSize; - // delta = (remainder == 0) ? 0 : (mPageSize - remainder); - // Though without examining further, the remainder might be a more appropriate value. - double num_of_pages = static_cast(mMessages.size()) / static_cast(mPageSize); - delta = static_cast((ceil(num_of_pages) - num_of_pages) * static_cast(mPageSize)); + int remainder = mMessages.size() % mPageSize; + delta = (remainder == 0) ? 0 : (mPageSize - remainder); } std::advance(iter, (mCurrentPage * mPageSize) - delta); diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 5105ef3702..2246a44761 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -39,7 +39,7 @@ public: virtual BOOL postBuild(); virtual void draw(); - virtual void onOpen(const LLSD& session_id); + virtual void onOpen(const LLSD& key); private: void onMoreHistoryBtnClick(); diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml index b8d0eef956..8796b87955 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -57,20 +57,28 @@ parameter="can_offer_teleport"/> - - + - + + + + + - - + + + + + -- cgit v1.2.3 From c2bb1a189c5f4c2367ee38e03371b28948e3ea81 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 31 Aug 2012 12:05:36 +0300 Subject: CHUI-154 FIXED (Add link to chat preferences from Conversation floater) - Added link to chat preferences from Conversation floater --- indra/newview/llimfloatercontainer.cpp | 22 ++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 2 ++ .../skins/default/xui/en/menu_participant_view.xml | 7 +++++++ 3 files changed, 31 insertions(+) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index aa85e5023d..f85b60cb36 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -40,6 +40,7 @@ #include "llavatarnamecache.h" #include "llgroupiconctrl.h" #include "llfloateravatarpicker.h" +#include "llfloaterpreference.h" #include "llimview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" @@ -53,6 +54,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mExpandCollapseBtn(NULL), mConversationsRoot(NULL) { + mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); + // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -435,6 +438,25 @@ void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) } } +void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + if ("chat_preferences" == command) + { + LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance("preferences"); + if (floater_prefs) + { + LLTabContainer* tab_container = floater_prefs->getChild("pref core"); + LLPanel* chat_panel = tab_container->getPanelByName("chat"); + if (tab_container && chat_panel) + { + tab_container->selectTabPanel(chat_panel); + } + } + } +} + void LLIMFloaterContainer::repositioningWidgets() { LLRect panel_rect = mConversationsListPanel->getRect(); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 300a820a26..a72a3e2221 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -103,6 +103,8 @@ private: void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); + void onCustomAction (const LLSD& userdata); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 6401b0e3b7..df2700c94c 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -2,6 +2,13 @@ + + + Date: Fri, 31 Aug 2012 16:52:50 +0300 Subject: CHUI-315 (Nearby chat messages do not appear in conversation floater): cancelled inheritance LLNearbyChat from LLSingleton; set mSingleInstance flag for it. --- indra/llui/llfloater.cpp | 7 ++++++ indra/llui/llfloater.h | 1 + indra/newview/llagent.cpp | 6 +++-- indra/newview/llchatitemscontainerctrl.cpp | 4 ++-- indra/newview/llfloatertranslationsettings.cpp | 3 ++- indra/newview/llgesturemgr.cpp | 4 +++- indra/newview/llimconversation.cpp | 31 +++++++++++++------------- indra/newview/llimview.cpp | 6 +++-- indra/newview/llnearbychat.cpp | 21 +++++++++-------- indra/newview/llnearbychat.h | 4 +--- indra/newview/llnearbychathandler.cpp | 5 +++-- indra/newview/llnotificationhandlerutil.cpp | 5 +++-- indra/newview/llnotificationtiphandler.cpp | 3 ++- indra/newview/llviewergesture.cpp | 4 +++- indra/newview/llviewerkeyboard.cpp | 3 ++- indra/newview/llviewermessage.cpp | 8 ++++--- indra/newview/llviewerwindow.cpp | 10 +++++---- 17 files changed, 76 insertions(+), 49 deletions(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 52812dc050..029c47c726 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -627,6 +627,13 @@ void LLFloater::setVisible( BOOL visible ) storeVisibilityControl(); } + +void LLFloater::setIsSingleInstance(BOOL is_single_instance) +{ + mSingleInstance = is_single_instance; +} + + // virtual void LLFloater::handleVisibilityChange ( BOOL new_visibility ) { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a1cac64a4a..4b738f88ea 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -217,6 +217,7 @@ public: /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); /*virtual*/ void setRect(const LLRect &rect); + void setIsSingleInstance(BOOL is_single_instance); void initFloater(const Params& p); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index be6901c36a..bb0dbc7ff0 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1911,7 +1911,8 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_START, FALSE); + (LLFloaterReg::getTypedInstance("nearby_chat"))-> + sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -1923,7 +1924,8 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - (LLNearbyChat::instance()).sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + (LLFloaterReg::getTypedInstance("nearby_chat"))-> + sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index e6340e0fa3..f1b5c42ef3 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,12 @@ BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - LLNearbyChat::instance().showHistory(); + (LLFloaterReg::getTypedInstance("nearby_chat"))->showHistory(); return FALSE; } } - LLNearbyChat::instance().showHistory(); + (LLFloaterReg::getTypedInstance("nearby_chat"))->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index b5b86dadc2..29d7732a68 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,7 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - LLNearbyChat::instance().showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + (LLFloaterReg::getTypedInstance("nearby_chat"))-> + showTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 0377337af6..0996af6125 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -35,6 +35,7 @@ // library #include "llaudioengine.h" #include "lldatapacker.h" +#include "llfloaterreg.h" #include "llinventory.h" #include "llkeyframemotion.h" #include "llmultigesture.h" @@ -997,7 +998,8 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLNearbyChat::instance().sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + (LLFloaterReg::getTypedInstance("nearby_chat"))-> + sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 7bb29be27b..5a5196fb7e 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -144,7 +144,7 @@ BOOL LLIMConversation::postBuild() updateHeaderAndToolbar(); - mSaveRect = isTornOff(); + mSaveRect = !getHost(); initRectControl(); if (isChatMultiTab()) @@ -267,11 +267,11 @@ void LLIMConversation::hideOrShowTitle() LLView* floater_contents = getChild("contents_view"); LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); + S32 top_border_of_contents = floater_rect.mTop - (getHost()? 0 : floater_header_size); LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(isTornOff()); + mDragHandle->setVisible(!getHost()); floater_contents->setShape(contents_rect); } @@ -289,8 +289,8 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_torn_off = !getHost(); - if (!is_torn_off) + bool is_hosted = !!getHost(); + if (is_hosted) { hideAllStandardButtons(); } @@ -299,7 +299,7 @@ void LLIMConversation::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - is_torn_off + !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -307,21 +307,21 @@ void LLIMConversation::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = !is_torn_off || is_participant_list_visible; + bool is_expanded = is_hosted || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(is_torn_off); + mDragHandle->setTitleVisible(!is_hosted); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + mTearOffBtn->setImageOverlay(getString(is_hosted? "tear_off_icon" : "return_icon")); - mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); enableDisableCallBtn(); @@ -358,9 +358,10 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().reloadMessages(); + nearby_chat->reloadMessages(); } } @@ -427,8 +428,8 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); - mSaveRect = isTornOff(); + setFollows(getHost()? FOLLOWS_NONE : FOLLOWS_ALL); + mSaveRect = !getHost(); initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index effcc9a826..f5392b442a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2486,9 +2486,11 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - if (LLNearbyChat::instanceExists()) + + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().addMessage(chat); + nearby_chat->addMessage(chat); } } else // going to IM session diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index f1518fe825..25bbc82fee 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -134,6 +134,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mKey = LLSD(); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); setName("nearby_chat"); + setIsSingleInstance(TRUE); } //virtual @@ -780,20 +781,21 @@ void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BO // static void LLNearbyChat::startChat(const char* line) { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat) { - (LLNearbyChat::instance()).show(); - (LLNearbyChat::instance()).setVisible(TRUE); - (LLNearbyChat::instance()).setFocus(TRUE); - (LLNearbyChat::instance().mInputEditor)->setFocus(TRUE); + nearby_chat->show(); + nearby_chat->setVisible(TRUE); + nearby_chat->setFocus(TRUE); + nearby_chat->mInputEditor->setFocus(TRUE); if (line) { std::string line_string(line); - (LLNearbyChat::instance().mInputEditor)->setText(line_string); + nearby_chat->mInputEditor->setText(line_string); } - (LLNearbyChat::instance().mInputEditor)->endOfDoc(); + nearby_chat->mInputEditor->endOfDoc(); } } @@ -801,9 +803,10 @@ void LLNearbyChat::startChat(const char* line) // static void LLNearbyChat::stopChat() { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat) { - (LLNearbyChat::instance().mInputEditor)->setFocus(FALSE); + nearby_chat->mInputEditor->setFocus(FALSE); gAgent.stopTyping(); } } diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 379bfbee4b..4fc5cb7f76 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -35,15 +35,13 @@ #include "lloutputmonitorctrl.h" #include "llspeakers.h" #include "llscrollbar.h" -#include "llsingleton.h" #include "llviewerchat.h" #include "llpanel.h" class LLResizeBar; class LLNearbyChat - : public LLIMConversation, - public LLSingleton + : public LLIMConversation { public: // constructor for inline chat-bars (e.g. hosted in chat history window) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 37f4cc4c19..ca3fffeffd 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -537,7 +537,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } - LLNearbyChat::instance().addMessage(chat_msg, true, args); + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + nearby_chat->addMessage(chat_msg, true, args); if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull() @@ -553,7 +554,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Send event on to LLEventStream sChatWatcher->post(chat); - if( LLNearbyChat::instance().isInVisibleChain() + if( nearby_chat->isInVisibleChain() || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT && gSavedSettings.getBOOL("UseChatBubbles") ) || mChannel.isDead() diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index db8e917435..2484040ac4 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,13 +181,14 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat) { LLChat chat_msg(notification->getMessage()); chat_msg.mSourceType = type; chat_msg.mFromName = SYSTEM_FROM; chat_msg.mFromID = LLUUID::null; - LLNearbyChat::instance().addMessage(chat_msg); + nearby_chat->addMessage(chat_msg); } } diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 67fc9b27dc..ef6668247c 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -85,7 +85,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); // don't show toast if Nearby Chat is opened - if (LLNearbyChat::instance().isChatVisible()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat && nearby_chat->isChatVisible()) { return false; } diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a2dea31d9b..71608b5280 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -33,6 +33,7 @@ #include "llviewerinventory.h" #include "sound_ids.h" // for testing +#include "llfloaterreg.h" #include "llkeyboard.h" // for key shortcuts for testing #include "llinventorymodel.h" #include "llvoavatar.h" @@ -130,7 +131,8 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLNearbyChat::instance().sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + (LLFloaterReg::getTypedInstance("nearby_chat"))-> + sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 7105720eb4..f8e988bc0c 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llappviewer.h" +#include "llfloaterreg.h" #include "llviewerkeyboard.h" #include "llmath.h" #include "llagent.h" @@ -543,7 +544,7 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) { - if (LLNearbyChat::instance().getCurrentChat().empty()) + if ((LLFloaterReg::getTypedInstance("nearby_chat"))->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' LLNearbyChat::startChat("/"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9abd269f0f..81cbc3b6c3 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2297,9 +2297,10 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m // Treat like a system message and put in chat history. chat.mText = av_name.getCompleteName() + ": " + message; - if (LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if (nearby_chat) { - LLNearbyChat::instance().addMessage(chat); + nearby_chat->addMessage(chat); } } @@ -2895,7 +2896,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. - if(!chat_from_system && LLNearbyChat::instanceExists()) + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + if(!chat_from_system && nearby_chat) { chat.mOwnerID = from_id; LLSD args; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 23d2b1633d..791cadaee4 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2493,12 +2493,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + // Traverses up the hierarchy if( keyboard_focus ) { - if (LLNearbyChat::instanceExists()) + if (nearby_chat) { - LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); + LLChatEntry* chat_editor = nearby_chat->getChatBox(); // arrow keys move avatar while chatting hack if (chat_editor && chat_editor->hasFocus()) @@ -2562,11 +2564,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLChatEntry* chat_editor = LLNearbyChat::instance().getChatBox(); + LLChatEntry* chat_editor = nearby_chat->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. - LLNearbyChat::instance().startChat(NULL); + nearby_chat->startChat(NULL); return TRUE; } } -- cgit v1.2.3 From 73769180f363556d5517e3070fc4a2ac61e713d6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 31 Aug 2012 19:22:41 +0300 Subject: CHUI-298 FIXED (Conversation started as an IM and then goes to voice call does not show as call in conversation log) - Show voice icon when call is started - Added flag LLConversation::mIsConversationPast which means that this conversation is finished and any of its data can't be changed. I.e. it cannot be reused. - When session removed (i.e. finished) corresponding conversation is marked as Past conversation. I.e. mIsConversationPast is true. - Added changed(const LLUUID& session_id, U32 mask) method to LLConversationLog to notify particular conversation. This is used in LLConversationLogList to update its particular item and not to rebuild the whole list. --- indra/newview/llconversationlog.cpp | 54 ++++++++++++++++++++++++++++++- indra/newview/llconversationlog.h | 25 ++++++++++---- indra/newview/llconversationloglist.cpp | 22 +++++++++++++ indra/newview/llconversationloglist.h | 1 + indra/newview/llconversationloglistitem.h | 4 +-- indra/newview/llvoicechannel.cpp | 2 +- indra/newview/llvoicechannel.h | 2 +- 7 files changed, 99 insertions(+), 11 deletions(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 486cea4064..23ccc78a0f 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -33,7 +33,8 @@ struct Conversation_params { Conversation_params(time_t time) : mTime(time), - mTimestamp(LLConversation::createTimestamp(time)) + mTimestamp(LLConversation::createTimestamp(time)), + mIsConversationPast(true) {} time_t mTime; @@ -44,6 +45,7 @@ struct Conversation_params LLUUID mSessionID; LLUUID mParticipantID; bool mIsVoice; + bool mIsConversationPast; bool mHasOfflineIMs; }; @@ -60,6 +62,7 @@ LLConversation::LLConversation(const Conversation_params& params) mSessionID(params.mSessionID), mParticipantID(params.mParticipantID), mIsVoice(params.mIsVoice), + mIsConversationPast(params.mIsConversationPast), mHasOfflineIMs(params.mHasOfflineIMs) { setListenIMFloaterOpened(); @@ -74,6 +77,7 @@ LLConversation::LLConversation(const LLIMModel::LLIMSession& session) mSessionID(session.mSessionID), mParticipantID(session.mOtherParticipantID), mIsVoice(session.mStartedAsIMCall), + mIsConversationPast(false), mHasOfflineIMs(session.mHasOfflineMessage) { setListenIMFloaterOpened(); @@ -89,6 +93,7 @@ LLConversation::LLConversation(const LLConversation& conversation) mSessionID = conversation.getSessionID(); mParticipantID = conversation.getParticipantID(); mIsVoice = conversation.isVoice(); + mIsConversationPast = conversation.isConversationPast(); mHasOfflineIMs = conversation.hasOfflineMessages(); setListenIMFloaterOpened(); @@ -99,6 +104,14 @@ LLConversation::~LLConversation() mIMFloaterShowedConnection.disconnect(); } +void LLConversation::setIsVoice(bool is_voice) +{ + if (mIsConversationPast) + return; + + mIsVoice = is_voice; +} + void LLConversation::onIMFloaterShown(const LLUUID& session_id) { if (mSessionID == session_id) @@ -228,6 +241,21 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string { LLConversation conversation(*session); LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + } +} + +void LLConversationLog::sessionRemoved(const LLUUID& session_id) +{ + conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); + + for (; rev_iter != mConversations.rend(); ++rev_iter) + { + if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast()) + { + rev_iter->setIsPast(true); + return; // return here because only one session with session_id may be active + } } } @@ -350,3 +378,27 @@ void LLConversationLog::notifyObservers() (*iter)->changed(); } } + +void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask) +{ + std::set::const_iterator iter = mObservers.begin(); + for (; iter != mObservers.end(); ++iter) + { + (*iter)->changed(session_id, mask); + } +} + +void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state) +{ + conversations_vec_t::reverse_iterator rev_iter = mConversations.rbegin(); + + for (; rev_iter != mConversations.rend(); ++rev_iter) + { + if (rev_iter->getSessionID() == session_id && !rev_iter->isConversationPast() && LLVoiceChannel::STATE_CALL_STARTED == state) + { + rev_iter->setIsVoice(true); + notifyPrticularConversationObservers(session_id, LLConversationLogObserver::VOICE_STATE); + return; // return here because only one session with session_id may be active + } + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index a7457d55e3..f2b6a67c92 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -57,8 +57,12 @@ public: const std::string& getTimestamp() const { return mTimestamp; } const time_t& getTime() const { return mTime; } bool isVoice() const { return mIsVoice; } + bool isConversationPast() const { return mIsConversationPast; } bool hasOfflineMessages() const { return mHasOfflineIMs; } + void setIsVoice(bool is_voice); + void setIsPast (bool is_past) { mIsConversationPast = is_past; } + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ @@ -87,6 +91,7 @@ private: LLUUID mParticipantID; bool mIsVoice; bool mHasOfflineIMs; + bool mIsConversationPast; // once session is finished conversation became past forever std::string mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm }; @@ -122,12 +127,14 @@ public: // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); - virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){} // Stub - virtual void sessionRemoved(const LLUUID& session_id){} // Stub - virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){} // Stub + virtual void sessionRemoved(const LLUUID& session_id); + virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub + virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub - // Triggered by LLFriendObserver change void notifyObservers(); + void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + + void onVoiceChannelConnected(const LLUUID& session_id, const LLVoiceChannel::EState& state); /** * public method which is called on viewer exit to save conversation log @@ -140,8 +147,7 @@ private: /** * constructs file name in which conversations log will be saved - * file name template: agentID.call_log. - * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log + * file name is conversation.log */ std::string getFileName(); @@ -158,8 +164,15 @@ private: class LLConversationLogObserver { public: + + enum EConversationChange + { + VOICE_STATE = 1 + }; + virtual ~LLConversationLogObserver(){} virtual void changed() = 0; + virtual void changed(const LLUUID& session_id, U32 mask){}; }; #endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 94be9055bd..d39e090c22 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -141,6 +141,28 @@ void LLConversationLogList::changed() refresh(); } +void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) +{ + if (mask & LLConversationLogObserver::VOICE_STATE) + { + std::vector panels; + LLFlatListViewEx::getItems(panels); + + std::vector::iterator iter = panels.begin(); + + for (; iter != panels.end(); ++iter) + { + LLConversationLogListItem* item = dynamic_cast(*iter); + + if (item && session_id == item->getConversation()->getSessionID() && !item->getConversation()->isConversationPast()) + { + item->initIcons(); + return; + } + } + } +} + void LLConversationLogList::addNewItem(const LLConversation* conversation) { LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h index dff34a74c6..5e7fc0a9fb 100644 --- a/indra/newview/llconversationloglist.h +++ b/indra/newview/llconversationloglist.h @@ -68,6 +68,7 @@ public: * Changes from LLConversationLogObserver */ virtual void changed(); + virtual void changed(const LLUUID& session_id, U32 mask); private: diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 8943e11604..2aaafa0fba 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -64,10 +64,10 @@ public: void onDoubleClick(); -private: - void initIcons(); +private: + const LLConversation* mConversation; LLTextBox* mConversationName; diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index bd12328a6b..ceff75a0cc 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -414,7 +414,7 @@ void LLVoiceChannel::doSetState(const EState& new_state) mState = new_state; if (!mStateChangedCallback.empty()) - mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent); + mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent, mSessionID); } //static diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index b8597ee5cb..fed44974fd 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -52,7 +52,7 @@ public: OUTGOING_CALL } EDirection; - typedef boost::signals2::signal state_changed_signal_t; + typedef boost::signals2::signal state_changed_signal_t; // on current channel changed signal typedef boost::function channel_changed_callback_t; -- cgit v1.2.3 From c355fb98d3f4040196b7b8586dc9328fccb906d2 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Mon, 3 Sep 2012 06:12:50 +0000 Subject: Extracted texture baking system into llappearance library. --- indra/llappearance/CMakeLists.txt | 32 +- indra/llappearance/llavatarappearance.cpp | 174 ++ indra/llappearance/llavatarappearance.h | 128 ++ indra/llappearance/llinventoryicon.cpp | 184 ++ indra/llappearance/llinventoryicon.h | 102 + indra/llappearance/lljointpickname.h | 46 + indra/llappearance/lllocaltextureobject.cpp | 213 +++ indra/llappearance/lllocaltextureobject.h | 87 + indra/llappearance/lltexglobalcolor.cpp | 154 ++ indra/llappearance/lltexglobalcolor.h | 83 + indra/llappearance/lltexlayer.cpp | 1778 ++++++++++++++++++ indra/llappearance/lltexlayer.h | 269 +++ indra/llappearance/lltexlayerparams.cpp | 571 ++++++ indra/llappearance/lltexlayerparams.h | 195 ++ indra/llappearance/lltexturemanagerbridge.cpp | 32 + indra/llappearance/lltexturemanagerbridge.h | 45 + indra/llappearance/llviewervisualparam.cpp | 165 ++ indra/llappearance/llviewervisualparam.h | 109 ++ indra/llappearance/llvoavatardefines.cpp | 249 +++ indra/llappearance/llvoavatardefines.h | 226 +++ indra/llappearance/llwearable.cpp | 868 +-------- indra/llappearance/llwearable.h | 87 +- indra/llappearance/llwearabletype.cpp | 162 ++ indra/llappearance/llwearabletype.h | 76 + indra/llcharacter/CMakeLists.txt | 1 + indra/llrender/llglslshader.h | 2 + indra/llrender/lltexture.h | 46 +- indra/newview/CMakeLists.txt | 21 +- indra/newview/llagentwearables.cpp | 120 +- indra/newview/llagentwearables.h | 49 +- indra/newview/llappearancemgr.cpp | 28 +- indra/newview/llappearancemgr.h | 1 - indra/newview/llassetuploadresponders.cpp | 2 +- indra/newview/llavatariconctrl.cpp | 2 + indra/newview/lldriverparam.cpp | 17 +- indra/newview/llfloaterauction.cpp | 1 + indra/newview/llfloateravatartextures.cpp | 5 +- indra/newview/llgroupiconctrl.cpp | 1 + indra/newview/llinventorybridge.cpp | 6 +- indra/newview/llinventorybridge.h | 8 +- indra/newview/llinventoryicon.cpp | 183 -- indra/newview/llinventoryicon.h | 102 - indra/newview/lllocalbitmaps.cpp | 4 +- indra/newview/lllocalbitmaps.h | 1 + indra/newview/lllocaltextureobject.cpp | 212 --- indra/newview/lllocaltextureobject.h | 87 - indra/newview/llpanelclassified.cpp | 1 + indra/newview/llpaneleditwearable.cpp | 10 +- indra/newview/llpaneleditwearable.h | 10 +- indra/newview/llpostcard.cpp | 1 + indra/newview/llsidepanelappearance.cpp | 10 +- indra/newview/llsidepanelappearance.h | 8 +- indra/newview/lltexglobalcolor.cpp | 152 -- indra/newview/lltexglobalcolor.h | 83 - indra/newview/lltexlayer.cpp | 2508 ------------------------- indra/newview/lltexlayer.h | 380 ---- indra/newview/lltexlayerparams.cpp | 568 ------ indra/newview/lltexlayerparams.h | 193 -- indra/newview/lltextureview.cpp | 4 +- indra/newview/llviewerjoint.h | 20 +- indra/newview/llviewerjointmesh.cpp | 4 +- indra/newview/llviewerjointmesh.h | 6 +- indra/newview/llviewershadermgr.h | 1 - indra/newview/llviewerstats.cpp | 2 +- indra/newview/llviewertexlayer.cpp | 791 ++++++++ indra/newview/llviewertexlayer.h | 172 ++ indra/newview/llviewertexture.cpp | 25 + indra/newview/llviewertexture.h | 48 +- indra/newview/llviewervisualparam.cpp | 164 -- indra/newview/llviewervisualparam.h | 109 -- indra/newview/llviewerwearable.cpp | 900 +++++++++ indra/newview/llviewerwearable.h | 116 ++ indra/newview/llvoavatar.cpp | 171 +- indra/newview/llvoavatar.h | 69 +- indra/newview/llvoavatardefines.cpp | 262 --- indra/newview/llvoavatardefines.h | 228 --- indra/newview/llvoavatarself.cpp | 65 +- indra/newview/llvoavatarself.h | 18 +- indra/newview/llwearablelist.cpp | 24 +- indra/newview/llwearablelist.h | 12 +- indra/newview/llwearabletype.cpp | 159 -- indra/newview/llwearabletype.h | 76 - 82 files changed, 7482 insertions(+), 6822 deletions(-) create mode 100644 indra/llappearance/llavatarappearance.cpp create mode 100644 indra/llappearance/llavatarappearance.h create mode 100644 indra/llappearance/llinventoryicon.cpp create mode 100644 indra/llappearance/llinventoryicon.h create mode 100644 indra/llappearance/lljointpickname.h create mode 100644 indra/llappearance/lllocaltextureobject.cpp create mode 100644 indra/llappearance/lllocaltextureobject.h create mode 100644 indra/llappearance/lltexglobalcolor.cpp create mode 100644 indra/llappearance/lltexglobalcolor.h create mode 100644 indra/llappearance/lltexlayer.cpp create mode 100644 indra/llappearance/lltexlayer.h create mode 100644 indra/llappearance/lltexlayerparams.cpp create mode 100644 indra/llappearance/lltexlayerparams.h create mode 100644 indra/llappearance/lltexturemanagerbridge.cpp create mode 100644 indra/llappearance/lltexturemanagerbridge.h create mode 100644 indra/llappearance/llviewervisualparam.cpp create mode 100644 indra/llappearance/llviewervisualparam.h create mode 100644 indra/llappearance/llvoavatardefines.cpp create mode 100644 indra/llappearance/llvoavatardefines.h create mode 100644 indra/llappearance/llwearabletype.cpp create mode 100644 indra/llappearance/llwearabletype.h delete mode 100644 indra/newview/llinventoryicon.cpp delete mode 100644 indra/newview/llinventoryicon.h delete mode 100644 indra/newview/lllocaltextureobject.cpp delete mode 100644 indra/newview/lllocaltextureobject.h delete mode 100644 indra/newview/lltexglobalcolor.cpp delete mode 100644 indra/newview/lltexglobalcolor.h delete mode 100644 indra/newview/lltexlayer.cpp delete mode 100644 indra/newview/lltexlayer.h delete mode 100644 indra/newview/lltexlayerparams.cpp delete mode 100644 indra/newview/lltexlayerparams.h create mode 100644 indra/newview/llviewertexlayer.cpp create mode 100644 indra/newview/llviewertexlayer.h delete mode 100644 indra/newview/llviewervisualparam.cpp delete mode 100644 indra/newview/llviewervisualparam.h create mode 100644 indra/newview/llviewerwearable.cpp create mode 100644 indra/newview/llviewerwearable.h delete mode 100644 indra/newview/llvoavatardefines.cpp delete mode 100644 indra/newview/llvoavatardefines.h delete mode 100644 indra/newview/llwearabletype.cpp delete mode 100644 indra/newview/llwearabletype.h diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 39bfbc9a21..bc4748b87f 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -28,34 +28,48 @@ include(LLLogin) include_directories( ${LLCOMMON_INCLUDE_DIRS} - ${VIEWER_INCLUDE_DIRS} - ${LLAUDIO_INCLUDE_DIRS} ${LLCHARACTER_INCLUDE_DIRS} - ${LLCOMMON_INCLUDE_DIRS} ${LLPHYSICS_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLKDU_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLMESSAGE_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} - ${LLPLUGIN_INCLUDE_DIRS} - ${LLPRIMITIVE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLLOGIN_INCLUDE_DIRS} ) set(llappearance_SOURCE_FILES + llavatarappearance.cpp + llinventoryicon.cpp + lllocaltextureobject.cpp + lltexglobalcolor.cpp + lltexlayer.cpp + lltexlayerparams.cpp + lltexturemanagerbridge.cpp llwearable.cpp + llwearabletype.cpp + llviewervisualparam.cpp + llvoavatardefines.cpp ) set(llappearance_HEADER_FILES - llwearable.h CMakeLists.txt + + llavatarappearance.h + llinventoryicon.cpp + lljointpickname.h + lllocaltextureobject.h + lltexglobalcolor.h + lltexlayer.h + lltexlayerparams.h + lltexturemanagerbridge.h + llwearable.h + llwearabletype.h + llviewervisualparam.h + llvoavatardefines.h ) set_source_files_properties(${llappearance_HEADER_FILES} diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp new file mode 100644 index 0000000000..1ca0161d7e --- /dev/null +++ b/indra/llappearance/llavatarappearance.cpp @@ -0,0 +1,174 @@ +/** + * @File llavatarappearance.cpp + * @brief Implementation of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "lltexglobalcolor.h" + +const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); + +LLAvatarAppearance::LLAvatarAppearance() : + LLCharacter(), + mTexSkinColor( NULL ), + mTexHairColor( NULL ), + mTexEyeColor( NULL ), + mIsDummy(FALSE) +{ + mDebugExistenceTimer.reset(); +} + +using namespace LLVOAvatarDefines; + +//static +BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) +{ + switch( te ) + { + case TEX_UPPER_SHIRT: + param_name[0] = 803; //"shirt_red"; + param_name[1] = 804; //"shirt_green"; + param_name[2] = 805; //"shirt_blue"; + break; + + case TEX_LOWER_PANTS: + param_name[0] = 806; //"pants_red"; + param_name[1] = 807; //"pants_green"; + param_name[2] = 808; //"pants_blue"; + break; + + case TEX_LOWER_SHOES: + param_name[0] = 812; //"shoes_red"; + param_name[1] = 813; //"shoes_green"; + param_name[2] = 817; //"shoes_blue"; + break; + + case TEX_LOWER_SOCKS: + param_name[0] = 818; //"socks_red"; + param_name[1] = 819; //"socks_green"; + param_name[2] = 820; //"socks_blue"; + break; + + case TEX_UPPER_JACKET: + case TEX_LOWER_JACKET: + param_name[0] = 834; //"jacket_red"; + param_name[1] = 835; //"jacket_green"; + param_name[2] = 836; //"jacket_blue"; + break; + + case TEX_UPPER_GLOVES: + param_name[0] = 827; //"gloves_red"; + param_name[1] = 829; //"gloves_green"; + param_name[2] = 830; //"gloves_blue"; + break; + + case TEX_UPPER_UNDERSHIRT: + param_name[0] = 821; //"undershirt_red"; + param_name[1] = 822; //"undershirt_green"; + param_name[2] = 823; //"undershirt_blue"; + break; + + case TEX_LOWER_UNDERPANTS: + param_name[0] = 824; //"underpants_red"; + param_name[1] = 825; //"underpants_green"; + param_name[2] = 826; //"underpants_blue"; + break; + + case TEX_SKIRT: + param_name[0] = 921; //"skirt_red"; + param_name[1] = 922; //"skirt_green"; + param_name[2] = 923; //"skirt_blue"; + break; + + case TEX_HEAD_TATTOO: + case TEX_LOWER_TATTOO: + case TEX_UPPER_TATTOO: + param_name[0] = 1071; //"tattoo_red"; + param_name[1] = 1072; //"tattoo_green"; + param_name[2] = 1073; //"tattoo_blue"; + break; + + default: + llassert(0); + return FALSE; + } + + return TRUE; +} + +void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) +{ + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake ); + setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake ); + setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake ); + } +} + +LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te ) +{ + LLColor4 color; + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + color.mV[VX] = getVisualParamWeight( param_name[0] ); + color.mV[VY] = getVisualParamWeight( param_name[1] ); + color.mV[VZ] = getVisualParamWeight( param_name[2] ); + } + return color; +} + +// static +LLColor4 LLAvatarAppearance::getDummyColor() +{ + return DUMMY_COLOR; +} + +LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) const +{ + if (color_name=="skin_color" && mTexSkinColor) + { + return mTexSkinColor->getColor(); + } + else if(color_name=="hair_color" && mTexHairColor) + { + return mTexHairColor->getColor(); + } + if(color_name=="eye_color" && mTexEyeColor) + { + return mTexEyeColor->getColor(); + } + else + { +// return LLColor4( .5f, .5f, .5f, .5f ); + return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color + } +} + + + diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h new file mode 100644 index 0000000000..cb2ae7aeef --- /dev/null +++ b/indra/llappearance/llavatarappearance.h @@ -0,0 +1,128 @@ +/** + * @file llavatarappearance.h + * @brief Declaration of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&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_AVATAR_APPEARANCE_H +#define LL_AVATAR_APPEARANCE_H + +#include "llcharacter.h" +#include "llframetimer.h" +#include "llvoavatardefines.h" + +class LLTexGlobalColor; +class LLTexLayerSet; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLAvatarAppearance +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLAvatarAppearance : public LLCharacter +{ + LOG_CLASS(LLAvatarAppearance); + +public: + LLAvatarAppearance(); + + //-------------------------------------------------------------------- + // Clothing colors (convenience functions to access visual parameters) + //-------------------------------------------------------------------- +public: + void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); + LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); + static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + LLColor4 getGlobalColor(const std::string& color_name ) const; + virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0; +protected: + LLTexGlobalColor* mTexSkinColor; + LLTexGlobalColor* mTexHairColor; + LLTexGlobalColor* mTexEyeColor; + + //-------------------------------------------------------------------- + // Morph masks + //-------------------------------------------------------------------- +public: + virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES) = 0; + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0; + +/******************************************************************************** + ** ** + ** MESHES + **/ + virtual void dirtyMesh() = 0; // Dirty the avatar mesh + virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority + +/******************************************************************************** + ** ** + ** RENDERING + **/ + BOOL mIsDummy; // for special views + +/******************************************************************************** + ** ** + ** STATE + **/ +public: + virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + virtual BOOL isUsingBakedTextures() const = 0; + +/******************************************************************************** + ** ** + ** WEARABLES + **/ +public: + virtual U32 getWearableCount(const LLWearableType::EType type) const = 0; + virtual U32 getWearableCount(const U32 tex_index) const = 0; + + virtual LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) = 0; + virtual const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const = 0; + + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const = 0; + + //-------------------------------------------------------------------- + // Avatar Rez Metrics + //-------------------------------------------------------------------- +public: + F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } + +protected: + LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. + +public: + static LLColor4 getDummyColor(); + virtual void updateMeshTextures() = 0; +}; + +#endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/llappearance/llinventoryicon.cpp b/indra/llappearance/llinventoryicon.cpp new file mode 100644 index 0000000000..62261058ef --- /dev/null +++ b/indra/llappearance/llinventoryicon.cpp @@ -0,0 +1,184 @@ +/** + * @file llinventoryicon.cpp + * @brief Implementation of the inventory icon. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" +#include "llinventoryicon.h" + +#include "lldictionary.h" +#include "llinventorydefines.h" +#include "llui.h" +#include "llwearabletype.h" + +struct IconEntry : public LLDictionaryEntry +{ + IconEntry(const std::string &item_name) + : + LLDictionaryEntry(item_name) + {} +}; + +class LLIconDictionary : public LLSingleton, + public LLDictionary +{ +public: + LLIconDictionary(); +}; + +LLIconDictionary::LLIconDictionary() +{ + addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); + addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound")); + addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); + addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object")); + addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); + addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); + addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); + + addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); + addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); + + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); + addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); + addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); + + addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); + + addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); + addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); + addEntry(LLInventoryIcon::ICONNAME_MESH, new IconEntry("Inv_Mesh")); + + addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); + + addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); +} + +LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 misc_flag, + BOOL item_is_multi) +{ + const std::string& icon_name = getIconName(asset_type, inventory_type, misc_flag, item_is_multi); + return LLUI::getUIImage(icon_name); +} + +LLUIImagePtr LLInventoryIcon::getIcon(EIconName idx) +{ + return LLUI::getUIImage(getIconName(idx)); +} + +const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 misc_flag, + BOOL item_is_multi) +{ + EIconName idx = ICONNAME_OBJECT; + if (item_is_multi) + { + idx = ICONNAME_OBJECT_MULTI; + return getIconName(idx); + } + + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? ICONNAME_SNAPSHOT : ICONNAME_TEXTURE; + break; + case LLAssetType::AT_SOUND: + idx = ICONNAME_SOUND; + break; + case LLAssetType::AT_CALLINGCARD: + idx = (misc_flag != 0) ? ICONNAME_CALLINGCARD_ONLINE : ICONNAME_CALLINGCARD_OFFLINE; + break; + case LLAssetType::AT_LANDMARK: + idx = (misc_flag != 0) ? ICONNAME_LANDMARK_VISITED : ICONNAME_LANDMARK; + break; + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + idx = ICONNAME_SCRIPT; + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + idx = assignWearableIcon(misc_flag); + break; + case LLAssetType::AT_NOTECARD: + idx = ICONNAME_NOTECARD; + break; + case LLAssetType::AT_ANIMATION: + idx = ICONNAME_ANIMATION; + break; + case LLAssetType::AT_GESTURE: + idx = ICONNAME_GESTURE; + break; + case LLAssetType::AT_LINK: + idx = ICONNAME_LINKITEM; + break; + case LLAssetType::AT_LINK_FOLDER: + idx = ICONNAME_LINKFOLDER; + break; + case LLAssetType::AT_OBJECT: + idx = ICONNAME_OBJECT; + break; + case LLAssetType::AT_MESH: + idx = ICONNAME_MESH; + default: + break; + } + + return getIconName(idx); +} + + +const std::string& LLInventoryIcon::getIconName(EIconName idx) +{ + const IconEntry *entry = LLIconDictionary::instance().lookup(idx); + return entry->mName; +} + +LLInventoryIcon::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) +{ + const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); + return LLWearableType::getIconName(wearable_type); +} diff --git a/indra/llappearance/llinventoryicon.h b/indra/llappearance/llinventoryicon.h new file mode 100644 index 0000000000..c7e2998a20 --- /dev/null +++ b/indra/llappearance/llinventoryicon.h @@ -0,0 +1,102 @@ +/** + * @file llinventoryfunctions.h + * @brief Miscellaneous inventory-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYICON_H +#define LL_LLINVENTORYICON_H + +#include "llassettype.h" +#include "llinventorytype.h" +#include "lluiimage.h" + +class LLInventoryIcon +{ +public: + enum EIconName + { + ICONNAME_TEXTURE, + ICONNAME_SOUND, + ICONNAME_CALLINGCARD_ONLINE, + ICONNAME_CALLINGCARD_OFFLINE, + ICONNAME_LANDMARK, + ICONNAME_LANDMARK_VISITED, + ICONNAME_SCRIPT, + ICONNAME_CLOTHING, + ICONNAME_OBJECT, + ICONNAME_OBJECT_MULTI, + ICONNAME_NOTECARD, + ICONNAME_BODYPART, + ICONNAME_SNAPSHOT, + + ICONNAME_BODYPART_SHAPE, + ICONNAME_BODYPART_SKIN, + ICONNAME_BODYPART_HAIR, + ICONNAME_BODYPART_EYES, + ICONNAME_CLOTHING_SHIRT, + ICONNAME_CLOTHING_PANTS, + ICONNAME_CLOTHING_SHOES, + ICONNAME_CLOTHING_SOCKS, + ICONNAME_CLOTHING_JACKET, + ICONNAME_CLOTHING_GLOVES, + ICONNAME_CLOTHING_UNDERSHIRT, + ICONNAME_CLOTHING_UNDERPANTS, + ICONNAME_CLOTHING_SKIRT, + ICONNAME_CLOTHING_ALPHA, + ICONNAME_CLOTHING_TATTOO, + + ICONNAME_ANIMATION, + ICONNAME_GESTURE, + + ICONNAME_CLOTHING_PHYSICS, + + ICONNAME_LINKITEM, + ICONNAME_LINKFOLDER, + ICONNAME_MESH, + + ICONNAME_INVALID, + ICONNAME_COUNT, + ICONNAME_NONE = -1 + }; + + static const std::string& getIconName(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, + U32 misc_flag = 0, // different meanings depending on item type + BOOL item_is_multi = FALSE); + static const std::string& getIconName(EIconName idx); + + static LLUIImagePtr getIcon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, + U32 misc_flag = 0, // different meanings depending on item type + BOOL item_is_multi = FALSE); + static LLUIImagePtr getIcon(EIconName idx); + +protected: + static EIconName assignWearableIcon(U32 misc_flag); +}; +#endif // LL_LLINVENTORYICON_H + + + diff --git a/indra/llappearance/lljointpickname.h b/indra/llappearance/lljointpickname.h new file mode 100644 index 0000000000..17181520e3 --- /dev/null +++ b/indra/llappearance/lljointpickname.h @@ -0,0 +1,46 @@ +/** + * @file lljointpickname.h + * @brief Defines OpenGL seleciton stack names + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#ifndef LL_LLJOINTPICKNAME_H +#define LL_LLJOINTPICKNAME_H + + +// Sets the OpenGL selection stack name that is pushed and popped +// with this joint state. The default value indicates that no name +// should be pushed/popped. +enum LLJointPickName +{ + PN_DEFAULT = -1, + PN_0 = 0, + PN_1 = 1, + PN_2 = 2, + PN_3 = 3, + PN_4 = 4, + PN_5 = 5 +}; + +#endif // LL_LLJOINTPICKNAME_H diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp new file mode 100644 index 0000000000..0e77444f49 --- /dev/null +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -0,0 +1,213 @@ +/** + * @file lllocaltextureobject.cpp + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lllocaltextureobject.h" + +#include "llimage.h" +#include "llrender.h" +#include "lltexlayer.h" +#include "lltexture.h" +#include "lluuid.h" +#include "llwearable.h" + + +LLLocalTextureObject::LLLocalTextureObject() : + mIsBakedReady(FALSE), + mDiscard(MAX_DISCARD_LEVEL+1) +{ + mImage = NULL; +} + +LLLocalTextureObject::LLLocalTextureObject(LLTexture* image, const LLUUID& id) : + mIsBakedReady(FALSE), + mDiscard(MAX_DISCARD_LEVEL+1) +{ + mImage = image; + gGL.getTexUnit(0)->bind(mImage); + mID = id; +} + +LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : + mImage(lto.mImage), + mID(lto.mID), + mIsBakedReady(lto.mIsBakedReady), + mDiscard(lto.mDiscard) +{ + U32 num_layers = lto.getNumTexLayers(); + mTexLayers.reserve(num_layers); + for (U32 index = 0; index < num_layers; index++) + { + LLTexLayer* original_layer = lto.getTexLayer(index); + if (!original_layer) + { + llerrs << "could not clone Local Texture Object: unable to extract texlayer!" << llendl; + continue; + } + + LLTexLayer* new_layer = new LLTexLayer(*original_layer); + new_layer->setLTO(this); + mTexLayers.push_back(new_layer); + } +} + +LLLocalTextureObject::~LLLocalTextureObject() +{ +} + +LLTexture* LLLocalTextureObject::getImage() const +{ + return mImage; +} + +LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const +{ + if (index >= getNumTexLayers()) + { + return NULL; + } + + return mTexLayers[index]; +} + +LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) +{ + for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++) + { + LLTexLayer *layer = *iter; + if (layer->getName().compare(name) == 0) + { + return layer; + } + } + + return NULL; +} + +U32 LLLocalTextureObject::getNumTexLayers() const +{ + return mTexLayers.size(); +} + +LLUUID LLLocalTextureObject::getID() const +{ + return mID; +} + +S32 LLLocalTextureObject::getDiscard() const +{ + return mDiscard; +} + +BOOL LLLocalTextureObject::getBakedReady() const +{ + return mIsBakedReady; +} + +void LLLocalTextureObject::setImage(LLTexture* new_image) +{ + mImage = new_image; +} + +BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) +{ + if (index >= getNumTexLayers() ) + { + return FALSE; + } + + if (new_tex_layer == NULL) + { + return removeTexLayer(index); + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer); + layer->setLTO(this); + + if (mTexLayers[index]) + { + delete mTexLayers[index]; + } + mTexLayers[index] = layer; + + return TRUE; +} + +BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) +{ + if (new_tex_layer == NULL) + { + return FALSE; + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); + layer->setLTO(this); + mTexLayers.push_back(layer); + return TRUE; +} + +BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) +{ + if (new_tex_layer == NULL) + { + return FALSE; + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable); + layer->setLTO(this); + mTexLayers.push_back(layer); + return TRUE; +} + +BOOL LLLocalTextureObject::removeTexLayer(U32 index) +{ + if (index >= getNumTexLayers()) + { + return FALSE; + } + tex_layer_vec_t::iterator iter = mTexLayers.begin(); + iter += index; + + delete *iter; + mTexLayers.erase(iter); + return TRUE; +} + +void LLLocalTextureObject::setID(LLUUID new_id) +{ + mID = new_id; +} + +void LLLocalTextureObject::setDiscard(S32 new_discard) +{ + mDiscard = new_discard; +} + +void LLLocalTextureObject::setBakedReady(BOOL ready) +{ + mIsBakedReady = ready; +} + diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h new file mode 100644 index 0000000000..8f868eb412 --- /dev/null +++ b/indra/llappearance/lllocaltextureobject.h @@ -0,0 +1,87 @@ +/** + * @file lllocaltextureobject.h + * @brief LLLocalTextureObject class header file + * + * $LicenseInfo:firstyear=2009&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_LOCALTEXTUREOBJECT_H +#define LL_LOCALTEXTUREOBJECT_H + +#include + +#include "llpointer.h" +#include "lltexture.h" + +class LLUUID; +class LLTexLayer; +class LLTexLayerTemplate; +class LLWearable; + +// Stores all relevant information for a single texture +// assumed to have ownership of all objects referred to - +// will delete objects when being replaced or if object is destroyed. +class LLLocalTextureObject +{ +public: + LLLocalTextureObject(); + LLLocalTextureObject(LLTexture* image, const LLUUID& id); + LLLocalTextureObject(const LLLocalTextureObject& lto); + ~LLLocalTextureObject(); + + LLTexture* getImage() const; + LLTexLayer* getTexLayer(U32 index) const; + LLTexLayer* getTexLayer(const std::string &name); + U32 getNumTexLayers() const; + LLUUID getID() const; + S32 getDiscard() const; + BOOL getBakedReady() const; + + void setImage(LLTexture* new_image); + BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index); + BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); + BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); + BOOL removeTexLayer(U32 index); + + void setID(LLUUID new_id); + void setDiscard(S32 new_discard); + void setBakedReady(BOOL ready); + +protected: + +private: + + LLPointer mImage; + // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer + // using shared pointers here only for smart assignment & cleanup + // do NOT create new shared pointers to these objects, or keep pointers to them around + typedef std::vector tex_layer_vec_t; + tex_layer_vec_t mTexLayers; + + LLUUID mID; + + BOOL mIsBakedReady; + S32 mDiscard; +}; + + #endif // LL_LOCALTEXTUREOBJECT_H + diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp new file mode 100644 index 0000000000..d9c6150fc6 --- /dev/null +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -0,0 +1,154 @@ +/** + * @file lltexlayerglobalcolor.cpp + * @brief Color for texture layers. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "lltexlayer.h" +//#include "llwearable.h" +#include "lltexglobalcolor.h" + +class LLWearable; + +//----------------------------------------------------------------------------- +// LLTexGlobalColor +//----------------------------------------------------------------------------- + +LLTexGlobalColor::LLTexGlobalColor(LLAvatarAppearance* appearance) + : + mAvatarAppearance(appearance), + mInfo(NULL) +{ +} + +LLTexGlobalColor::~LLTexGlobalColor() +{ + // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter() + //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); +} + +BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) + { + LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); + if (!param_color->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + mParamGlobalColorList.push_back(param_color); + } + + return TRUE; +} + +LLColor4 LLTexGlobalColor::getColor() const +{ + // Sum of color params + if (mParamGlobalColorList.empty()) + return LLColor4(1.f, 1.f, 1.f, 1.f); + + LLColor4 net_color(0.f, 0.f, 0.f, 0.f); + LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color); + return net_color; +} + +const std::string& LLTexGlobalColor::getName() const +{ + return mInfo->mName; +} + +//----------------------------------------------------------------------------- +// LLTexParamGlobalColor +//----------------------------------------------------------------------------- +LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) : + LLTexLayerParamColor(tex_global_color->getAvatarAppearance()), + mTexGlobalColor(tex_global_color) +{ +} + +/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const +{ + LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor); + *new_param = *this; + return new_param; +} + +void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake) +{ + mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake); +} + +//----------------------------------------------------------------------------- +// LLTexGlobalColorInfo +//----------------------------------------------------------------------------- + +LLTexGlobalColorInfo::LLTexGlobalColorInfo() +{ +} + + +LLTexGlobalColorInfo::~LLTexGlobalColorInfo() +{ + for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); +} + +BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) +{ + // name attribute + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + llwarns << " element is missing name attribute." << llendl; + return FALSE; + } + // sub-element + for (LLXmlTreeNode* child = node->getChildByName("param"); + child; + child = node->getNextNamedChild()) + { + if (child->getChildByName("param_color")) + { + // + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + mParamColorInfoList.push_back(info); + } + } + return TRUE; +} diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h new file mode 100644 index 0000000000..2867479876 --- /dev/null +++ b/indra/llappearance/lltexglobalcolor.h @@ -0,0 +1,83 @@ +/** + * @file lltexglobalcolor.h + * @brief This is global texture color info used by llavatarappearance. + * + * $LicenseInfo:firstyear=2008&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_LLTEXGLOBALCOLOR_H +#define LL_LLTEXGLOBALCOLOR_H + +#include "lltexlayer.h" +#include "lltexlayerparams.h" + +class LLAvatarAppearance; +class LLWearable; +class LLTexGlobalColorInfo; + +class LLTexGlobalColor +{ +public: + LLTexGlobalColor( LLAvatarAppearance* appearance ); + ~LLTexGlobalColor(); + + LLTexGlobalColorInfo* getInfo() const { return mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLTexGlobalColorInfo *info); + + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + LLColor4 getColor() const; + const std::string& getName() const; + +private: + param_color_list_t mParamGlobalColorList; + LLAvatarAppearance* mAvatarAppearance; // just backlink, don't LLPointer + LLTexGlobalColorInfo *mInfo; +}; + +// Used by llavatarappearance to determine skin/eye/hair color. +class LLTexGlobalColorInfo +{ + friend class LLTexGlobalColor; +public: + LLTexGlobalColorInfo(); + ~LLTexGlobalColorInfo(); + + BOOL parseXml(LLXmlTreeNode* node); + +private: + param_color_info_list_t mParamColorInfoList; + std::string mName; +}; + +class LLTexParamGlobalColor : public LLTexLayerParamColor +{ +public: + LLTexParamGlobalColor(LLTexGlobalColor *tex_color); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; +protected: + /*virtual*/ void onGlobalColorChanged(bool upload_bake); +private: + LLTexGlobalColor* mTexGlobalColor; +}; + +#endif diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp new file mode 100644 index 0000000000..3bb31d3721 --- /dev/null +++ b/indra/llappearance/lltexlayer.cpp @@ -0,0 +1,1778 @@ +/** + * @file lltexlayer.cpp + * @brief A texture layer. Used for avatars. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lltexlayer.h" + +#include "llavatarappearance.h" +#include "llcrc.h" +#include "imageids.h" +#include "llimagej2c.h" +#include "llimagetga.h" +//#include "llnotificationsutil.h" +#include "lldir.h" +#include "llvfile.h" +#include "llvfs.h" +//#include "llviewerstats.h" +//#include "llviewerregion.h" +//#include "pipeline.h" +#include "lltexlayerparams.h" +#include "lltexturemanagerbridge.h" +#include "llui.h" +//#include "llagentwearables.h" +#include "llwearable.h" +//#include "llviewercontrol.h" +//#include "llviewershadermgr.h" +#include "llviewervisualparam.h" + +//#include "../tools/imdebug/imdebug.h" + +using namespace LLVOAvatarDefines; + +static const S32 BAKE_UPLOAD_ATTEMPTS = 7; +static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt + +// runway consolidate +extern std::string self_av_string(); + +class LLTexLayerInfo +{ + friend class LLTexLayer; + friend class LLTexLayerTemplate; + friend class LLTexLayerInterface; +public: + LLTexLayerInfo(); + ~LLTexLayerInfo(); + + BOOL parseXml(LLXmlTreeNode* node); + BOOL createVisualParams(LLAvatarAppearance *appearance); + BOOL isUserSettable() { return mLocalTexture != -1; } + S32 getLocalTexture() const { return mLocalTexture; } + BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } + std::string getName() const { return mName; } + +private: + std::string mName; + + BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, + LLTexLayerInterface::ERenderPass mRenderPass; + + std::string mGlobalColor; + LLColor4 mFixedColor; + + S32 mLocalTexture; + std::string mStaticImageFileName; + BOOL mStaticImageIsMask; + BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask + BOOL mIsVisibilityMask; + + typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t; + morph_name_list_t mMorphNameList; + param_color_info_list_t mParamColorInfoList; + param_alpha_info_list_t mParamAlphaInfoList; +}; + + +//----------------------------------------------------------------------------- +// LLTexLayerSetInfo +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +LLTexLayerSetInfo::LLTexLayerSetInfo() : + mBodyRegion( "" ), + mWidth( 512 ), + mHeight( 512 ), + mClearAlpha( TRUE ) +{ +} + +LLTexLayerSetInfo::~LLTexLayerSetInfo( ) +{ + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); +} + +BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "layer_set" ) ); + if( !node->hasName( "layer_set" ) ) + { + return FALSE; + } + + // body_region + static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region"); + if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) + { + llwarns << " is missing body_region attribute" << llendl; + return FALSE; + } + + // width, height + static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); + if( !node->getFastAttributeS32( width_string, mWidth ) ) + { + return FALSE; + } + + static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); + if( !node->getFastAttributeS32( height_string, mHeight ) ) + { + return FALSE; + } + + // Optional alpha component to apply after all compositing is complete. + static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file"); + node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName ); + + static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha"); + node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha ); + + // + for (LLXmlTreeNode* child = node->getChildByName( "layer" ); + child; + child = node->getNextNamedChild()) + { + LLTexLayerInfo* info = new LLTexLayerInfo(); + if( !info->parseXml( child )) + { + delete info; + return FALSE; + } + mLayerInfoList.push_back( info ); + } + return TRUE; +} + +// creates visual params without generating layersets or layers +void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) +{ + //layer_info_list_t mLayerInfoList; + for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin(); + layer_iter != mLayerInfoList.end(); + layer_iter++) + { + LLTexLayerInfo *layer_info = *layer_iter; + layer_info->createVisualParams(appearance); + } +} + +//----------------------------------------------------------------------------- +// LLTexLayerSet +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +BOOL LLTexLayerSet::sHasCaches = FALSE; + +LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : + mAvatarAppearance( appearance ), + mIsVisible( TRUE ), + mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD), + mInfo( NULL ) +{ +} + +// virtual +LLTexLayerSet::~LLTexLayerSet() +{ + deleteCaches(); + std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); + std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer()); +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mLayerList.reserve(info->mLayerInfoList.size()); + for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin(); + iter != info->mLayerInfoList.end(); + iter++) + { + LLTexLayerInterface *layer = NULL; + if ( (*iter)->isUserSettable() ) + { + layer = new LLTexLayerTemplate( this, getAvatarAppearance() ); + } + else + { + layer = new LLTexLayer(this); + } + // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance + if (!layer->setInfo(*iter, NULL)) + { + mInfo = NULL; + return FALSE; + } + if (!layer->isVisibilityMask()) + { + mLayerList.push_back( layer ); + } + else + { + mMaskLayerList.push_back(layer); + } + } + + requestUpdate(); + + stop_glerror(); + + return TRUE; +} + +#if 0 // obsolete +//----------------------------------------------------------------------------- +// parseData +//----------------------------------------------------------------------------- + +BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) +{ + LLTexLayerSetInfo *info = new LLTexLayerSetInfo; + + if (!info->parseXml(node)) + { + delete info; + return FALSE; + } + if (!setInfo(info)) + { + delete info; + return FALSE; + } + return TRUE; +} +#endif + +void LLTexLayerSet::deleteCaches() +{ + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + layer->deleteCaches(); + } + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayerInterface* layer = *iter; + layer->deleteCaches(); + } +} + + +BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) +{ + BOOL success = TRUE; + mIsVisible = TRUE; + + if (mMaskLayerList.size() > 0) + { + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayerInterface* layer = *iter; + if (layer->isInvisibleAlphaMask()) + { + mIsVisible = FALSE; + } + } + } + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + LLGLSUIDefault gls_ui; + LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); + gGL.setColorMask(true, true); + + // clear buffer area to ensure we don't pick up UI elements + { + gGL.flush(); + LLGLDisable no_alpha(GL_ALPHA_TEST); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.0f); + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + + if (mIsVisible) + { + // composite color layers + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer->getRenderPass() == LLTexLayer::RP_COLOR) + { + gGL.flush(); + success &= layer->render(x, y, width, height); + gGL.flush(); + } + } + + renderAlphaMaskTextures(x, y, width, height, false); + + stop_glerror(); + } + else + { + gGL.flush(); + + gGL.setSceneBlendType(LLRender::BT_REPLACE); + LLGLDisable no_alpha(GL_ALPHA_TEST); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 0.f ); + + gl_rect_2d_simple( width, height ); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gGL.flush(); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + + return success; +} + + +BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const +{ + return mInfo->mBodyRegion == region; +} + +const std::string LLTexLayerSet::getBodyRegionName() const +{ + return mInfo->mBodyRegion; +} + + +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) +{ + const LLTexLayerSetInfo *info = getInfo(); + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + gGL.setColorMask(false, true); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + + // (Optionally) replace alpha with a single component image from a tga file. + if (!info->mStaticAlphaFileName.empty()) + { + gGL.flush(); + { + LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); + if( tex ) + { + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->bind(tex); + gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); + gl_rect_2d_simple_tex( width, height ); + } + } + gGL.flush(); + } + else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0)) + { + // Set the alpha channel to one (clean up after previous blending) + gGL.flush(); + LLGLDisable no_alpha(GL_ALPHA_TEST); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + + // (Optional) Mask out part of the baked texture with alpha masks + // will still have an effect even if mClearAlpha is set or the alpha component was replaced + if (mMaskLayerList.size() > 0) + { + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); + gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) + { + LLTexLayerInterface* layer = *iter; + gGL.flush(); + layer->blendAlphaTexture(x,y,width, height); + gGL.flush(); + } + + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + +void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) +{ + mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); +} + +BOOL LLTexLayerSet::isMorphValid() const +{ + for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + const LLTexLayerInterface* layer = *iter; + if (layer && !layer->isMorphValid()) + { + return FALSE; + } + } + return TRUE; +} + +void LLTexLayerSet::invalidateMorphMasks() +{ + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer) + { + layer->invalidateMorphMasks(); + } + } +} + + +//----------------------------------------------------------------------------- +// LLTexLayerInfo +//----------------------------------------------------------------------------- +LLTexLayerInfo::LLTexLayerInfo() : + mWriteAllChannels( FALSE ), + mRenderPass(LLTexLayer::RP_COLOR), + mFixedColor( 0.f, 0.f, 0.f, 0.f ), + mLocalTexture( -1 ), + mStaticImageIsMask( FALSE ), + mUseLocalTextureAlphaOnly(FALSE), + mIsVisibilityMask(FALSE) +{ +} + +LLTexLayerInfo::~LLTexLayerInfo( ) +{ + std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); + std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer()); +} + +BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "layer" ) ); + + // name attribute + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if( !node->getFastAttributeString( name_string, mName ) ) + { + return FALSE; + } + + static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); + node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels ); + + std::string render_pass_name; + static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass"); + if( node->getFastAttributeString( render_pass_string, render_pass_name ) ) + { + if( render_pass_name == "bump" ) + { + mRenderPass = LLTexLayer::RP_BUMP; + } + } + + // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a child. + // global color attribute (optional) + static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); + node->getFastAttributeString( global_color_string, mGlobalColor ); + + // Visibility mask (optional) + BOOL is_visibility; + static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); + if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) + { + mIsVisibilityMask = is_visibility; + } + + // color attribute (optional) + LLColor4U color4u; + static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); + if( node->getFastAttributeColor4U( fixed_color_string, color4u ) ) + { + mFixedColor.setVec( color4u ); + } + + // optional sub-element + for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" ); + texture_node; + texture_node = node->getNextNamedChild()) + { + std::string local_texture_name; + static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); + static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); + static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); + static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only"); + if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) + { + texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); + } + else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name)) + { + texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); + + /* if ("upper_shirt" == local_texture_name) + mLocalTexture = TEX_UPPER_SHIRT; */ + mLocalTexture = TEX_NUM_INDICES; + for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) + { + const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + if (local_texture_name == texture_dict->mName) + { + mLocalTexture = iter->first; + break; + } + } + if (mLocalTexture == TEX_NUM_INDICES) + { + llwarns << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << llendl; + return FALSE; + } + } + else + { + llwarns << " element is missing a required attribute. " << mName << llendl; + return FALSE; + } + } + + for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" ); + maskNode; + maskNode = node->getNextNamedChild()) + { + std::string morph_name; + static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); + if (maskNode->getFastAttributeString(morph_name_string, morph_name)) + { + BOOL invert = FALSE; + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + maskNode->getFastAttributeBOOL(invert_string, invert); + mMorphNameList.push_back(std::pair(morph_name,invert)); + } + } + + // optional sub-element (color or alpha params) + for (LLXmlTreeNode* child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if( child->getChildByName( "param_color" ) ) + { + // + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + mParamColorInfoList.push_back(info); + } + else if( child->getChildByName( "param_alpha" ) ) + { + // + LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( ); + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + mParamAlphaInfoList.push_back(info); + } + } + + return TRUE; +} + +BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) +{ + BOOL success = TRUE; + for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin(); + color_info_iter != mParamColorInfoList.end(); + color_info_iter++) + { + LLTexLayerParamColorInfo * color_info = *color_info_iter; + LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); + if (!param_color->setInfo(color_info, TRUE)) + { + llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl; + delete param_color; + success = FALSE; + } + } + + for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin(); + alpha_info_iter != mParamAlphaInfoList.end(); + alpha_info_iter++) + { + LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; + LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); + if (!param_alpha->setInfo(alpha_info, TRUE)) + { + llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl; + delete param_alpha; + success = FALSE; + } + } + + return success; +} + +LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): + mTexLayerSet( layer_set ), + mMorphMasksValid( FALSE ), + mInfo(NULL), + mHasMorph(FALSE) +{ +} + +LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable): + mTexLayerSet( layer.mTexLayerSet ), + mInfo(NULL) +{ + // don't add visual params for cloned layers + setInfo(layer.getInfo(), wearable); + + mHasMorph = layer.mHasMorph; +} + +BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions +{ + // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. + // Not a critical warning, but could be useful for debugging later issues. -Nyx + if (mInfo != NULL) + { + llwarns << "mInfo != NULL" << llendl; + } + mInfo = info; + //mID = info->mID; // No ID + + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); + iter != mInfo->mParamColorInfoList.end(); + iter++) + { + LLTexLayerParamColor* param_color; + if (!wearable) + { + param_color = new LLTexLayerParamColor(this); + if (!param_color->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + else + { + param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID()); + if (!param_color) + { + mInfo = NULL; + return FALSE; + } + } + mParamColorList.push_back( param_color ); + } + + mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); + for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); + iter != mInfo->mParamAlphaInfoList.end(); + iter++) + { + LLTexLayerParamAlpha* param_alpha; + if (!wearable) + { + param_alpha = new LLTexLayerParamAlpha( this ); + if (!param_alpha->setInfo(*iter, TRUE)) + { + mInfo = NULL; + return FALSE; + } + } + else + { + param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID()); + if (!param_alpha) + { + mInfo = NULL; + return FALSE; + } + } + mParamAlphaList.push_back( param_alpha ); + } + + return TRUE; +} + +/*virtual*/ void LLTexLayerInterface::requestUpdate() +{ + mTexLayerSet->requestUpdate(); +} + +const std::string& LLTexLayerInterface::getName() const +{ + return mInfo->mName; +} + +LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const +{ + return mInfo->mRenderPass; +} + +const std::string& LLTexLayerInterface::getGlobalColor() const +{ + return mInfo->mGlobalColor; +} + +BOOL LLTexLayerInterface::isVisibilityMask() const +{ + return mInfo->mIsVisibilityMask; +} + +void LLTexLayerInterface::invalidateMorphMasks() +{ + mMorphMasksValid = FALSE; +} + +LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const +{ + LLViewerVisualParam *result = NULL; + for (param_color_list_t::const_iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter) + { + if ((*color_iter)->getID() == index) + { + result = *color_iter; + } + } + for (param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter) + { + if ((*alpha_iter)->getID() == index) + { + result = *alpha_iter; + } + } + + return result; +} + +//----------------------------------------------------------------------------- +// LLTexLayer +// A single texture layer, consisting of: +// * color, consisting of either +// * one or more color parameters (weighted colors) +// * a reference to a global color +// * a fixed color with non-zero alpha +// * opaque white (the default) +// * (optional) a texture defined by either +// * a GUID +// * a texture entry index (TE) +// * (optional) one or more alpha parameters (weighted alpha textures) +//----------------------------------------------------------------------------- +LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : + LLTexLayerInterface( layer_set ), + mLocalTextureObject(NULL) +{ +} + +LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) : + LLTexLayerInterface( layer, wearable ), + mLocalTextureObject(NULL) +{ +} + +LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) : + LLTexLayerInterface( layer_template, wearable ), + mLocalTextureObject(lto) +{ +} + +LLTexLayer::~LLTexLayer() +{ + // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get + // deleted with ~LLCharacter() + //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer()); + //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); + + for( alpha_cache_t::iterator iter = mAlphaCache.begin(); + iter != mAlphaCache.end(); iter++ ) + { + U8* alpha_data = iter->second; + delete [] alpha_data; + } + +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +{ + return LLTexLayerInterface::setInfo(info, wearable); +} + +//static +void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) +{ + for (param_color_list_t::const_iterator iter = param_list.begin(); + iter != param_list.end(); iter++) + { + const LLTexLayerParamColor* param = *iter; + LLColor4 param_net = param->getNetColor(); + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); + switch(info->getOperation()) + { + case LLTexLayerParamColor::OP_ADD: + net_color += param_net; + break; + case LLTexLayerParamColor::OP_MULTIPLY: + net_color = net_color * param_net; + break; + case LLTexLayerParamColor::OP_BLEND: + net_color = lerp(net_color, param_net, param->getWeight()); + break; + default: + llassert(0); + break; + } + } + net_color.clamp(); +} + +/*virtual*/ void LLTexLayer::deleteCaches() +{ + // Only need to delete caches for alpha params. Color params don't hold extra memory + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); + iter != mParamAlphaList.end(); iter++ ) + { + LLTexLayerParamAlpha* param = *iter; + param->deleteCaches(); + } +} + +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) +{ + LLGLEnable color_mat(GL_COLOR_MATERIAL); + // *TODO: Is this correct? + //gPipeline.disableLights(); + stop_glerror(); + glDisable(GL_LIGHTING); + stop_glerror(); + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + LLColor4 net_color; + BOOL color_specified = findNetColor(&net_color); + + if (mTexLayerSet->getAvatarAppearance()->mIsDummy) + { + color_specified = true; + net_color = LLAvatarAppearance::getDummyColor(); + } + + BOOL success = TRUE; + + // If you can't see the layer, don't render it. + if( is_approx_zero( net_color.mV[VW] ) ) + { + return success; + } + + BOOL alpha_mask_specified = FALSE; + param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); + if( iter != mParamAlphaList.end() ) + { + // If we have alpha masks, but we're skipping all of them, skip the whole layer. + // However, we can't do this optimization if we have morph masks that need updating. +/* if (!mHasMorph) + { + BOOL skip_layer = TRUE; + + while( iter != mParamAlphaList.end() ) + { + const LLTexLayerParamAlpha* param = *iter; + + if( !param->getSkip() ) + { + skip_layer = FALSE; + break; + } + + iter++; + } + + if( skip_layer ) + { + return success; + } + }//*/ + + renderMorphMasks(x, y, width, height, net_color); + alpha_mask_specified = TRUE; + gGL.flush(); + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); + } + + gGL.color4fv( net_color.mV); + + if( getInfo()->mWriteAllChannels ) + { + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + } + + if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) + { + { + LLTexture* tex = NULL; + if (mLocalTextureObject && mLocalTextureObject->getImage()) + { + tex = mLocalTextureObject->getImage(); + if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR) + { + tex = NULL; + } + } + else + { + llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl; + } +// if( mTexLayerSet->getAvatarAppearance()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) + { + if( tex ) + { + bool no_alpha_test = getInfo()->mWriteAllChannels; + LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0); + if (use_shaders && no_alpha_test) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + gl_rect_2d_simple_tex( width, height ); + + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (use_shaders && no_alpha_test) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + } + } +// else +// { +// success = FALSE; +// } + } + } + + if( !getInfo()->mStaticImageFileName.empty() ) + { + { + LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + gGL.getTexUnit(0)->bind(tex, TRUE); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else + { + success = FALSE; + } + } + } + + if(((-1 == getInfo()->mLocalTexture) || + getInfo()->mUseLocalTextureAlphaOnly) && + getInfo()->mStaticImageFileName.empty() && + color_specified ) + { + LLGLDisable no_alpha(GL_ALPHA_TEST); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4fv( net_color.mV ); + gl_rect_2d_simple( width, height ); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + + if( alpha_mask_specified || getInfo()->mWriteAllChannels ) + { + // Restore standard blend func value + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + stop_glerror(); + } + + if( !success ) + { + llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl; + } + return success; +} + +const U8* LLTexLayer::getAlphaData() const +{ + LLCRC alpha_mask_crc; + const LLUUID& uuid = getUUID(); + alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); + + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + { + const LLTexLayerParamAlpha* param = *iter; + // MULTI-WEARABLE: verify visual parameters used here + F32 param_weight = param->getWeight(); + alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); + } + + U32 cache_index = alpha_mask_crc.getCRC(); + + alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index); + return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; +} + +BOOL LLTexLayer::findNetColor(LLColor4* net_color) const +{ + // Color is either: + // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) + // * a reference to a global color + // * a fixed color with non-zero alpha + // * opaque white (the default) + + if( !mParamColorList.empty() ) + { + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) ); + } + else if (getInfo()->mFixedColor.mV[VW]) + { + net_color->setVec( getInfo()->mFixedColor ); + } + else + { + net_color->setVec( 0.f, 0.f, 0.f, 0.f ); + } + + calculateTexLayerColor(mParamColorList, *net_color); + return TRUE; + } + + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) ); + return TRUE; + } + + if( getInfo()->mFixedColor.mV[VW] ) + { + net_color->setVec( getInfo()->mFixedColor ); + return TRUE; + } + + net_color->setToWhite(); + + return FALSE; // No need to draw a separate colored polygon +} + +BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) +{ + BOOL success = TRUE; + + gGL.flush(); + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + if( tex ) + { + LLGLSNoAlphaTest gls_no_alpha_test; + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + gGL.getTexUnit(0)->bind(tex, TRUE); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + else + { + success = FALSE; + } + } + else + { + if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) + { + LLTexture* tex = mLocalTextureObject->getImage(); + if (tex) + { + LLGLSNoAlphaTest gls_no_alpha_test; + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + gGL.getTexUnit(0)->bind(tex); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + success = TRUE; + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + } + } + + return success; +} + +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +{ + addAlphaMask(data, originX, originY, width, height); +} + +BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) +{ + BOOL success = TRUE; + + llassert( !mParamAlphaList.empty() ); + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + + gGL.setColorMask(false, true); + + LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); + // Note: if the first param is a mulitply, multiply against the current buffer's alpha + if( !first_param || !first_param->getMultiplyBlend() ) + { + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Clear the alpha + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + + gGL.color4f( 0.f, 0.f, 0.f, 0.f ); + gl_rect_2d_simple( width, height ); + } + + // Accumulate alphas + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.color4f( 1.f, 1.f, 1.f, 1.f ); + for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + { + LLTexLayerParamAlpha* param = *iter; + success &= param->render( x, y, width, height ); + } + + // Approximates a min() function + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); + + // Accumulate the alpha component of the texture + if( getInfo()->mLocalTexture != -1 ) + { + LLTexture* tex = mLocalTextureObject->getImage(); + if( tex && (tex->getComponents() == 4) ) + { + LLGLSNoAlphaTest gls_no_alpha_test; + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + gl_rect_2d_simple_tex( width, height ); + + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + } + + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + if( (tex->getComponents() == 4) || + ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) + { + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(tex, TRUE); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + } + } + + // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. + // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); + if (layer_color.mV[VW] != 1.f) + { + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4fv(layer_color.mV); + gl_rect_2d_simple( width, height ); + } + + if (use_shaders) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + LLGLSUIDefault gls_ui; + + gGL.setColorMask(true, true); + + if (hasMorph() && success) + { + LLCRC alpha_mask_crc; + const LLUUID& uuid = getUUID(); + alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); + + for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) + { + const LLTexLayerParamAlpha* param = *iter; + F32 param_weight = param->getWeight(); + alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); + } + + U32 cache_index = alpha_mask_crc.getCRC(); + U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL); + if (!alpha_data) + { + // clear out a slot if we have filled our cache + S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; + while ((S32)mAlphaCache.size() >= max_cache_entries) + { + alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry + alpha_data = iter2->second; + delete [] alpha_data; + mAlphaCache.erase(iter2); + } + alpha_data = new U8[width * height]; + mAlphaCache[cache_index] = alpha_data; + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + } + + getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); + + mMorphMasksValid = TRUE; + getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); + } + + return success; +} + +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +{ + S32 size = width * height; + const U8* alphaData = getAlphaData(); + if (!alphaData && hasAlphaParams()) + { + LLColor4 net_color; + findNetColor( &net_color ); + // TODO: eliminate need for layer morph mask valid flag + invalidateMorphMasks(); + renderMorphMasks(originX, originY, width, height, net_color); + alphaData = getAlphaData(); + } + if (alphaData) + { + for( S32 i = 0; i < size; i++ ) + { + U8 curAlpha = data[i]; + U16 resultAlpha = curAlpha; + resultAlpha *= (alphaData[i] + 1); + resultAlpha = resultAlpha >> 8; + data[i] = (U8)resultAlpha; + } + } +} + +/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask() const +{ + if (mLocalTextureObject) + { + if (mLocalTextureObject->getID() == IMG_INVISIBLE) + { + return TRUE; + } + } + + return FALSE; +} + +LLUUID LLTexLayer::getUUID() const +{ + LLUUID uuid; + if( getInfo()->mLocalTexture != -1 ) + { + LLTexture* tex = mLocalTextureObject->getImage(); + if (tex) + { + uuid = mLocalTextureObject->getID(); + } + } + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + uuid = tex->getID(); + } + } + return uuid; +} + + +//----------------------------------------------------------------------------- +// LLTexLayerTemplate +// A single texture layer, consisting of: +// * color, consisting of either +// * one or more color parameters (weighted colors) +// * a reference to a global color +// * a fixed color with non-zero alpha +// * opaque white (the default) +// * (optional) a texture defined by either +// * a GUID +// * a texture entry index (TE) +// * (optional) one or more alpha parameters (weighted alpha textures) +//----------------------------------------------------------------------------- +LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set, LLAvatarAppearance* const appearance) : + LLTexLayerInterface(layer_set), + mAvatarAppearance( appearance ) +{ +} + +LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : + LLTexLayerInterface(layer), + mAvatarAppearance(layer.getAvatarAppearance()) +{ +} + +LLTexLayerTemplate::~LLTexLayerTemplate() +{ +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +{ + return LLTexLayerInterface::setInfo(info, wearable); +} + +U32 LLTexLayerTemplate::updateWearableCache() const +{ + mWearableCache.clear(); + + S32 te = mInfo->mLocalTexture; + if (te == -1) + { + //this isn't a cloneable layer + return 0; + } + LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te); + U32 num_wearables = getAvatarAppearance()->getWearableCount(wearable_type); + U32 added = 0; + for (U32 i = 0; i < num_wearables; i++) + { + LLWearable* wearable = getAvatarAppearance()->getWearable(wearable_type, i); + if (!wearable) + { + continue; + } + mWearableCache.push_back(wearable); + added++; + } + return added; +} +LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const +{ + if (mWearableCache.size() <= i) + { + return NULL; + } + LLWearable *wearable = mWearableCache[i]; + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + return layer; +} + +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) +{ + if(!mInfo) + { + return FALSE ; + } + + BOOL success = TRUE; + updateWearableCache(); + for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++) + { + LLWearable* wearable = NULL; + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + wearable = *iter; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + if (layer) + { + wearable->writeToAvatar(); + layer->setLTO(lto); + success &= layer->render(x,y,width,height); + } + } + + return success; +} + +/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer +{ + BOOL success = TRUE; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + success &= layer->blendAlphaTexture(x,y,width,height); + } + } + return success; +} + +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +{ + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->addAlphaMask(data, originX, originY, width, height); + } + } +} + +/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval) +{ + mHasMorph = newval; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->setHasMorph(newval); + } + } +} + +/*virtual*/ void LLTexLayerTemplate::deleteCaches() +{ + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->deleteCaches(); + } + } +} + +/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask() const +{ + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + if (layer->isInvisibleAlphaMask()) + { + return TRUE; + } + } + } + + return FALSE; +} + + +//----------------------------------------------------------------------------- +// finds a specific layer based on a passed in name +//----------------------------------------------------------------------------- +LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) +{ + for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer->getName() == name) + { + return layer; + } + } + for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer->getName() == name) + { + return layer; + } + } + return NULL; +} + +void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable) +{ + // initialize all texlayers with this texture type for this LTO + for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; + if (layer->getInfo()->getLocalTexture() == (S32) tex_index) + { + lto->addTexLayer(layer, wearable); + } + } + for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) + { + LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; + if (layer->getInfo()->getLocalTexture() == (S32) tex_index) + { + lto->addTexLayer(layer, wearable); + } + } +} +//----------------------------------------------------------------------------- +// LLTexLayerStaticImageList +//----------------------------------------------------------------------------- + +LLTexLayerStaticImageList::LLTexLayerStaticImageList() : + mGLBytes(0), + mTGABytes(0), + mImageNames(16384) +{ +} + +LLTexLayerStaticImageList::~LLTexLayerStaticImageList() +{ + deleteCachedImages(); +} + +void LLTexLayerStaticImageList::dumpByteCount() const +{ + llinfos << "Avatar Static Textures " << + "KB GL:" << (mGLBytes / 1024) << + "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; +} + +void LLTexLayerStaticImageList::deleteCachedImages() +{ + if( mGLBytes || mTGABytes ) + { + llinfos << "Clearing Static Textures " << + "KB GL:" << (mGLBytes / 1024) << + "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; + + //mStaticImageLists uses LLPointers, clear() will cause deletion + + mStaticImageListTGA.clear(); + mStaticImageList.clear(); + + mGLBytes = 0; + mTGABytes = 0; + } +} + +// Note: in general, for a given image image we'll call either getImageTga() or getTexture(). +// We call getImageTga() if the image is used as an alpha gradient. +// Otherwise, we call getTexture() + +// Returns an LLImageTGA that contains the encoded data from a tga file named file_name. +// Caches the result to speed identical subsequent requests. +LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) +{ + const char *namekey = mImageNames.addString(file_name); + image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); + if( iter != mStaticImageListTGA.end() ) + { + return iter->second; + } + else + { + std::string path; + path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); + LLPointer image_tga = new LLImageTGA( path ); + if( image_tga->getDataSize() > 0 ) + { + mStaticImageListTGA[ namekey ] = image_tga; + mTGABytes += image_tga->getDataSize(); + return image_tga; + } + else + { + return NULL; + } + } +} + +// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. +// Caches the result to speed identical subsequent requests. +LLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) +{ + LLPointer tex; + const char *namekey = mImageNames.addString(file_name); + + texture_map_t::const_iterator iter = mStaticImageList.find(namekey); + if( iter != mStaticImageList.end() ) + { + tex = iter->second; + } + else + { + llassert(gTextureManagerBridgep); + tex = gTextureManagerBridgep->getLocalTexture( FALSE ); + LLPointer image_raw = new LLImageRaw; + if( loadImageRaw( file_name, image_raw ) ) + { + if( (image_raw->getComponents() == 1) && is_mask ) + { + // Note: these are static, unchanging images so it's ok to assume + // that once an image is a mask it's always a mask. + tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); + } + tex->createGLTexture(0, image_raw, 0, TRUE, LLTexture::LOCAL); + + gGL.getTexUnit(0)->bind(tex); + tex->setAddressMode(LLTexUnit::TAM_CLAMP); + + mStaticImageList [ namekey ] = tex; + mGLBytes += (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); + } + else + { + tex = NULL; + } + } + + return tex; +} + +// Reads a .tga file, decodes it, and puts the decoded data in image_raw. +// Returns TRUE if successful. +BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) +{ + BOOL success = FALSE; + std::string path; + path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); + LLPointer image_tga = new LLImageTGA( path ); + if( image_tga->getDataSize() > 0 ) + { + // Copy data from tga to raw. + success = image_tga->decode( image_raw ); + } + + return success; +} + diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h new file mode 100644 index 0000000000..5ee08e67ec --- /dev/null +++ b/indra/llappearance/lltexlayer.h @@ -0,0 +1,269 @@ +/** + * @file lltexlayer.h + * @brief Texture layer classes. Used for avatars. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXLAYER_H +#define LL_LLTEXLAYER_H + +#include +#include "lltexture.h" +#include "llframetimer.h" +#include "llvoavatardefines.h" +#include "lltexlayerparams.h" + +class LLAvatarAppearance; +class LLImageTGA; +class LLImageRaw; +class LLXmlTreeNode; +class LLTexLayerSet; +class LLTexLayerSetInfo; +class LLTexLayerInfo; +class LLWearable; +class LLViewerVisualParam; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerInterface +// +// Interface class to generalize functionality shared by LLTexLayer +// and LLTexLayerTemplate. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerInterface +{ +public: + enum ERenderPass + { + RP_COLOR, + RP_BUMP, + RP_SHINE + }; + + LLTexLayerInterface(LLTexLayerSet* const layer_set); + LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); + virtual ~LLTexLayerInterface() {} + + virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; + virtual void deleteCaches() = 0; + virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; + virtual BOOL isInvisibleAlphaMask() const = 0; + + const LLTexLayerInfo* getInfo() const { return mInfo; } + virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions + + const std::string& getName() const; + const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } + LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } + + void invalidateMorphMasks(); + virtual void setHasMorph(BOOL newval) { mHasMorph = newval; } + BOOL hasMorph() const { return mHasMorph; } + BOOL isMorphValid() const { return mMorphMasksValid; } + + void requestUpdate(); + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; + BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } + + ERenderPass getRenderPass() const; + BOOL isVisibilityMask() const; + +protected: + const std::string& getGlobalColor() const; + LLViewerVisualParam* getVisualParamPtr(S32 index) const; + +protected: + LLTexLayerSet* const mTexLayerSet; + const LLTexLayerInfo* mInfo; + BOOL mMorphMasksValid; + BOOL mHasMorph; + + // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. + param_color_list_t mParamColorList; + param_alpha_list_t mParamAlphaList; + // mGlobalColor name stored in mInfo + // mFixedColor value stored in mInfo +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerTemplate +// +// Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerTemplate : public LLTexLayerInterface +{ +public: + LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); + LLTexLayerTemplate(const LLTexLayerTemplate &layer); + /*virtual*/ ~LLTexLayerTemplate(); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ void setHasMorph(BOOL newval); + /*virtual*/ void deleteCaches(); + /*virtual*/ BOOL isInvisibleAlphaMask() const; +protected: + U32 updateWearableCache() const; + LLTexLayer* getLayer(U32 i) const; + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } +private: + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. + typedef std::vector wearable_cache_t; + mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayer +// +// A single texture layer. Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayer : public LLTexLayerInterface +{ +public: + LLTexLayer(LLTexLayerSet* const layer_set); + LLTexLayer(const LLTexLayer &layer, LLWearable *wearable); + LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable); + /*virtual*/ ~LLTexLayer(); + + /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + + /*virtual*/ void deleteCaches(); + const U8* getAlphaData() const; + + BOOL findNetColor(LLColor4* color) const; + /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ BOOL isInvisibleAlphaMask() const; + + void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } + LLLocalTextureObject* getLTO() { return mLocalTextureObject; } + + static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); +protected: + LLUUID getUUID() const; +private: + typedef std::map alpha_cache_t; + alpha_cache_t mAlphaCache; + LLLocalTextureObject* mLocalTextureObject; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSet +// +// An ordered set of texture layers that gets composited into a single texture. +// Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSet +{ +public: + LLTexLayerSet(LLAvatarAppearance* const appearance); + virtual ~LLTexLayerSet(); + + const LLTexLayerSetInfo* getInfo() const { return mInfo; } + BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions + + BOOL render(S32 x, S32 y, S32 width, S32 height); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); + + BOOL isBodyRegion(const std::string& region) const; + void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); + BOOL isMorphValid() const; + virtual void requestUpdate() = 0; + void invalidateMorphMasks(); + void deleteCaches(); + LLTexLayerInterface* findLayerByName(const std::string& name); + void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); + + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + const std::string getBodyRegionName() const; + LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } + void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } + BOOL isVisible() const { return mIsVisible; } + + static BOOL sHasCaches; + +protected: + typedef std::vector layer_list_t; + layer_list_t mLayerList; + layer_list_t mMaskLayerList; + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. + BOOL mIsVisible; + + LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; + const LLTexLayerSetInfo* mInfo; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSetInfo +// +// Contains shared layer set data. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSetInfo +{ + friend class LLTexLayerSet; +public: + LLTexLayerSetInfo(); + ~LLTexLayerSetInfo(); + BOOL parseXml(LLXmlTreeNode* node); + void createVisualParams(LLAvatarAppearance *appearance); + S32 getWidth() const { return mWidth; } + S32 getHeight() const { return mHeight; } +protected: + std::string mBodyRegion; + S32 mWidth; + S32 mHeight; + std::string mStaticAlphaFileName; + BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) + typedef std::vector layer_info_list_t; + layer_info_list_t mLayerInfoList; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerStaticImageList +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerStaticImageList : public LLSingleton +{ +public: + LLTexLayerStaticImageList(); + ~LLTexLayerStaticImageList(); + LLTexture* getTexture(const std::string& file_name, BOOL is_mask); + LLImageTGA* getImageTGA(const std::string& file_name); + void deleteCachedImages(); + void dumpByteCount() const; +protected: + BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); +private: + LLStringTable mImageNames; + typedef std::map > texture_map_t; + texture_map_t mStaticImageList; + typedef std::map > image_tga_map_t; + image_tga_map_t mStaticImageListTGA; + S32 mGLBytes; + S32 mTGABytes; +}; + +#endif // LL_LLTEXLAYER_H diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp new file mode 100644 index 0000000000..c843367357 --- /dev/null +++ b/indra/llappearance/lltexlayerparams.cpp @@ -0,0 +1,571 @@ +/** + * @file lltexlayerparams.cpp + * @brief Texture layer parameters + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lltexlayerparams.h" + +#include "llavatarappearance.h" +//#include "llagentcamera.h" +#include "llimagetga.h" +#include "llquantize.h" +#include "lltexlayer.h" +#include "lltexturemanagerbridge.h" +#include "llwearable.h" +#include "llui.h" + +//----------------------------------------------------------------------------- +// LLTexLayerParam +//----------------------------------------------------------------------------- +LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : + mTexLayer(layer), + mAvatarAppearance(NULL) +{ + if (mTexLayer != NULL) + { + mAvatarAppearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); + } + else + { + llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl; + } +} + +LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) : + mTexLayer(NULL), + mAvatarAppearance(appearance) +{ +} + + +BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance) +{ + LLViewerVisualParam::setInfo(info); + + if (add_to_appearance) + { + mAvatarAppearance->addVisualParam( this); + } + + return TRUE; +} + + +//----------------------------------------------------------------------------- +// LLTexLayerParamAlpha +//----------------------------------------------------------------------------- + +// static +LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; + +// static +void LLTexLayerParamAlpha::dumpCacheByteCount() +{ + S32 gl_bytes = 0; + getCacheByteCount( &gl_bytes); + llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl; +} + +// static +void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) +{ + *gl_bytes = 0; + + for (param_alpha_ptr_list_t::iterator iter = sInstances.begin(); + iter != sInstances.end(); iter++) + { + LLTexLayerParamAlpha* instance = *iter; + LLTexture* tex = instance->mCachedProcessedTexture; + if (tex) + { + S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); + + if (tex->hasGLTexture()) + { + *gl_bytes += bytes; + } + } + } +} + +LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) : + LLTexLayerParam(layer), + mCachedProcessedTexture(NULL), + mNeedsCreateTexture(FALSE), + mStaticImageInvalid(FALSE), + mAvgDistortionVec(1.f, 1.f, 1.f), + mCachedEffectiveWeight(0.f) +{ + sInstances.push_front(this); +} + +LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) : + LLTexLayerParam(appearance), + mCachedProcessedTexture(NULL), + mNeedsCreateTexture(FALSE), + mStaticImageInvalid(FALSE), + mAvgDistortionVec(1.f, 1.f, 1.f), + mCachedEffectiveWeight(0.f) +{ + sInstances.push_front(this); +} + + +LLTexLayerParamAlpha::~LLTexLayerParamAlpha() +{ + deleteCaches(); + sInstances.remove(this); +} + +/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const +{ + LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer); + *new_param = *this; + return new_param; +} + +void LLTexLayerParamAlpha::deleteCaches() +{ + mStaticImageTGA = NULL; // deletes image + mCachedProcessedTexture = NULL; + mStaticImageRaw = NULL; + mNeedsCreateTexture = FALSE; +} + +BOOL LLTexLayerParamAlpha::getMultiplyBlend() const +{ + return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; +} + +void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake) +{ + if (mIsAnimating || mTexLayer == NULL) + { + return; + } + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + F32 new_weight = llclamp(weight, min_weight, max_weight); + U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); + U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); + if (cur_u8 != new_u8) + { + mCurWeight = new_weight; + + if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + { + if (!mAvatarAppearance->isUsingBakedTextures()) + { + upload_bake = FALSE; + } + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); + mTexLayer->invalidateMorphMasks(); + } + } +} + +void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake) +{ + // do not animate dummy parameters + if (mIsDummy) + { + setWeight(target_value, upload_bake); + return; + } + + mTargetWeight = target_value; + setWeight(target_value, upload_bake); + mIsAnimating = TRUE; + if (mNext) + { + mNext->setAnimationTarget(target_value, upload_bake); + } +} + +void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake) +{ + if (mNext) + { + mNext->animate(delta, upload_bake); + } +} + +BOOL LLTexLayerParamAlpha::getSkip() const +{ + if (!mTexLayer) + { + return TRUE; + } + + const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); + + if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight) + { + F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + if (is_approx_zero(effective_weight)) + { + return TRUE; + } + } + + LLWearableType::EType type = (LLWearableType::EType)getWearableType(); + if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type)) + { + return TRUE; + } + + return FALSE; +} + + +BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) +{ + BOOL success = TRUE; + + if (!mTexLayer) + { + return success; + } + + F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + BOOL weight_changed = effective_weight != mCachedEffectiveWeight; + if (getSkip()) + { + return success; + } + + LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo(); + gGL.flush(); + if (info->mMultiplyBlend) + { + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function + } + else + { + gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function + } + + if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid) + { + if (mStaticImageTGA.isNull()) + { + // Don't load the image file until we actually need it the first time. Like now. + mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); + // We now have something in one of our caches + LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE; + + if (mStaticImageTGA.isNull()) + { + llwarns << "Unable to load static file: " << info->mStaticImageFileName << llendl; + mStaticImageInvalid = TRUE; // don't try again. + return FALSE; + } + } + + const S32 image_tga_width = mStaticImageTGA->getWidth(); + const S32 image_tga_height = mStaticImageTGA->getHeight(); + if (!mCachedProcessedTexture || + (mCachedProcessedTexture->getWidth() != image_tga_width) || + (mCachedProcessedTexture->getHeight() != image_tga_height) || + (weight_changed)) + { +// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; + mCachedEffectiveWeight = effective_weight; + + if (!mCachedProcessedTexture) + { + llassert(gTextureManagerBridgep); + mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, FALSE); + + // We now have something in one of our caches + LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE; + + mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); + } + + // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. + mStaticImageRaw = NULL; + mStaticImageRaw = new LLImageRaw; + mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); + mNeedsCreateTexture = TRUE; + } + + if (mCachedProcessedTexture) + { + { + // Create the GL texture, and then hang onto it for future use. + if (mNeedsCreateTexture) + { + mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); + mNeedsCreateTexture = FALSE; + gGL.getTexUnit(0)->bind(mCachedProcessedTexture); + mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); + } + + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(mCachedProcessedTexture); + gl_rect_2d_simple_tex(width, height); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + stop_glerror(); + } + } + + // Don't keep the cache for other people's avatars + // (It's not really a "cache" in that case, but the logic is the same) + if (!mAvatarAppearance->isSelf()) + { + mCachedProcessedTexture = NULL; + } + } + else + { + LLGLDisable no_alpha(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f(0.f, 0.f, 0.f, effective_weight); + gl_rect_2d_simple(width, height); + } + + return success; +} + +//----------------------------------------------------------------------------- +// LLTexLayerParamAlphaInfo +//----------------------------------------------------------------------------- +LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : + mMultiplyBlend(FALSE), + mSkipIfZeroWeight(FALSE), + mDomain(0.f) +{ +} + +BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) +{ + llassert(node->hasName("param") && node->getChildByName("param_alpha")); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return FALSE; + + LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha"); + if (!param_alpha_node) + { + return FALSE; + } + + static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); + if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName)) + { + // Don't load the image file until it's actually needed. + } +// else +// { +// llwarns << " element is missing tga_file attribute." << llendl; +// } + + static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); + param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend); + + static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); + param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight); + + static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); + param_alpha_node->getFastAttributeF32(domain_string, mDomain); + + return TRUE; +} + + + + +LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) : + LLTexLayerParam(layer), + mAvgDistortionVec(1.f, 1.f, 1.f) +{ +} + +LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) : + LLTexLayerParam(appearance), + mAvgDistortionVec(1.f, 1.f, 1.f) +{ +} + +LLTexLayerParamColor::~LLTexLayerParamColor() +{ +} + +/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const +{ + LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer); + *new_param = *this; + return new_param; +} + +LLColor4 LLTexLayerParamColor::getNetColor() const +{ + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); + + llassert(info->mNumColors >= 1); + + F32 effective_weight = (mAvatarAppearance && (mAvatarAppearance->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); + + S32 index_last = info->mNumColors - 1; + F32 scaled_weight = effective_weight * index_last; + S32 index_start = (S32) scaled_weight; + S32 index_end = index_start + 1; + if (index_start == index_last) + { + return info->mColors[index_last]; + } + else + { + F32 weight = scaled_weight - index_start; + const LLColor4 *start = &info->mColors[ index_start ]; + const LLColor4 *end = &info->mColors[ index_end ]; + return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX], + (1.f - weight) * start->mV[VY] + weight * end->mV[VY], + (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], + (1.f - weight) * start->mV[VW] + weight * end->mV[VW]); + } +} + +void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake) +{ + if (mIsAnimating) + { + return; + } + + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + F32 new_weight = llclamp(weight, min_weight, max_weight); + U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); + U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); + if (cur_u8 != new_u8) + { + mCurWeight = new_weight; + + if (info->mNumColors <= 0) + { + // This will happen when we set the default weight the first time. + return; + } + + if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + { + onGlobalColorChanged(upload_bake); + if (mTexLayer) + { + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); + } + } + +// llinfos << "param " << mName << " = " << new_weight << llendl; + } +} + +void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake) +{ + // set value first then set interpolating flag to ignore further updates + mTargetWeight = target_value; + setWeight(target_value, upload_bake); + mIsAnimating = TRUE; + if (mNext) + { + mNext->setAnimationTarget(target_value, upload_bake); + } +} + +void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake) +{ + if (mNext) + { + mNext->animate(delta, upload_bake); + } +} + +//----------------------------------------------------------------------------- +// LLTexLayerParamColorInfo +//----------------------------------------------------------------------------- +LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : + mOperation(LLTexLayerParamColor::OP_ADD), + mNumColors(0) +{ +} + +BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) +{ + llassert(node->hasName("param") && node->getChildByName("param_color")); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return FALSE; + + LLXmlTreeNode* param_color_node = node->getChildByName("param_color"); + if (!param_color_node) + { + return FALSE; + } + + std::string op_string; + static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); + if (param_color_node->getFastAttributeString(operation_string, op_string)) + { + LLStringUtil::toLower(op_string); + if (op_string == "add") mOperation = LLTexLayerParamColor::OP_ADD; + else if (op_string == "multiply") mOperation = LLTexLayerParamColor::OP_MULTIPLY; + else if (op_string == "blend") mOperation = LLTexLayerParamColor::OP_BLEND; + } + + mNumColors = 0; + + LLColor4U color4u; + for (LLXmlTreeNode* child = param_color_node->getChildByName("value"); + child; + child = param_color_node->getNextNamedChild()) + { + if ((mNumColors < MAX_COLOR_VALUES)) + { + static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); + if (child->getFastAttributeColor4U(color_string, color4u)) + { + mColors[ mNumColors ].setVec(color4u); + mNumColors++; + } + } + } + if (!mNumColors) + { + llwarns << " is missing sub-elements" << llendl; + return FALSE; + } + + if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1)) + { + llwarns << " with operation\"blend\" must have exactly one " << llendl; + return FALSE; + } + + return TRUE; +} diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h new file mode 100644 index 0000000000..dbffd15751 --- /dev/null +++ b/indra/llappearance/lltexlayerparams.h @@ -0,0 +1,195 @@ +/** + * @file lltexlayerparams.h + * @brief Texture layer parameters, used by lltexlayer. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXLAYERPARAMS_H +#define LL_LLTEXLAYERPARAMS_H + +#include "llpointer.h" +#include "v4color.h" +#include "llviewervisualparam.h" + +class LLAvatarAppearance; +class LLImageRaw; +class LLImageTGA; +class LLTexLayer; +class LLTexLayerInterface; +class LLTexture; +class LLWearable; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParam +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParam : public LLViewerVisualParam +{ +public: + LLTexLayerParam(LLTexLayerInterface *layer); + LLTexLayerParam(LLAvatarAppearance *appearance); + /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; + +protected: + LLTexLayerInterface* mTexLayer; + LLAvatarAppearance* mAvatarAppearance; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamAlpha +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParamAlpha : public LLTexLayerParam +{ +public: + LLTexLayerParamAlpha( LLTexLayerInterface* layer ); + LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); + /*virtual*/ ~LLTexLayerParamAlpha(); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + BOOL render( S32 x, S32 y, S32 width, S32 height ); + BOOL getSkip() const; + void deleteCaches(); + BOOL getMultiplyBlend() const; + +private: + LLPointer mCachedProcessedTexture; + LLPointer mStaticImageTGA; + LLPointer mStaticImageRaw; + BOOL mNeedsCreateTexture; + BOOL mStaticImageInvalid; + LLVector4a mAvgDistortionVec; + F32 mCachedEffectiveWeight; + +public: + // Global list of instances for gathering statistics + static void dumpCacheByteCount(); + static void getCacheByteCount( S32* gl_bytes ); + + typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; + static param_alpha_ptr_list_t sInstances; +}; +class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamAlpha; +public: + LLTexLayerParamAlphaInfo(); + /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + +private: + std::string mStaticImageFileName; + BOOL mMultiplyBlend; + BOOL mSkipIfZeroWeight; + F32 mDomain; +}; +// +// LLTexLayerParamAlpha +//----------------------------------------------------------------------------- + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamColor +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParamColor : public LLTexLayerParam +{ +public: + enum EColorOperation + { + OP_ADD = 0, + OP_MULTIPLY = 1, + OP_BLEND = 2, + OP_COUNT = 3 // Number of operations + }; + + LLTexLayerParamColor( LLTexLayerInterface* layer ); + LLTexLayerParamColor( LLAvatarAppearance* appearance ); + /* virtual */ ~LLTexLayerParamColor(); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); + + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + LLColor4 getNetColor() const; +protected: + virtual void onGlobalColorChanged(bool upload_bake) {} +private: + LLVector4a mAvgDistortionVec; +}; + +class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamColor; + +public: + LLTexLayerParamColorInfo(); + virtual ~LLTexLayerParamColorInfo() {}; + BOOL parseXml( LLXmlTreeNode* node ); + LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } +private: + enum { MAX_COLOR_VALUES = 20 }; + LLTexLayerParamColor::EColorOperation mOperation; + LLColor4 mColors[MAX_COLOR_VALUES]; + S32 mNumColors; +}; + +typedef std::vector param_color_list_t; +typedef std::vector param_alpha_list_t; +typedef std::vector param_color_info_list_t; +typedef std::vector param_alpha_info_list_t; + +#endif diff --git a/indra/llappearance/lltexturemanagerbridge.cpp b/indra/llappearance/lltexturemanagerbridge.cpp new file mode 100644 index 0000000000..33f2185e4f --- /dev/null +++ b/indra/llappearance/lltexturemanagerbridge.cpp @@ -0,0 +1,32 @@ + /** + * @file lltexturemanagerbridge.cpp + * @brief Defined a null texture manager bridge. Applications must provide their own bridge implementaton. + * + * $LicenseInfo:firstyear=2012&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 "lltexturemanagerbridge.h" + +// Define a null texture manager bridge. Applications must provide their own bridge implementaton. +LLTextureManagerBridge* gTextureManagerBridgep = NULL; + + diff --git a/indra/llappearance/lltexturemanagerbridge.h b/indra/llappearance/lltexturemanagerbridge.h new file mode 100644 index 0000000000..20f5d0fd3c --- /dev/null +++ b/indra/llappearance/lltexturemanagerbridge.h @@ -0,0 +1,45 @@ +/** + * @file lltexturemanagerbridge.h + * @brief Bridge to an application-specific texture manager. + * + * $LicenseInfo:firstyear=2012&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_TEXTUREMANAGERBRIDGE_H +#define LL_TEXTUREMANAGERBRIDGE_H + +#include "llpointer.h" +#include "lltexture.h" + +// Abstract bridge interface +class LLTextureManagerBridge +{ +public: + virtual LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0; + virtual LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0; + virtual LLTexture* getFetchedTexture(const LLUUID &image_id) = 0; +}; + +extern LLTextureManagerBridge* gTextureManagerBridgep; + +#endif // LL_TEXTUREMANAGERBRIDGE_H + diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp new file mode 100644 index 0000000000..e1ddeeeff0 --- /dev/null +++ b/indra/llappearance/llviewervisualparam.cpp @@ -0,0 +1,165 @@ +/** + * @file llviewervisualparam.cpp + * @brief Implementation of LLViewerVisualParam class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "llviewervisualparam.h" +#include "llxmltree.h" +#include "llui.h" +#include "llwearable.h" + +//----------------------------------------------------------------------------- +// LLViewerVisualParamInfo() +//----------------------------------------------------------------------------- +LLViewerVisualParamInfo::LLViewerVisualParamInfo() + : + mWearableType( LLWearableType::WT_INVALID ), + mCrossWearable(FALSE), + mCamDist( 0.5f ), + mCamAngle( 0.f ), + mCamElevation( 0.f ), + mEditGroupDisplayOrder( 0 ), + mShowSimple(FALSE), + mSimpleMin(0.f), + mSimpleMax(100.f) +{ +} + +LLViewerVisualParamInfo::~LLViewerVisualParamInfo() +{ +} + +//----------------------------------------------------------------------------- +// parseXml() +//----------------------------------------------------------------------------- +BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) +{ + llassert( node->hasName( "param" ) ); + + if (!LLVisualParamInfo::parseXml(node)) + return FALSE; + + // VIEWER SPECIFIC PARAMS + + std::string wearable; + static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable"); + if( node->getFastAttributeString( wearable_string, wearable) ) + { + mWearableType = LLWearableType::typeNameToType( wearable ); + } + + static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); + if (!node->getFastAttributeString( edit_group_string, mEditGroup)) + { + mEditGroup = ""; + } + + static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); + if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable)) + { + mCrossWearable = FALSE; + } + + // Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). + static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance"); + node->getFastAttributeF32( camera_distance_string, mCamDist ); + static LLStdStringHandle camera_angle_string = LLXmlTree::addAttributeString("camera_angle"); + node->getFastAttributeF32( camera_angle_string, mCamAngle ); // in degrees + static LLStdStringHandle camera_elevation_string = LLXmlTree::addAttributeString("camera_elevation"); + node->getFastAttributeF32( camera_elevation_string, mCamElevation ); + + mCamAngle += 180; + + static S32 params_loaded = 0; + + // By default, parameters are displayed in the order in which they appear in the xml file. + // "edit_group_order" overriddes. + static LLStdStringHandle edit_group_order_string = LLXmlTree::addAttributeString("edit_group_order"); + if( !node->getFastAttributeF32( edit_group_order_string, mEditGroupDisplayOrder ) ) + { + mEditGroupDisplayOrder = (F32)params_loaded; + } + + params_loaded++; + + return TRUE; +} + +/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out) +{ + LLVisualParamInfo::toStream(out); + + out << mWearableType << "\t"; + out << mEditGroup << "\t"; + out << mEditGroupDisplayOrder << "\t"; +} + +//----------------------------------------------------------------------------- +// LLViewerVisualParam() +//----------------------------------------------------------------------------- +LLViewerVisualParam::LLViewerVisualParam() +{ +} + +//----------------------------------------------------------------------------- +// setInfo() +//----------------------------------------------------------------------------- + +BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return FALSE; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight(), FALSE ); + return TRUE; +} + +/* +//============================================================================= +// These virtual functions should always be overridden, +// but are included here for use as templates +//============================================================================= + +//----------------------------------------------------------------------------- +// parseData() +//----------------------------------------------------------------------------- +BOOL LLViewerVisualParam::parseData(LLXmlTreeNode *node) +{ + LLViewerVisualParamInfo* info = new LLViewerVisualParamInfo; + + info->parseXml(node); + if (!setInfo(info)) + return FALSE; + + return TRUE; +} +*/ diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h new file mode 100644 index 0000000000..3bc95cbfbf --- /dev/null +++ b/indra/llappearance/llviewervisualparam.h @@ -0,0 +1,109 @@ +/** + * @file llviewervisualparam.h + * @brief viewer side visual params (with data file parsing) + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLViewerVisualParam_H +#define LL_LLViewerVisualParam_H + +#include "v3math.h" +#include "llstring.h" +#include "llvisualparam.h" + +class LLWearable; + +//----------------------------------------------------------------------------- +// LLViewerVisualParamInfo +//----------------------------------------------------------------------------- +class LLViewerVisualParamInfo : public LLVisualParamInfo +{ + friend class LLViewerVisualParam; +public: + LLViewerVisualParamInfo(); + /*virtual*/ ~LLViewerVisualParamInfo(); + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + + /*virtual*/ void toStream(std::ostream &out); + +protected: + S32 mWearableType; + BOOL mCrossWearable; + std::string mEditGroup; + F32 mCamDist; + F32 mCamAngle; // degrees + F32 mCamElevation; + F32 mEditGroupDisplayOrder; + BOOL mShowSimple; // show edit controls when in "simple ui" mode? + F32 mSimpleMin; // when in simple UI, apply this minimum, range 0.f to 100.f + F32 mSimpleMax; // when in simple UI, apply this maximum, range 0.f to 100.f +}; + +//----------------------------------------------------------------------------- +// LLViewerVisualParam +// VIRTUAL CLASS +// a viewer side interface class for a generalized parametric modification of the avatar mesh +//----------------------------------------------------------------------------- +class LLViewerVisualParam : public LLVisualParam +{ +public: + LLViewerVisualParam(); + /*virtual*/ ~LLViewerVisualParam(){}; + + // Special: These functions are overridden by child classes + LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; }; + // This sets mInfo and calls initialization functions + BOOL setInfo(LLViewerVisualParamInfo *info); + + virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + + // New Virtual functions + virtual F32 getTotalDistortion() = 0; + virtual const LLVector4a& getAvgDistortion() = 0; + virtual F32 getMaxDistortion() = 0; + virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; + virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; + + // interface methods + F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } + S32 getWearableType() const { return getInfo()->mWearableType; } + const std::string& getEditGroup() const { return getInfo()->mEditGroup; } + + F32 getCameraDistance() const { return getInfo()->mCamDist; } + F32 getCameraAngle() const { return getInfo()->mCamAngle; } // degrees + F32 getCameraElevation() const { return getInfo()->mCamElevation; } + + BOOL getShowSimple() const { return getInfo()->mShowSimple; } + F32 getSimpleMin() const { return getInfo()->mSimpleMin; } + F32 getSimpleMax() const { return getInfo()->mSimpleMax; } + + BOOL getCrossWearable() const { return getInfo()->mCrossWearable; } + +}; + +#endif // LL_LLViewerVisualParam_H diff --git a/indra/llappearance/llvoavatardefines.cpp b/indra/llappearance/llvoavatardefines.cpp new file mode 100644 index 0000000000..48ef63ab64 --- /dev/null +++ b/indra/llappearance/llvoavatardefines.cpp @@ -0,0 +1,249 @@ +/** + * @file llvoavatardefines.cpp + * @brief Implementation of LLVOAvatarDefines::LLVOAvatarDictionary + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "llvoavatardefines.h" +//#include "llviewercontrol.h" // gSavedSettings + +const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; +const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; +const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; + +using namespace LLVOAvatarDefines; + +/********************************************************************************* + * Edit this function to add/remove/change textures and mesh definitions for avatars. + */ + +LLVOAvatarDictionary::Textures::Textures() +{ + addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); + addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); + addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); + addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); + addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); + addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); + addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); + addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); + addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); + addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); + + addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + + addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); +} + +LLVOAvatarDictionary::BakedTextures::BakedTextures() +{ + // Baked textures + addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, + "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", + 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, + 5, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, + "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", + 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, + TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, + 8, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, + "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", + 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, + TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, + 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, + "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", + 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, + 2, LLWearableType::WT_EYES, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, + "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", + 1, TEX_SKIRT, + 1, LLWearableType::WT_SKIRT)); + + addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, + "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", + 2, TEX_HAIR, TEX_HAIR_ALPHA, + 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); +} + +LLVOAvatarDictionary::Meshes::Meshes() +{ + // Meshes + addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); + addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); + addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently + addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); + addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); + addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); + addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); + addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); +} + +/* + * + *********************************************************************************/ + +LLVOAvatarDictionary::LLVOAvatarDictionary() +{ + createAssociations(); +} + +//virtual +LLVOAvatarDictionary::~LLVOAvatarDictionary() +{ +} + +// Baked textures are composites of textures; for each such composited texture, +// map it to the baked texture. +void LLVOAvatarDictionary::createAssociations() +{ + for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) + { + const EBakedTextureIndex baked_index = (iter->first); + const BakedEntry *dict = (iter->second); + + // For each texture that this baked texture index affects, associate those textures + // with this baked texture index. + for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); + local_texture_iter != dict->mLocalTextures.end(); + local_texture_iter++) + { + const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; + mTextures[local_texture_index]->mIsUsedByBakedTexture = true; + mTextures[local_texture_index]->mBakedTextureIndex = baked_index; + } + } + +} + +LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name, + bool is_local_texture, + EBakedTextureIndex baked_texture_index, + const std::string &default_image_name, + LLWearableType::EType wearable_type) : + LLDictionaryEntry(name), + mIsLocalTexture(is_local_texture), + mIsBakedTexture(!is_local_texture), + mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), + mBakedTextureIndex(baked_texture_index), + mDefaultImageName(default_image_name), + mWearableType(wearable_type) +{ +} + +LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, + U8 level, + LLJointPickName pick) : + LLDictionaryEntry(name), + mBakedID(baked_index), + mLOD(level), + mPickName(pick) +{ +} +LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, + const std::string &name, + const std::string &hash_name, + U32 num_local_textures, + ... ) : + LLDictionaryEntry(name), + mWearablesHashID(LLUUID(hash_name)), + mTextureIndex(tex_index) +{ + va_list argp; + + va_start(argp, num_local_textures); + + // Read in local textures + for (U8 i=0; i < num_local_textures; i++) + { + ETextureIndex t = (ETextureIndex)va_arg(argp,int); + mLocalTextures.push_back(t); + } + + // Read in number of wearables + const U32 num_wearables = (U32)va_arg(argp,int); + // Read in wearables + for (U8 i=0; i < num_wearables; i++) + { + LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); + mWearables.push_back(t); + } +} + +// static +ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) +{ + return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; +} + +//static +EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) +{ + U8 index = 0; + while (index < BAKED_NUM_INDICES) + { + const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + if (be && be->mName.compare(name) == 0) + { + // baked texture found + return (EBakedTextureIndex) index; + } + index++; + } + // baked texture could not be found + return BAKED_NUM_INDICES; +} + +// static +LLWearableType::EType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index ) +{ + return getInstance()->getTexture(index)->mWearableType; +} + diff --git a/indra/llappearance/llvoavatardefines.h b/indra/llappearance/llvoavatardefines.h new file mode 100644 index 0000000000..7b0442bffb --- /dev/null +++ b/indra/llappearance/llvoavatardefines.h @@ -0,0 +1,226 @@ +/** + * @file llvoavatardefines.h + * @brief Various LLAvatarAppearance related definitions + * LLViewerObject + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLVOAVATAR_DEFINES_H +#define LLVOAVATAR_DEFINES_H + +#include +#include "lljointpickname.h" +#include "llwearable.h" +#include "lldictionary.h" + +namespace LLVOAvatarDefines +{ + +extern const S32 SCRATCH_TEX_WIDTH; +extern const S32 SCRATCH_TEX_HEIGHT; +extern const S32 IMPOSTOR_PERIOD; + +//-------------------------------------------------------------------- +// Enums +//-------------------------------------------------------------------- +enum ETextureIndex +{ + TEX_HEAD_BODYPAINT = 0, + TEX_UPPER_SHIRT, + TEX_LOWER_PANTS, + TEX_EYES_IRIS, + TEX_HAIR, + TEX_UPPER_BODYPAINT, + TEX_LOWER_BODYPAINT, + TEX_LOWER_SHOES, + TEX_HEAD_BAKED, // Pre-composited + TEX_UPPER_BAKED, // Pre-composited + TEX_LOWER_BAKED, // Pre-composited + TEX_EYES_BAKED, // Pre-composited + TEX_LOWER_SOCKS, + TEX_UPPER_JACKET, + TEX_LOWER_JACKET, + TEX_UPPER_GLOVES, + TEX_UPPER_UNDERSHIRT, + TEX_LOWER_UNDERPANTS, + TEX_SKIRT, + TEX_SKIRT_BAKED, // Pre-composited + TEX_HAIR_BAKED, // Pre-composited + TEX_LOWER_ALPHA, + TEX_UPPER_ALPHA, + TEX_HEAD_ALPHA, + TEX_EYES_ALPHA, + TEX_HAIR_ALPHA, + TEX_HEAD_TATTOO, + TEX_UPPER_TATTOO, + TEX_LOWER_TATTOO, + TEX_NUM_INDICES +}; + +enum EBakedTextureIndex +{ + BAKED_HEAD = 0, + BAKED_UPPER, + BAKED_LOWER, + BAKED_EYES, + BAKED_SKIRT, + BAKED_HAIR, + BAKED_NUM_INDICES +}; + +// Reference IDs for each mesh. Used as indices for vector of joints +enum EMeshIndex +{ + MESH_ID_HAIR = 0, + MESH_ID_HEAD, + MESH_ID_EYELASH, + MESH_ID_UPPER_BODY, + MESH_ID_LOWER_BODY, + MESH_ID_EYEBALL_LEFT, + MESH_ID_EYEBALL_RIGHT, + MESH_ID_SKIRT, + MESH_ID_NUM_INDICES +}; + +//-------------------------------------------------------------------- +// Vector Types +//-------------------------------------------------------------------- +typedef std::vector texture_vec_t; +typedef std::vector bakedtexture_vec_t; +typedef std::vector mesh_vec_t; +typedef std::vector wearables_vec_t; + +//------------------------------------------------------------------------ +// LLVOAvatarDictionary +// +// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. +// information that is common to all avatars. +// +// This holds const data - it is initialized once and the contents never change after that. +//------------------------------------------------------------------------ +class LLVOAvatarDictionary : public LLSingleton +{ + //-------------------------------------------------------------------- + // Constructors and Destructors + //-------------------------------------------------------------------- +public: + LLVOAvatarDictionary(); + virtual ~LLVOAvatarDictionary(); +private: + void createAssociations(); + + //-------------------------------------------------------------------- + // Local and baked textures + //-------------------------------------------------------------------- +public: + struct TextureEntry : public LLDictionaryEntry + { + TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml + bool is_local_texture, + EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, + const std::string& default_image_name = "", + LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); + const std::string mDefaultImageName; + const LLWearableType::EType mWearableType; + // It's either a local texture xor baked + BOOL mIsLocalTexture; + BOOL mIsBakedTexture; + // If it's a local texture, it may be used by a baked texture + BOOL mIsUsedByBakedTexture; + EBakedTextureIndex mBakedTextureIndex; + }; + + struct Textures : public LLDictionary + { + Textures(); + } mTextures; + const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } + const Textures& getTextures() const { return mTextures; } + + //-------------------------------------------------------------------- + // Meshes + //-------------------------------------------------------------------- +public: + struct MeshEntry : public LLDictionaryEntry + { + MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, // names of mesh types as they are used in avatar_lad.xml + U8 level, + LLJointPickName pick); + // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml + // Otherwise meshes will be unable to be found, or levels of detail will be ignored + const U8 mLOD; + const EBakedTextureIndex mBakedID; + const LLJointPickName mPickName; + }; + + struct Meshes : public LLDictionary + { + Meshes(); + } mMeshes; + const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } + const Meshes& getMeshes() const { return mMeshes; } + + //-------------------------------------------------------------------- + // Baked Textures + //-------------------------------------------------------------------- +public: + struct BakedEntry : public LLDictionaryEntry + { + BakedEntry(ETextureIndex tex_index, + const std::string &name, // unused, but necessary for templating. + const std::string &hash_name, + U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list + // Local Textures + const ETextureIndex mTextureIndex; + texture_vec_t mLocalTextures; + // Wearables + const LLUUID mWearablesHashID; + wearables_vec_t mWearables; + }; + + struct BakedTextures: public LLDictionary + { + BakedTextures(); + } mBakedTextures; + const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } + const BakedTextures& getBakedTextures() const { return mBakedTextures; } + + //-------------------------------------------------------------------- + // Convenience Functions + //-------------------------------------------------------------------- +public: + // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED + static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t); + + // find a baked texture index based on its name + static EBakedTextureIndex findBakedByRegionName(std::string name); + + // Given a texture entry, determine which wearable type owns it. + static LLWearableType::EType getTEWearableType(ETextureIndex index); + +}; // End LLVOAvatarDictionary + +} // End namespace LLVOAvatarDefines + +#endif //LL_VO_AVATARDEFINES_H diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index d72999d8c7..64bd921ec5 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -24,14 +24,13 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" -//#include "llagent.h" -//#include "llagentcamera.h" -#include "llagentwearables.h" +#include "llavatarappearance.h" +//#include "llagentwearables.h" //#include "lldictionary.h" //#include "llfloatersidepanelcontainer.h" -//#include "lllocaltextureobject.h" +#include "lllocaltextureobject.h" //#include "llnotificationsutil.h" //#include "llviewertexturelist.h" //#include "llinventorymodel.h" @@ -39,12 +38,11 @@ //#include "llsidepanelappearance.h" #include "lltexlayer.h" //#include "lltexglobalcolor.h" +#include "lltexturemanagerbridge.h" //#include "lltrans.h" //#include "llviewerregion.h" #include "llvisualparam.h" -//#include "llvoavatar.h" -//#include "llvoavatarself.h" -//#include "llvoavatardefines.h" +#include "llvoavatardefines.h" #include "llwearable.h" //#include "llviewercontrol.h" @@ -53,52 +51,10 @@ using namespace LLVOAvatarDefines; // static S32 LLWearable::sCurrentDefinitionVersion = 1; -// support class - remove for 2.1 (hackity hack hack) -class LLOverrideBakedTextureUpdate -{ -public: - LLOverrideBakedTextureUpdate(bool temp_state) - { - U32 num_bakes = (U32) LLVOAvatarDefines::BAKED_NUM_INDICES; - for( U32 index = 0; index < num_bakes; ++index ) - { - composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); - } - gAgentAvatarp->setCompositeUpdatesEnabled(temp_state); - } - - ~LLOverrideBakedTextureUpdate() - { - U32 num_bakes = (U32)LLVOAvatarDefines::BAKED_NUM_INDICES; - for( U32 index = 0; index < num_bakes; ++index ) - { - gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); - } - } -private: - bool composite_enabled[LLVOAvatarDefines::BAKED_NUM_INDICES]; -}; - // Private local functions static std::string terse_F32_to_string(F32 f); -static std::string asset_id_to_filename(const LLUUID &asset_id); - -LLWearable::LLWearable(const LLTransactionID& transaction_id) : - mDefinitionVersion(LLWearable::sCurrentDefinitionVersion), - mType(LLWearableType::WT_INVALID) -{ - mTransactionID = transaction_id; - mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); -} - -LLWearable::LLWearable(const LLAssetID& asset_id) : - mDefinitionVersion( LLWearable::sCurrentDefinitionVersion ), - mType(LLWearableType::WT_INVALID) -{ - mAssetID = asset_id; - mTransactionID.setNull(); -} +// virtual LLWearable::~LLWearable() { } @@ -118,6 +74,7 @@ LLAssetType::EType LLWearable::getAssetType() const return LLWearableType::getAssetType(mType); } +// virtual BOOL LLWearable::exportFile(LLFILE* file) const { // header and version @@ -178,16 +135,16 @@ BOOL LLWearable::exportFile(LLFILE* file) const } // texture entries - S32 num_textures = mTEMap.size(); + S32 num_textures = mTextureIDMap.size(); if( fprintf( file, "textures %d\n", num_textures ) < 0 ) { return FALSE; } - for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) + for (texture_id_map_t::const_iterator iter = mTextureIDMap.begin(); iter != mTextureIDMap.end(); ++iter) { S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); + const LLUUID& image_id = iter->second; if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 ) { return FALSE; @@ -197,40 +154,8 @@ BOOL LLWearable::exportFile(LLFILE* file) const } -void LLWearable::createVisualParams() -{ - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if (param->getWearableType() == mType) - { - addVisualParam(param->cloneParam(this)); - } - } - - // resync driver parameters to point to the newly cloned driven parameters - for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); - param_iter != mVisualParamIndexMap.end(); - ++param_iter) - { - LLVisualParam* param = param_iter->second; - LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; - // need this line to disambiguate between versions of LLCharacter::getVisualParam() - LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam; - param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) - { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) - { - llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; - continue; - } - } - } -} - -BOOL LLWearable::importFile( LLFILE* file ) +// virtual +LLWearable::EImportResult LLWearable::importFile( LLFILE* file ) { // *NOTE: changing the type or size of this buffer will require // changes in the fscanf() code below. You would be better off @@ -238,23 +163,14 @@ BOOL LLWearable::importFile( LLFILE* file ) char text_buffer[2048]; /* Flawfinder: ignore */ S32 fields_read = 0; - // suppress texlayerset updates while wearables are being imported. Layersets will be updated - // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. - LLOverrideBakedTextureUpdate stop_bakes(false); - // read header and version fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion ); if( fields_read != 1 ) { - // Shouldn't really log the asset id for security reasons, but - // we need it in this case. - llwarns << "Bad Wearable asset header: " << mAssetID << llendl; - //gVFS->dumpMap(); - return FALSE; + return LLWearable::BAD_HEADER; } - - // Temoprary hack to allow wearables with definition version 24 to still load. + // Temporary hack to allow wearables with definition version 24 to still load. // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 // the extra check for version == 24 can be removed before release, once internal testers // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that @@ -262,7 +178,7 @@ BOOL LLWearable::importFile( LLFILE* file ) if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) { llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; - return FALSE; + return LLWearable::FAILURE; } // name @@ -282,10 +198,9 @@ BOOL LLWearable::importFile( LLFILE* file ) if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ { llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; + return LLWearable::FAILURE; } mName = text_buffer; - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); } // description @@ -305,10 +220,9 @@ BOOL LLWearable::importFile( LLFILE* file ) if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ { llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; + return LLWearable::FAILURE; } mDescription = text_buffer; - LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); } // permissions @@ -317,11 +231,11 @@ BOOL LLWearable::importFile( LLFILE* file ) if( (fields_read != 1) || (perm_version != 0) ) { llwarns << "Bad Wearable asset: missing permissions" << llendl; - return FALSE; + return LLWearable::FAILURE; } if( !mPermissions.importFile( file ) ) { - return FALSE; + return LLWearable::FAILURE; } // sale info @@ -330,7 +244,7 @@ BOOL LLWearable::importFile( LLFILE* file ) if( (fields_read != 1) || (sale_info_version != 0) ) { llwarns << "Bad Wearable asset: missing sale_info" << llendl; - return FALSE; + return LLWearable::FAILURE; } // Sale info used to contain next owner perm. It is now in the // permissions. Thus, we read that out, and fix legacy @@ -340,7 +254,7 @@ BOOL LLWearable::importFile( LLFILE* file ) U32 perm_mask = 0; if( !mSaleInfo.importFile(file, has_perm_mask, perm_mask) ) { - return FALSE; + return LLWearable::FAILURE; } if(has_perm_mask) { @@ -358,7 +272,7 @@ BOOL LLWearable::importFile( LLFILE* file ) if( fields_read != 1 ) { llwarns << "Bad Wearable asset: bad type" << llendl; - return FALSE; + return LLWearable::FAILURE; } if( 0 <= type && type < LLWearableType::WT_COUNT ) { @@ -368,7 +282,7 @@ BOOL LLWearable::importFile( LLFILE* file ) { mType = LLWearableType::WT_COUNT; llwarns << "Bad Wearable asset: bad type #" << type << llendl; - return FALSE; + return LLWearable::FAILURE; } // parameters header @@ -377,7 +291,7 @@ BOOL LLWearable::importFile( LLFILE* file ) if( fields_read != 1 ) { llwarns << "Bad Wearable asset: missing parameters block" << llendl; - return FALSE; + return LLWearable::FAILURE; } if( num_parameters != mVisualParamIndexMap.size() ) @@ -395,7 +309,7 @@ BOOL LLWearable::importFile( LLFILE* file ) if( fields_read != 2 ) { llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; - return FALSE; + return LLWearable::FAILURE; } mSavedVisualParamMap[param_id] = param_weight; } @@ -406,10 +320,11 @@ BOOL LLWearable::importFile( LLFILE* file ) if( fields_read != 1 ) { llwarns << "Bad Wearable asset: missing textures block" << llendl; - return FALSE; + return LLWearable::FAILURE; } // textures + mTextureIDMap.clear(); for( i = 0; i < num_textures; i++ ) { S32 te = 0; @@ -420,367 +335,21 @@ BOOL LLWearable::importFile( LLFILE* file ) if( fields_read != 2 ) { llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; - return FALSE; + return LLWearable::FAILURE; } if( !LLUUID::validate( text_buffer ) ) { llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl; - return FALSE; + return LLWearable::FAILURE; } LLUUID id = LLUUID(text_buffer); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id ); - if( mTEMap.find(te) != mTEMap.end() ) - { - delete mTEMap[te]; - } - if( mSavedTEMap.find(te) != mSavedTEMap.end() ) - { - delete mSavedTEMap[te]; - } - - if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) - { - image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(id, (LLVOAvatarDefines::ETextureIndex)te), NULL); - } - LLUUID textureid(text_buffer); - mTEMap[te] = new LLLocalTextureObject(image, textureid); - mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); - createLayers(te); - } - - // copy all saved param values to working params - revertValues(); - - return TRUE; -} - - -// Avatar parameter and texture definitions can change over time. -// This function returns true if parameters or textures have been added or removed -// since this wearable was created. -BOOL LLWearable::isOldVersion() const -{ - if (!isAgentAvatarValid()) return FALSE; - - if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion ) - { - llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; - llassert(0); - } - - if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion ) - { - return TRUE; - } - - S32 param_count = 0; - for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) && (param->isTweakable() ) ) - { - param_count++; - if( !is_in_map(mVisualParamIndexMap, param->getID() ) ) - { - return TRUE; - } - } - } - if( param_count != mVisualParamIndexMap.size() ) - { - return TRUE; - } - - - S32 te_count = 0; - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_count++; - if( !is_in_map(mTEMap, te ) ) - { - return TRUE; - } - } - } - if( te_count != mTEMap.size() ) - { - return TRUE; - } - - return FALSE; -} - -// Avatar parameter and texture definitions can change over time. -// * If parameters or textures have been REMOVED since the wearable was created, -// they're just ignored, so we consider the wearable clean even though isOldVersion() -// will return true. -// * If parameters or textures have been ADDED since the wearable was created, -// they are taken to have default values, so we consider the wearable clean -// only if those values are the same as the defaults. -BOOL LLWearable::isDirty() const -{ - if (!isAgentAvatarValid()) return FALSE; - - for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) - && (param->isTweakable() ) - && !param->getCrossWearable()) - { - F32 current_weight = getVisualParamWeight(param->getID()); - current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() ); - F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight()); - saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() ); - - U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); - U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); - if( a != b ) - { - return TRUE; - } - } - } - - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator current_iter = mTEMap.find(te); - if(current_iter != mTEMap.end()) - { - const LLUUID& current_image_id = current_iter->second->getID(); - te_map_t::const_iterator saved_iter = mSavedTEMap.find(te); - if(saved_iter != mSavedTEMap.end()) - { - const LLUUID& saved_image_id = saved_iter->second->getID(); - if (saved_image_id != current_image_id) - { - // saved vs current images are different, wearable is dirty - return TRUE; - } - } - else - { - // image found in current image list but not saved image list - return TRUE; - } - } - } - } - - return FALSE; -} - - -void LLWearable::setParamsToDefaults() -{ - if (!isAgentAvatarValid()) return; - - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) ) - { - setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE); - } - } -} - -void LLWearable::setTexturesToDefaults() -{ - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - LLUUID id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); - if( mTEMap.find(te) == mTEMap.end() ) - { - mTEMap[te] = new LLLocalTextureObject(image, id); - createLayers(te); - } - else - { - // Local Texture Object already created, just set image and UUID - LLLocalTextureObject *lto = mTEMap[te]; - lto->setID(id); - lto->setImage(image); - } - } - } -} - -// Updates the user's avatar's appearance -void LLWearable::writeToAvatar() -{ - if (!isAgentAvatarValid()) return; - - ESex old_sex = gAgentAvatarp->getSex(); - - // Pull params - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the - // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. - if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) - { - S32 param_id = param->getID(); - F32 weight = getVisualParamWeight(param_id); - - gAgentAvatarp->setVisualParamWeight( param_id, weight, FALSE ); - } - } - - // Pull texture entries - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = mTEMap.find(te); - LLUUID image_id; - if(iter != mTEMap.end()) - { - image_id = iter->second->getID(); - } - else - { - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); - // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. - gAgentAvatarp->setLocalTextureTE(te, image, 0); - } - } - - ESex new_sex = gAgentAvatarp->getSex(); - if( old_sex != new_sex ) - { - gAgentAvatarp->updateSexDependentLayerSets( FALSE ); - } - -// if( upload_bake ) -// { -// gAgent.sendAgentSetAppearance(); -// } -} - - -// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. -// static -void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ) -{ - if (!isAgentAvatarValid()) return; - - // You can't just remove body parts. - if( (type == LLWearableType::WT_SHAPE) || - (type == LLWearableType::WT_SKIN) || - (type == LLWearableType::WT_HAIR) || - (type == LLWearableType::WT_EYES) ) - { - return; - } - - // Pull params - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) - { - if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) ) - { - S32 param_id = param->getID(); - gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake ); - } - } - - if(gAgentCamera.cameraCustomizeAvatar()) - { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); - } - - gAgentAvatarp->updateVisualParams(); - gAgentAvatarp->wearableUpdated(type, FALSE); - -// if( upload_bake ) -// { -// gAgent.sendAgentSetAppearance(); -// } -} - -// Does not copy mAssetID. -// Definition version is current: removes obsolete enties and creates default values for new ones. -void LLWearable::copyDataFrom(const LLWearable* src) -{ - if (!isAgentAvatarValid()) return; - - mDefinitionVersion = LLWearable::sCurrentDefinitionVersion; - - mName = src->mName; - mDescription = src->mDescription; - mPermissions = src->mPermissions; - mSaleInfo = src->mSaleInfo; - - setType(src->mType); - - mSavedVisualParamMap.clear(); - // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) - { - if( (param->getWearableType() == mType) ) - { - S32 id = param->getID(); - F32 weight = src->getVisualParamWeight(id); - mSavedVisualParamMap[id] = weight; - } - } - - destroyTextures(); - // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - for (S32 te = 0; te < TEX_NUM_INDICES; te++) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = src->mTEMap.find(te); - LLUUID image_id; - LLViewerFetchedTexture *image = NULL; - if(iter != src->mTEMap.end()) - { - image = src->getLocalTextureObject(te)->getImage(); - image_id = src->getLocalTextureObject(te)->getID(); - mTEMap[te] = new LLLocalTextureObject(image, image_id); - mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); - mTEMap[te]->setBakedReady(src->getLocalTextureObject(te)->getBakedReady()); - mTEMap[te]->setDiscard(src->getLocalTextureObject(te)->getDiscard()); - } - else - { - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - image = LLViewerTextureManager::getFetchedTexture( image_id ); - mTEMap[te] = new LLLocalTextureObject(image, image_id); - mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); - } - createLayers(te); - } + mTextureIDMap[te] = id; } - // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable - // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) - revertValues(); + return LLWearable::SUCCESS; } -void LLWearable::setItemID(const LLUUID& item_id) -{ - mItemID = item_id; -} - -const LLUUID& LLWearable::getItemID() const -{ - return mItemID; -} void LLWearable::setType(LLWearableType::EType type) { @@ -788,51 +357,6 @@ void LLWearable::setType(LLWearableType::EType type) createVisualParams(); } -LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) -{ - te_map_t::iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const -{ - te_map_t::const_iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - const LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -std::vector LLWearable::getLocalTextureListSeq() -{ - std::vector result; - - for(te_map_t::const_iterator iter = mTEMap.begin(); - iter != mTEMap.end(); iter++) - { - LLLocalTextureObject* lto = iter->second; - result.push_back(lto); - } - - return result; -} - -void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) -{ - if( mTEMap.find(index) != mTEMap.end() ) - { - mTEMap.erase(index); - } - mTEMap[index] = new LLLocalTextureObject(lto); -} - void LLWearable::addVisualParam(LLVisualParam *param) { @@ -845,17 +369,6 @@ void LLWearable::addVisualParam(LLVisualParam *param) mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); } -void LLWearable::setVisualParams() -{ - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - gAgentAvatarp->setVisualParamWeight(id, value, FALSE); - } -} - void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) { @@ -918,7 +431,7 @@ LLColor4 LLWearable::getClothesColor(S32 te) const { LLColor4 color; U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + if( LLAvatarAppearance::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) { for( U8 index = 0; index < 3; index++ ) { @@ -931,7 +444,7 @@ LLColor4 LLWearable::getClothesColor(S32 te) const void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) { U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + if( LLAvatarAppearance::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) { for( U8 index = 0; index < 3; index++ ) { @@ -940,312 +453,6 @@ void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload } } -void LLWearable::revertValues() -{ - //update saved settings so wearable is no longer dirty - // non-driver params first - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && !dynamic_cast(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - //then driver params - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && dynamic_cast(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - // make sure that saved values are sane - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *param = getVisualParam(id); - if( param ) - { - mSavedVisualParamMap[id] = param->getWeight(); - } - } - - syncImages(mSavedTEMap, mTEMap); - - - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel ) - { - panel->updateScrollingPanelList(); - } -} - -BOOL LLWearable::isOnTop() const -{ - return (this == gAgentWearables.getTopWearable(mType)); -} - -void LLWearable::createLayers(S32 te) -{ - LLTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); - if (layer_set) - { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); - } - else - { - llerrs << "could not find layerset for LTO in wearable!" << llendl; - } -} - -void LLWearable::saveValues() -{ - //update saved settings so wearable is no longer dirty - mSavedVisualParamMap.clear(); - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - mSavedVisualParamMap[id] = value; - } - - // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - syncImages(mTEMap, mSavedTEMap); - - - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if( panel ) - { - panel->updateScrollingPanelList(); - } -} - -void LLWearable::syncImages(te_map_t &src, te_map_t &dst) -{ - // Deep copy of src (copies only those tes that are current, filling in defaults where needed) - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = src.find(te); - LLUUID image_id; - LLViewerFetchedTexture *image = NULL; - LLLocalTextureObject *lto = NULL; - if(iter != src.end()) - { - // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. - lto = iter->second; - image = lto->getImage(); - image_id = lto->getID(); - } - else - { - // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. - image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); - image = LLViewerTextureManager::getFetchedTexture( image_id ); - } - - if( dst.find(te) != dst.end() ) - { - // there's already an entry in the destination map for the texture. Just update its values. - dst[te]->setImage(image); - dst[te]->setID(image_id); - } - else - { - // no entry found in the destination map, we need to create a new Local Texture Object - dst[te] = new LLLocalTextureObject(image, image_id); - } - - if( lto ) - { - // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. - dst[te]->setBakedReady(lto->getBakedReady()); - dst[te]->setDiscard(lto->getDiscard()); - } - } - } -} - -void LLWearable::destroyTextures() -{ - for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mTEMap.clear(); - for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mSavedTEMap.clear(); -} - -void LLWearable::pullCrossWearableValues() -{ - // scan through all of the avatar's visual parameters - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if( param ) - { - LLDriverParam *driver_param = dynamic_cast(param); - if(driver_param) - { - // parameter is a driver parameter, have it update its - driver_param->updateCrossDrivenParams(getType()); - } - } - } -} - - -void LLWearable::setLabelUpdated() const -{ - gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); -} - -void LLWearable::refreshName() -{ - LLUUID item_id = getItemID(); - LLInventoryItem* item = gInventory.getItem(item_id); - if( item ) - { - mName = item->getName(); - } -} - -struct LLWearableSaveData -{ - LLWearableType::EType mType; -}; - -void LLWearable::saveNewAsset() const -{ -// llinfos << "LLWearable::saveNewAsset() type: " << getTypeName() << llendl; - //llinfos << *this << llendl; - - const std::string filename = asset_id_to_filename(mAssetID); - LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ - BOOL successful_save = FALSE; - if(fp && exportFile(fp)) - { - successful_save = TRUE; - } - if(fp) - { - fclose(fp); - fp = NULL; - } - if(!successful_save) - { - std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str()); - llwarns << buffer << llendl; - - LLSD args; - args["NAME"] = mName; - LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args); - return; - } - - // save it out to database - if( gAssetStorage ) - { - /* - std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); - if (!url.empty()) - { - llinfos << "Update Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); - body["asset_type"] = LLAssetType::lookup(getAssetType()); - body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); - body["name"] = getName(); - body["description"] = getDescription(); - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); - } - else - { - } - */ - LLWearableSaveData* data = new LLWearableSaveData; - data->mType = mType; - gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), - &LLWearable::onSaveNewAssetComplete, - (void*)data); - } -} - -// static -void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLWearableSaveData* data = (LLWearableSaveData*)userdata; - const std::string& type_name = LLWearableType::getTypeName(data->mType); - if(0 == status) - { - // Success - llinfos << "Saved wearable " << type_name << llendl; - } - else - { - std::string buffer = llformat("Unable to save %s to central asset store.", type_name.c_str()); - llwarns << buffer << " Status: " << status << llendl; - LLSD args; - args["NAME"] = type_name; - LLNotificationsUtil::add("CannotSaveToAssetStore", args); - } - - // Delete temp file - const std::string src_filename = asset_id_to_filename(new_asset_id); - LLFile::remove(src_filename); - - // delete the context data - delete data; - -} - -std::ostream& operator<<(std::ostream &s, const LLWearable &w) -{ - s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; - s << " Name: " << w.mName << "\n"; - s << " Desc: " << w.mDescription << "\n"; - //w.mPermissions - //w.mSaleInfo - - s << " Params:" << "\n"; - for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); - iter != w.mVisualParamIndexMap.end(); ++iter) - { - S32 param_id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 param_weight = wearable_param->getWeight(); - s << " " << param_id << " " << param_weight << "\n"; - } - - s << " Textures:" << "\n"; - for (LLWearable::te_map_t::const_iterator iter = w.mTEMap.begin(); - iter != w.mTEMap.end(); ++iter) - { - S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); - s << " " << te << " " << image_id << "\n"; - } - return s; -} - - std::string terse_F32_to_string(F32 f) { std::string r = llformat("%.2f", f); @@ -1276,10 +483,3 @@ std::string terse_F32_to_string(F32 f) return r; } -std::string asset_id_to_filename(const LLUUID &asset_id) -{ - std::string asset_id_string; - asset_id.toString(asset_id_string); - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl"; - return filename; -} diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index c8f9ef1fb9..56c931e43b 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -27,31 +27,25 @@ #ifndef LL_LLWEARABLE_H #define LL_LLWEARABLE_H +#include "llextendedstatus.h" //#include "lluuid.h" //#include "llstring.h" -//#include "llpermissions.h" -//#include "llsaleinfo.h" +#include "llpermissions.h" +#include "llsaleinfo.h" //#include "llassetstorage.h" -//#include "llwearabletype.h" +#include "llwearabletype.h" //#include "llfile.h" -//#include "lllocaltextureobject.h" +#include "lllocaltextureobject.h" -class LLViewerInventoryItem; class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; class LLWearable { - friend class LLWearableList; - //-------------------------------------------------------------------- // Constructors and destructors //-------------------------------------------------------------------- -private: - // Private constructors used by LLWearableList - LLWearable(const LLTransactionID& transactionID); - LLWearable(const LLAssetID& assetID); public: virtual ~LLWearable(); @@ -59,10 +53,7 @@ public: // Accessors //-------------------------------------------------------------------- public: - const LLUUID& getItemID() const; - const LLAssetID& getAssetID() const { return mAssetID; } - const LLTransactionID& getTransactionID() const { return mTransactionID; } - LLWearableType::EType getType() const { return mType; } + LLWearableType::EType getType() const { return mType; } void setType(LLWearableType::EType type); const std::string& getName() const { return mName; } void setName(const std::string& name) { mName = name; } @@ -81,36 +72,22 @@ public: public: typedef std::vector visual_param_vec_t; - BOOL isDirty() const; - BOOL isOldVersion() const; - - void writeToAvatar(); - void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); } - static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); - - BOOL exportFile(LLFILE* file) const; - BOOL importFile(LLFILE* file); - - void setParamsToDefaults(); - void setTexturesToDefaults(); + enum EImportResult + { + FAILURE = 0, + SUCCESS, + BAD_HEADER + }; + virtual BOOL exportFile(LLFILE* file) const; + virtual EImportResult importFile(LLFILE* file); - void saveNewAsset() const; - static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); + virtual LLLocalTextureObject* getLocalTextureObject(S32 index) = 0; + virtual void writeToAvatar() = 0; - void copyDataFrom(const LLWearable* src); static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } - friend std::ostream& operator<<(std::ostream &s, const LLWearable &w); - void setItemID(const LLUUID& item_id); - - LLLocalTextureObject* getLocalTextureObject(S32 index); - const LLLocalTextureObject* getLocalTextureObject(S32 index) const; - std::vector getLocalTextureListSeq(); - - void setLocalTextureObject(S32 index, LLLocalTextureObject <o); void addVisualParam(LLVisualParam *param); - void setVisualParams(); void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); F32 getVisualParamWeight(S32 index) const; LLVisualParam* getVisualParam(S32 index) const; @@ -120,27 +97,11 @@ public: LLColor4 getClothesColor(S32 te) const; void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); - void revertValues(); - void saveValues(); - void pullCrossWearableValues(); - - BOOL isOnTop() const; + typedef std::map texture_id_map_t; + const texture_id_map_t& getTextureIDMap() const { return mTextureIDMap; } - // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). - void setLabelUpdated() const; - - // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, - // not the wearable asset itself. - void refreshName(); - -private: - typedef std::map te_map_t; - typedef std::map visual_param_index_map_t; - - void createLayers(S32 te); - void createVisualParams(); - void syncImages(te_map_t &src, te_map_t &dst); - void destroyTextures(); +protected: + virtual void createVisualParams() = 0; static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. @@ -148,18 +109,16 @@ private: std::string mDescription; LLPermissions mPermissions; LLSaleInfo mSaleInfo; - LLAssetID mAssetID; - LLTransactionID mTransactionID; LLWearableType::EType mType; typedef std::map param_map_t; param_map_t mSavedVisualParamMap; // last saved version of visual params + typedef std::map visual_param_index_map_t; visual_param_index_map_t mVisualParamIndexMap; - te_map_t mTEMap; // maps TE to LocalTextureObject - te_map_t mSavedTEMap; // last saved version of TEMap - LLUUID mItemID; // ID of the inventory item in the agent's inventory + // *TODO: Lazy mutable. Find a better way? + mutable texture_id_map_t mTextureIDMap; }; #endif // LL_LLWEARABLE_H diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp new file mode 100644 index 0000000000..d47702ff4d --- /dev/null +++ b/indra/llappearance/llwearabletype.cpp @@ -0,0 +1,162 @@ +/** + * @file llwearabletype.cpp + * @brief LLWearableType class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "llwearabletype.h" +//#include "llinventoryfunctions.h" +#include "llinventoryicon.h" +#include "lltrans.h" + +struct WearableEntry : public LLDictionaryEntry +{ + WearableEntry(const std::string &name, + const std::string& default_new_name, + LLAssetType::EType assetType, + LLInventoryIcon::EIconName iconName, + BOOL disable_camera_switch = FALSE, + BOOL allow_multiwear = TRUE) : + LLDictionaryEntry(name), + mAssetType(assetType), + mDefaultNewName(default_new_name), + mLabel(LLTrans::getString(name)), + mIconName(iconName), + mDisableCameraSwitch(disable_camera_switch), + mAllowMultiwear(allow_multiwear) + { + + } + const LLAssetType::EType mAssetType; + const std::string mLabel; + const std::string mDefaultNewName; //keep mLabel for backward compatibility + LLInventoryIcon::EIconName mIconName; + BOOL mDisableCameraSwitch; + BOOL mAllowMultiwear; +}; + +class LLWearableDictionary : public LLSingleton, + public LLDictionary +{ +public: + LLWearableDictionary(); +}; + +LLWearableDictionary::LLWearableDictionary() +{ + addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); + addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); + + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); + + addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); +} + +// static +LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const LLWearableType::EType wearable = dict->lookup(type_name); + return wearable; +} + +// static +const std::string& LLWearableType::getTypeName(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return getTypeName(WT_INVALID); + return entry->mName; +} + +//static +const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return getTypeDefaultNewName(WT_INVALID); + return entry->mDefaultNewName; +} + +// static +const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return getTypeLabel(WT_INVALID); + return entry->mLabel; +} + +// static +LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return getAssetType(WT_INVALID); + return entry->mAssetType; +} + +// static +LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return getIconName(WT_INVALID); + return entry->mIconName; +} + +// static +BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return FALSE; + return entry->mDisableCameraSwitch; +} + +// static +BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) +{ + const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); + const WearableEntry *entry = dict->lookup(type); + if (!entry) return FALSE; + return entry->mAllowMultiwear; +} + diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h new file mode 100644 index 0000000000..d633b4807e --- /dev/null +++ b/indra/llappearance/llwearabletype.h @@ -0,0 +1,76 @@ +/** + * @file llwearabletype.h + * @brief LLWearableType class header file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWEARABLETYPE_H +#define LL_LLWEARABLETYPE_H + +#include "llassettype.h" +#include "lldictionary.h" +#include "llinventoryicon.h" +#include "llsingleton.h" + +class LLWearableType +{ +public: + enum EType + { + WT_SHAPE = 0, + WT_SKIN = 1, + WT_HAIR = 2, + WT_EYES = 3, + WT_SHIRT = 4, + WT_PANTS = 5, + WT_SHOES = 6, + WT_SOCKS = 7, + WT_JACKET = 8, + WT_GLOVES = 9, + WT_UNDERSHIRT = 10, + WT_UNDERPANTS = 11, + WT_SKIRT = 12, + WT_ALPHA = 13, + WT_TATTOO = 14, + WT_PHYSICS = 15, + WT_COUNT = 16, + + WT_INVALID = 255, + WT_NONE = -1, + }; + + static const std::string& getTypeName(EType type); + static const std::string& getTypeDefaultNewName(EType type); + static const std::string& getTypeLabel(EType type); + static LLAssetType::EType getAssetType(EType type); + static EType typeNameToType(const std::string& type_name); + static LLInventoryIcon::EIconName getIconName(EType type); + static BOOL getDisableCameraSwitch(EType type); + static BOOL getAllowMultiwear(EType type); + +protected: + LLWearableType() {} + ~LLWearableType() {} +}; + +#endif // LL_LLWEARABLETYPE_H diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index a1712699eb..e9704d5635 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories( ${LLMESSAGE_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} + ${LLAPPEARANCE_INCLUDE_DIRS} ) set(llcharacter_SOURCE_FILES diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 5c68cb46eb..cf21101e35 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -159,6 +159,8 @@ public: extern LLGLSLShader gUIProgram; //output vec4(color.rgb,color.a*tex0[tc0].a) extern LLGLSLShader gSolidColorProgram; +//Alpha mask shader (declared here so llappearance can access properly) +extern LLGLSLShader gAlphaMaskProgram; #endif diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 569a65c2e0..a23aa72520 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -32,10 +32,12 @@ #ifndef LL_TEXTURE_H #define LL_TEXTURE_H +#include "llgltypes.h" #include "llrefcount.h" -class LLImageGL ; -class LLTexUnit ; +#include "llrender.h" + class LLFontGL ; +class LLImageRaw ; // //this is an abstract class as the parent for the class LLViewerTexture @@ -52,6 +54,39 @@ protected: public: LLTexture(){} + enum EBoostLevel + { + BOOST_NONE = 0, + BOOST_AVATAR_BAKED , + BOOST_AVATAR , + BOOST_CLOUDS , + BOOST_SCULPTED , + + BOOST_HIGH = 10, + BOOST_BUMP , + BOOST_TERRAIN , // has to be high priority for minimap / low detail + BOOST_SELECTED , + BOOST_AVATAR_BAKED_SELF , + BOOST_AVATAR_SELF , // needed for baking avatar + BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. + BOOST_HUD , + BOOST_ICON , + BOOST_UI , + BOOST_PREVIEW , + BOOST_MAP , + BOOST_MAP_VISIBLE , + BOOST_MAX_LEVEL, + + //other texture Categories + LOCAL = BOOST_MAX_LEVEL, + AVATAR_SCRATCH_TEX, + DYNAMIC_TEX, + MEDIA, + ATLAS, + OTHER, + MAX_GL_IMAGE_CATEGORY + }; + // //interfaces to access LLViewerTexture // @@ -62,6 +97,13 @@ public: virtual void setActive() = 0 ; virtual S32 getWidth(S32 discard_level = -1) const = 0 ; virtual S32 getHeight(S32 discard_level = -1) const = 0 ; + virtual BOOL hasGLTexture() const = 0; + virtual BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLTexture::OTHER) = 0; + virtual void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE) = 0; + virtual void setAddressMode(LLTexUnit::eTextureAddressMode mode) = 0; + virtual LLTexUnit::eTextureAddressMode getAddressMode(void) const = 0; + virtual S8 getComponents() const = 0; + virtual const LLUUID& getID() const = 0; private: //note: do not make this function public. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ff3fb0038c..a40f7cd3d3 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -302,7 +302,6 @@ set(viewer_SOURCE_FILES llinventorybridge.cpp llinventoryfilter.cpp llinventoryfunctions.cpp - llinventoryicon.cpp llinventoryitemslist.cpp llinventorylistitem.cpp llinventorymodel.cpp @@ -316,7 +315,6 @@ set(viewer_SOURCE_FILES lllistcontextmenu.cpp lllistview.cpp lllocalbitmaps.cpp - lllocaltextureobject.cpp lllocationhistory.cpp lllocationinputctrl.cpp lllogchat.cpp @@ -495,9 +493,6 @@ set(viewer_SOURCE_FILES llsyswellwindow.cpp llteleporthistory.cpp llteleporthistorystorage.cpp - lltexglobalcolor.cpp - lltexlayer.cpp - lltexlayerparams.cpp lltextureatlas.cpp lltextureatlasmanager.cpp lltexturecache.cpp @@ -595,18 +590,18 @@ set(viewer_SOURCE_FILES llviewershadermgr.cpp llviewerstats.cpp llviewerstatsrecorder.cpp + llviewertexlayer.cpp llviewertexteditor.cpp llviewertexture.cpp llviewertextureanim.cpp llviewertexturelist.cpp llviewerthrottle.cpp - llviewervisualparam.cpp + llviewerwearable.cpp llviewerwindow.cpp llviewerwindowlistener.cpp llvlcomposition.cpp llvlmanager.cpp llvoavatar.cpp - llvoavatardefines.cpp llvoavatarself.cpp llvocache.cpp llvograss.cpp @@ -629,7 +624,6 @@ set(viewer_SOURCE_FILES llwaterparamset.cpp llwearableitemslist.cpp llwearablelist.cpp - llwearabletype.cpp llweb.cpp llwebprofile.cpp llwebsharing.cpp @@ -877,7 +871,6 @@ set(viewer_HEADER_FILES llinventorybridge.h llinventoryfilter.h llinventoryfunctions.h - llinventoryicon.h llinventoryitemslist.h llinventorylistitem.h llinventorymodel.h @@ -892,7 +885,6 @@ set(viewer_HEADER_FILES lllistcontextmenu.h lllistview.h lllocalbitmaps.h - lllocaltextureobject.h lllocationhistory.h lllocationinputctrl.h lllogchat.h @@ -1062,9 +1054,6 @@ set(viewer_HEADER_FILES lltable.h llteleporthistory.h llteleporthistorystorage.h - lltexglobalcolor.h - lltexlayer.h - lltexlayerparams.h lltextureatlas.h lltextureatlasmanager.h lltexturecache.h @@ -1163,18 +1152,18 @@ set(viewer_HEADER_FILES llviewershadermgr.h llviewerstats.h llviewerstatsrecorder.h + llviewertexlayer.h llviewertexteditor.h llviewertexture.h llviewertextureanim.h llviewertexturelist.h llviewerthrottle.h - llviewervisualparam.h + llviewerwearable.h llviewerwindow.h llviewerwindowlistener.h llvlcomposition.h llvlmanager.h llvoavatar.h - llvoavatardefines.h llvoavatarself.h llvocache.h llvograss.h @@ -1197,7 +1186,6 @@ set(viewer_HEADER_FILES llwaterparamset.h llwearableitemslist.h llwearablelist.h - llwearabletype.h llweb.h llwebprofile.h llwebsharing.h @@ -1834,6 +1822,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${TCMALLOC_LIBRARIES} + ${LLAPPEARANCE_LIBRARIES} ) if (USE_KDU) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e44b27c6af..e4f02b9f0b 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -47,7 +47,7 @@ #include "lltooldraganddrop.h" #include "llviewerregion.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llwearablelist.h" #include @@ -82,7 +82,7 @@ class LLWearAndEditCallback : public LLInventoryCallback // wearable type stored in asset is some other value. // Calling this function whenever a wearable is added to increase visibility if this problem // turns up in other inventories. -void checkWearableAgainstInventory(LLWearable *wearable) +void checkWearableAgainstInventory(LLViewerWearable *wearable) { if (wearable->getItemID().isNull()) return; @@ -119,7 +119,7 @@ void LLAgentWearables::dump() llinfos << "Type: " << i << " count " << count << llendl; for (U32 j=0; j cb, LLWearableType::EType type, U32 index, LLWearable* wearable, U32 todo) : + LLPointer cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo) : mType(type), mIndex(index), mWearable(wearable), @@ -265,7 +265,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::EType type, const U32 index, const LLUUID& item_id, - LLWearable* wearable) + LLViewerWearable* wearable) { llinfos << "type " << type << " index " << index << " item " << item_id.asString() << llendl; @@ -312,7 +312,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() { for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index) { - LLWearable* wearable = getWearable((LLWearableType::EType)type,index); + LLViewerWearable* wearable = getWearable((LLWearableType::EType)type,index); if (wearable) { if (wearable->getItemID().isNull()) @@ -354,7 +354,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() U8 type_u8 = (U8)type; gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8); - LLWearable* wearable = getWearable((LLWearableType::EType)type, 0); + LLViewerWearable* wearable = getWearable((LLWearableType::EType)type, 0); if (wearable) { //llinfos << "Sending wearable " << wearable->getName() << llendl; @@ -382,14 +382,14 @@ void LLAgentWearables::sendAgentWearablesUpdate() void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update, const std::string new_name) { - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getWearable(type, index); if(!old_wearable) return; bool name_changed = !new_name.empty() && (new_name != old_wearable->getName()); if (name_changed || old_wearable->isDirty() || old_wearable->isOldVersion()) { LLUUID old_item_id = old_wearable->getItemID(); - LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); - new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()? + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); + new_wearable->setItemID(old_item_id); // should this be in LLViewerWearable::copyDataFrom()? setWearable(type,index,new_wearable); // old_wearable may still be referred to by other inventory items. Revert @@ -465,7 +465,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; return; } - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getWearable(type, index); if (!old_wearable) { llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; @@ -480,7 +480,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, } std::string trunc_name(new_name); LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN); - LLWearable* new_wearable = LLWearableList::instance().createCopy( + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy( old_wearable, trunc_name); LLPointer cb = @@ -518,7 +518,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) { - LLWearable* wearable = getWearable(type, index); + LLViewerWearable* wearable = getWearable(type, index); llassert(wearable); if (wearable) { @@ -553,13 +553,13 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& LLUUID curr_item_id = getWearableItemID((LLWearableType::EType)i,j); if (curr_item_id == item_id) { - LLWearable* old_wearable = getWearable((LLWearableType::EType)i,j); + LLViewerWearable* old_wearable = getWearable((LLWearableType::EType)i,j); llassert(old_wearable); if (!old_wearable) continue; std::string old_name = old_wearable->getName(); old_wearable->setName(new_name); - LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); + LLViewerWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable); new_wearable->setItemID(item_id); LLInventoryItem* item = gInventory.getItem(item_id); if (item) @@ -640,14 +640,14 @@ LLInventoryItem* LLAgentWearables::getWearableInventoryItem(LLWearableType::ETyp return item; } -const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const +const LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - const LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + const LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -657,14 +657,14 @@ const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) return NULL; } -LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) +LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) { const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id); for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -674,13 +674,13 @@ LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) return NULL; } -LLWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_id) +LLViewerWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_id) { for (S32 i=0; i < LLWearableType::WT_COUNT; i++) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getAssetID() == asset_id)) { return curr_wearable; @@ -705,7 +705,7 @@ BOOL LLAgentWearables::selfHasWearable(LLWearableType::EType type) return (gAgentWearables.getWearableCount(type) > 0); } -LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) +LLViewerWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) { wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) @@ -723,10 +723,10 @@ LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 } } -void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) +void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index, LLViewerWearable *wearable) { - LLWearable *old_wearable = getWearable(type,index); + LLViewerWearable *old_wearable = getWearable(type,index); if (!old_wearable) { pushWearable(type,wearable); @@ -753,7 +753,7 @@ void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index, } } -U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLWearable *wearable) +U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLViewerWearable *wearable) { if (wearable == NULL) { @@ -771,7 +771,7 @@ U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLWearable return MAX_CLOTHING_PER_TYPE; } -void LLAgentWearables::wearableUpdated(LLWearable *wearable) +void LLAgentWearables::wearableUpdated(LLViewerWearable *wearable) { gAgentAvatarp->wearableUpdated(wearable->getType(), FALSE); wearable->refreshName(); @@ -794,7 +794,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable) } -void LLAgentWearables::popWearable(LLWearable *wearable) +void LLAgentWearables::popWearable(LLViewerWearable *wearable) { if (wearable == NULL) { @@ -813,7 +813,7 @@ void LLAgentWearables::popWearable(LLWearable *wearable) void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) { - LLWearable *wearable = getWearable(type, index); + LLViewerWearable *wearable = getWearable(type, index); if (wearable) { mWearableDatas[type].erase(mWearableDatas[type].begin() + index); @@ -825,7 +825,7 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) } } -U32 LLAgentWearables::getWearableIndex(const LLWearable *wearable) const +U32 LLAgentWearables::getWearableIndex(const LLViewerWearable *wearable) const { if (wearable == NULL) { @@ -851,7 +851,7 @@ U32 LLAgentWearables::getWearableIndex(const LLWearable *wearable) const return MAX_CLOTHING_PER_TYPE; } -const LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) const +const LLViewerWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) const { wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); if (wearable_iter == mWearableDatas.end()) @@ -869,7 +869,7 @@ const LLWearable* LLAgentWearables::getWearable(const LLWearableType::EType type } } -LLWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type) +LLViewerWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type) { U32 count = getWearableCount(type); if ( count == 0) @@ -880,7 +880,7 @@ LLWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type) return getWearable(type, count-1); } -LLWearable* LLAgentWearables::getBottomWearable(const LLWearableType::EType type) +LLViewerWearable* LLAgentWearables::getBottomWearable(const LLWearableType::EType type) { if (getWearableCount(type) == 0) { @@ -920,7 +920,7 @@ U32 LLAgentWearables::itemUpdatePendingCount() const const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const { - const LLWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getWearable(type,index); if (wearable) return wearable->getItemID(); else @@ -929,7 +929,7 @@ const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 const LLUUID LLAgentWearables::getWearableAssetID(LLWearableType::EType type, U32 index) const { - const LLWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getWearable(type,index); if (wearable) return wearable->getAssetID(); else @@ -1012,7 +1012,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i); if (asset_id.isNull()) { - LLWearable::removeFromAvatar(type, FALSE); + LLViewerWearable::removeFromAvatar(type, FALSE); } else { @@ -1058,7 +1058,7 @@ void LLAgentWearables::recoverMissingWearable(const LLWearableType::EType type, // Try to recover by replacing missing wearable with a new one. LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; - LLWearable* new_wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* new_wearable = LLWearableList::instance().createNewWearable(type); setWearable(type,index,new_wearable); //new_wearable->writeToAvatar(TRUE); @@ -1095,7 +1095,7 @@ void LLAgentWearables::recoverMissingWearableDone() void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index) { - LLWearable* wearable = getWearable((LLWearableType::EType)wearable_type, wearable_index); + LLViewerWearable* wearable = getWearable((LLWearableType::EType)wearable_type, wearable_index); if (!wearable) { llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl; @@ -1128,7 +1128,7 @@ public: mItemsToLink, link_waiter); } - void addPendingWearable(LLWearable *wearable) + void addPendingWearable(LLViewerWearable *wearable) { if (!wearable) { @@ -1163,7 +1163,7 @@ public: LLWearableType::EType type = item->getWearableType(); if (type < LLWearableType::WT_COUNT) { - LLWearable *wearable = mWearablesAwaitingItems[type]; + LLViewerWearable *wearable = mWearablesAwaitingItems[type]; if (wearable) wearable->setItemID(inv_item); } @@ -1176,7 +1176,7 @@ public: private: LLInventoryModel::item_array_t mItemsToLink; - std::vector mWearablesAwaitingItems; + std::vector mWearablesAwaitingItems; }; void LLAgentWearables::createStandardWearables() @@ -1208,7 +1208,7 @@ void LLAgentWearables::createStandardWearables() if (create[i]) { llassert(getWearableCount((LLWearableType::EType)i) == 0); - LLWearable* wearable = LLWearableList::instance().createNewWearable((LLWearableType::EType)i); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable((LLWearableType::EType)i); ((OnWearableItemCreatedCB*)(&(*cb)))->addPendingWearable(wearable); // no need to update here... LLUUID category_id = LLUUID::null; @@ -1267,7 +1267,7 @@ void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index) void LLAgentWearables::addWearableToAgentInventory(LLPointer cb, - LLWearable* wearable, + LLViewerWearable* wearable, const LLUUID& category_id, BOOL notify) { @@ -1305,7 +1305,7 @@ void LLAgentWearables::removeWearable(const LLWearableType::EType type, bool do_ } else { - LLWearable* old_wearable = getWearable(type,index); + LLViewerWearable* old_wearable = getWearable(type,index); if (old_wearable) { @@ -1363,7 +1363,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo S32 max_entry = mWearableDatas[type].size()-1; for (S32 i=max_entry; i>=0; i--) { - LLWearable* old_wearable = getWearable(type,i); + LLViewerWearable* old_wearable = getWearable(type,i); //queryWearableCache(); // moved below if (old_wearable) { @@ -1375,7 +1375,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo } else { - LLWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getWearable(type, index); //queryWearableCache(); // moved below if (old_wearable) @@ -1394,7 +1394,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo // Assumes existing wearables are not dirty. void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items, - const LLDynamicArray< LLWearable* >& wearables, + const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove) { llinfos << "setWearableOutfit() start" << llendl; @@ -1419,7 +1419,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it S32 i; for (i = 0; i < count; i++) { - LLWearable* new_wearable = wearables[i]; + LLViewerWearable* new_wearable = wearables[i]; LLPointer new_item = items[i]; llassert(new_wearable); @@ -1476,7 +1476,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // User has picked "wear on avatar" from a menu. -void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) +void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) { //LLAgentDumper dumper("setWearableItem"); if (isWearingItem(new_item->getUUID())) @@ -1491,7 +1491,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* ne { // Remove old wearable, if any // MULTI_WEARABLE: hardwired to 0 - LLWearable* old_wearable = getWearable(type,0); + LLViewerWearable* old_wearable = getWearable(type,0); if (old_wearable) { const LLUUID& old_item_id = old_wearable->getItemID(); @@ -1517,7 +1517,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* ne } // static -bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable) +bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); @@ -1553,7 +1553,7 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& // Called from setWearableItem() and onSetWearableDialog() to actually set the wearable. // MULTI_WEARABLE: unify code after null objects are gone. -void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append) +void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append) { const LLWearableType::EType type = new_wearable->getType(); @@ -1570,7 +1570,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n // Replace the old wearable with a new one. llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); - LLWearable *old_wearable = getWearable(type,0); + LLViewerWearable *old_wearable = getWearable(type,0); LLUUID old_item_id; if (old_wearable) { @@ -1666,7 +1666,7 @@ LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextur const U32 num_wearables = getWearableCount(baked_type); for (U32 index = 0; index < num_wearables; ++index) { - const LLWearable* wearable = getWearable(baked_type,index); + const LLViewerWearable* wearable = getWearable(baked_type,index); if (wearable) { LLUUID asset_id = wearable->getAssetID(); @@ -1902,11 +1902,11 @@ void LLAgentWearables::checkWearablesLoaded() const // (depending on closer_to_body parameter). bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) { - const LLWearable* wearable = getWearableFromItemID(item_id); + const LLViewerWearable* wearable = getWearableFromItemID(item_id); if (!wearable) return false; LLWearableType::EType wtype = wearable->getType(); - const LLWearable* marginal_wearable = closer_to_body ? getBottomWearable(wtype) : getTopWearable(wtype); + const LLViewerWearable* marginal_wearable = closer_to_body ? getBottomWearable(wtype) : getTopWearable(wtype); if (!marginal_wearable) return false; return wearable != marginal_wearable; @@ -1928,7 +1928,7 @@ void LLAgentWearables::updateWearablesLoaded() } } -bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const +bool LLAgentWearables::canWearableBeRemoved(const LLViewerWearable* wearable) const { if (!wearable) return false; @@ -1943,7 +1943,7 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake) { for (S32 count = 0; count < (S32)getWearableCount((LLWearableType::EType)type); ++count) { - LLWearable *wearable = getWearable((LLWearableType::EType)type,count); + LLViewerWearable *wearable = getWearable((LLWearableType::EType)type,count); llassert(wearable); if (wearable) { @@ -1972,7 +1972,7 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos for (U32 i = 0; i < wearable_vec.size(); ++i) { - LLWearable* wearable = wearable_vec[i]; + LLViewerWearable* wearable = wearable_vec[i]; if (!wearable) continue; if (wearable->getAssetID() != asset_id) continue; @@ -1991,7 +1991,7 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con { if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return; - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type); LLAssetType::EType asset_type = wearable->getAssetType(); LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; LLPointer cb = wear ? new LLWearAndEditCallback : NULL; @@ -2024,7 +2024,7 @@ void LLAgentWearables::editWearable(const LLUUID& item_id) return; } - LLWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); + LLViewerWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); if (!wearable) { llwarns << "Cannot get wearable" << llendl; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 5932be21c6..3df552544b 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -40,10 +40,9 @@ class LLInventoryItem; class LLVOAvatarSelf; -class LLWearable; +class LLViewerWearable; class LLInitialWearablesFetch; class LLViewerObject; -class LLTexLayerTemplate; class LLAgentWearables : public LLInitClass { @@ -82,7 +81,7 @@ public: bool canMoveWearable(const LLUUID& item_id, bool closer_to_body); // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1. - bool canWearableBeRemoved(const LLWearable* wearable) const; + bool canWearableBeRemoved(const LLViewerWearable* wearable) const; void animateAllWearableParams(F32 delta, BOOL upload_bake); @@ -92,15 +91,15 @@ public: public: const LLUUID getWearableItemID(LLWearableType::EType type, U32 index /*= 0*/) const; const LLUUID getWearableAssetID(LLWearableType::EType type, U32 index /*= 0*/) const; - const LLWearable* getWearableFromItemID(const LLUUID& item_id) const; - LLWearable* getWearableFromItemID(const LLUUID& item_id); - LLWearable* getWearableFromAssetID(const LLUUID& asset_id); + const LLViewerWearable* getWearableFromItemID(const LLUUID& item_id) const; + LLViewerWearable* getWearableFromItemID(const LLUUID& item_id); + LLViewerWearable* getWearableFromAssetID(const LLUUID& asset_id); LLInventoryItem* getWearableInventoryItem(LLWearableType::EType type, U32 index /*= 0*/); static BOOL selfHasWearable(LLWearableType::EType type); - LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); - const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; - LLWearable* getTopWearable(const LLWearableType::EType type); - LLWearable* getBottomWearable(const LLWearableType::EType type); + LLViewerWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLViewerWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; + LLViewerWearable* getTopWearable(const LLWearableType::EType type); + LLViewerWearable* getBottomWearable(const LLWearableType::EType type); U32 getWearableCount(const LLWearableType::EType type) const; U32 getWearableCount(const U32 tex_index) const; @@ -113,31 +112,31 @@ public: private: // Low-level data structure setter - public access is via setWearableItem, etc. - void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); - U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable); - void wearableUpdated(LLWearable *wearable); - void popWearable(LLWearable *wearable); + void setWearable(const LLWearableType::EType type, U32 index, LLViewerWearable *wearable); + U32 pushWearable(const LLWearableType::EType type, LLViewerWearable *wearable); + void wearableUpdated(LLViewerWearable *wearable); + void popWearable(LLViewerWearable *wearable); void popWearable(const LLWearableType::EType type, U32 index); public: - void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false); - void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove); + void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false); + void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index); - U32 getWearableIndex(const LLWearable *wearable) const; + U32 getWearableIndex(const LLViewerWearable *wearable) const; protected: - void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false); - static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable); + void setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append = false); + static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable); void addWearableToAgentInventory(LLPointer cb, - LLWearable* wearable, + LLViewerWearable* wearable, const LLUUID& category_id = LLUUID::null, BOOL notify = TRUE); void addWearabletoAgentInventoryDone(const LLWearableType::EType type, const U32 index, const LLUUID& item_id, - LLWearable* wearable); + LLViewerWearable* wearable); void recoverMissingWearable(const LLWearableType::EType type, U32 index /*= 0*/); void recoverMissingWearableDone(); @@ -180,7 +179,7 @@ protected: void sendAgentWearablesRequest(); void queryWearableCache(); void updateServer(); - static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata); + static void onInitialWearableAssetArrived(LLViewerWearable* wearable, void* userdata); //-------------------------------------------------------------------- // Outfits @@ -245,7 +244,7 @@ private: // Member variables //-------------------------------------------------------------------- private: - typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) + typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type wearableentry_map_t mWearableDatas; @@ -289,13 +288,13 @@ private: addWearableToAgentInventoryCallback(LLPointer cb, LLWearableType::EType type, U32 index, - LLWearable* wearable, + LLViewerWearable* wearable, U32 todo = CALL_NONE); virtual void fire(const LLUUID& inv_item); private: LLWearableType::EType mType; U32 mIndex; - LLWearable* mWearable; + LLViewerWearable* mWearable; U32 mTodo; LLPointer mCB; }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3e02f98933..58a0b0fa5b 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -277,7 +277,7 @@ struct LLFoundData std::string mName; LLAssetType::EType mAssetType; LLWearableType::EType mWearableType; - LLWearable* mWearable; + LLViewerWearable* mWearable; bool mIsReplacement; }; @@ -301,7 +301,7 @@ public: void recoverMissingWearable(LLWearableType::EType type); void clearCOFLinksForMissingWearables(); - void onWearableAssetFetch(LLWearable *wearable); + void onWearableAssetFetch(LLViewerWearable *wearable); void onAllComplete(); typedef std::list found_list_t; @@ -327,7 +327,7 @@ private: typedef std::set type_set_hp; static type_set_hp sActiveHoldingPatterns; bool mIsMostRecent; - std::set mLateArrivals; + std::set mLateArrivals; bool mIsAllComplete; }; @@ -561,7 +561,7 @@ bool LLWearableHoldingPattern::pollFetchCompletion() class RecoveredItemLinkCB: public LLInventoryCallback { public: - RecoveredItemLinkCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder): + RecoveredItemLinkCB(LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder): mHolder(holder), mWearable(wearable), mType(type) @@ -609,14 +609,14 @@ public: } private: LLWearableHoldingPattern* mHolder; - LLWearable *mWearable; + LLViewerWearable *mWearable; LLWearableType::EType mType; }; class RecoveredItemCB: public LLInventoryCallback { public: - RecoveredItemCB(LLWearableType::EType type, LLWearable *wearable, LLWearableHoldingPattern* holder): + RecoveredItemCB(LLWearableType::EType type, LLViewerWearable *wearable, LLWearableHoldingPattern* holder): mHolder(holder), mWearable(wearable), mType(type) @@ -649,7 +649,7 @@ public: } private: LLWearableHoldingPattern* mHolder; - LLWearable *mWearable; + LLViewerWearable *mWearable; LLWearableType::EType mType; }; @@ -665,7 +665,7 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearableType::getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type); // Add a new one in the lost and found folder. const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); @@ -772,11 +772,11 @@ void LLWearableHoldingPattern::handleLateArrivals() iter != getFoundList().end(); ++iter) { LLFoundData& data = *iter; - for (std::set::iterator wear_it = mLateArrivals.begin(); + for (std::set::iterator wear_it = mLateArrivals.begin(); wear_it != mLateArrivals.end(); ++wear_it) { - LLWearable *wearable = *wear_it; + LLViewerWearable *wearable = *wear_it; if(wearable->getAssetID() == data.mAssetID) { @@ -836,7 +836,7 @@ void LLWearableHoldingPattern::resetTime(F32 timeout) mWaitTime.setTimerExpirySec(timeout); } -void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) +void LLWearableHoldingPattern::onWearableAssetFetch(LLViewerWearable *wearable) { if (!isMostRecent()) { @@ -887,7 +887,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable) } } -static void onWearableAssetFetch(LLWearable* wearable, void* data) +static void onWearableAssetFetch(LLViewerWearable* wearable, void* data) { LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data; holder->onWearableAssetFetch(wearable); @@ -1588,7 +1588,7 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo { lldebugs << "updateAgentWearables()" << llendl; LLInventoryItem::item_array_t items; - LLDynamicArray< LLWearable* > wearables; + LLDynamicArray< LLViewerWearable* > wearables; // For each wearable type, find the wearables of that type. for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) @@ -1597,7 +1597,7 @@ void LLAppearanceMgr::updateAgentWearables(LLWearableHoldingPattern* holder, boo iter != holder->getFoundList().end(); ++iter) { LLFoundData& data = *iter; - LLWearable* wearable = data.mWearable; + LLViewerWearable* wearable = data.mWearable; if( wearable && ((S32)wearable->getType() == i) ) { LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 742833211a..370aec8a8f 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -35,7 +35,6 @@ #include "llinventoryobserver.h" #include "llviewerinventory.h" -class LLWearable; class LLWearableHoldingPattern; class LLInventoryCallback; class LLOutfitUnLockTimer; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 65bfc990d1..35e44d73d4 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -48,8 +48,8 @@ #include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "llviewermenufile.h" +#include "llviewertexlayer.h" #include "llviewerwindow.h" -#include "lltexlayer.h" #include "lltrans.h" // library includes diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b539ac38ed..d2acd32713 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -37,6 +37,8 @@ #include "lluictrlfactory.h" #include "llagentdata.h" #include "llimfloater.h" +#include "llviewertexture.h" +#include "llvoavatardefines.h" // library includes #include "llavatarnamecache.h" diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 885cae1737..0ae9acd1af 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -32,7 +32,7 @@ #include "llvoavatar.h" #include "llvoavatarself.h" #include "llagent.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llagentwearables.h" //----------------------------------------------------------------------------- @@ -623,10 +623,19 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) { + bool use_self = false; if(isAgentAvatarValid() && - mWearablep && - driven->mParam->getCrossWearable() && - mWearablep->isOnTop()) + mWearablep && + driven->mParam->getCrossWearable()) + { + LLViewerWearable* wearable = dynamic_cast (mWearablep); + if (!wearable->isOnTop()) + { + use_self = false; + } + } + + if (use_self) { // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values gAgentAvatarp->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 2939d31087..3c40e2d4bc 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -38,6 +38,7 @@ #include "message.h" #include "llagent.h" +#include "llassetstorage.h" #include "llcombobox.h" #include "llestateinfomodel.h" #include "llmimetypes.h" diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 4e10b4fc2c..b26b302ea6 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -32,6 +32,7 @@ #include "llagent.h" #include "llagentwearables.h" +#include "llviewerwearable.h" #include "lltexturectrl.h" #include "lluictrlfactory.h" #include "llviewerobjectlist.h" @@ -81,7 +82,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, if (avatarp->isSelf()) { const LLWearableType::EType wearable_type = tex_entry->mWearableType; - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(te); @@ -173,7 +174,7 @@ void LLFloaterAvatarTextures::onClickDump(void* data) LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i); if (avatarp->isSelf()) { - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(i); diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 2f9810775b..97f72b020c 100644 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -29,6 +29,7 @@ #include "llgroupiconctrl.h" #include "llagent.h" +#include "llviewertexture.h" /* #include "llavatarconstants.h" #include "llcallingcard.h" // for LLAvatarTracker diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b819100b9b..17e9b8026a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5692,7 +5692,7 @@ void LLWearableBridge::wearAddOnAvatar() } // static -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) +void LLWearableBridge::onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata ) { LLUUID* item_id = (LLUUID*) userdata; if(wearable) @@ -5718,7 +5718,7 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda // static // BAP remove the "add" code path once everything is fully COF-ified. -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) +void LLWearableBridge::onWearAddOnAvatarArrived( LLViewerWearable* wearable, void* userdata ) { LLUUID* item_id = (LLUUID*) userdata; if(wearable) @@ -5799,7 +5799,7 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data) } // static -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, +void LLWearableBridge::onRemoveFromAvatarArrived(LLViewerWearable* wearable, void* userdata) { OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index dc9e88d54d..067e4bdf3d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -33,7 +33,7 @@ #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llviewercontrol.h" -#include "llwearable.h" +#include "llviewerwearable.h" class LLInventoryFilter; class LLInventoryPanel; @@ -486,10 +486,10 @@ public: static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu static BOOL canWearOnAvatar( void* userdata ); - static void onWearOnAvatarArrived( LLWearable* wearable, void* userdata ); + static void onWearOnAvatarArrived( LLViewerWearable* wearable, void* userdata ); void wearOnAvatar(); - static void onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ); + static void onWearAddOnAvatarArrived( LLViewerWearable* wearable, void* userdata ); void wearAddOnAvatar(); static BOOL canEditOnAvatar( void* userdata ); // Access to editOnAvatar() from menu @@ -498,7 +498,7 @@ public: static BOOL canRemoveFromAvatar( void* userdata ); static void onRemoveFromAvatar( void* userdata ); - static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata ); + static void onRemoveFromAvatarArrived( LLViewerWearable* wearable, void* userdata ); static void removeItemFromAvatar(LLViewerInventoryItem *item); static void removeAllClothesFromAvatar(); void removeFromAvatar(); diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp deleted file mode 100644 index 34734d57c5..0000000000 --- a/indra/newview/llinventoryicon.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file llinventoryicon.cpp - * @brief Implementation of the inventory icon. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llinventoryicon.h" - -#include "lldictionary.h" -#include "llinventorydefines.h" -#include "llui.h" -#include "llwearabletype.h" - -struct IconEntry : public LLDictionaryEntry -{ - IconEntry(const std::string &item_name) - : - LLDictionaryEntry(item_name) - {} -}; - -class LLIconDictionary : public LLSingleton, - public LLDictionary -{ -public: - LLIconDictionary(); -}; - -LLIconDictionary::LLIconDictionary() -{ - addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); - addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); - addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); - - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); - addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); - addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); - - addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); - addEntry(LLInventoryIcon::ICONNAME_MESH, new IconEntry("Inv_Mesh")); - - addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); - - addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); -} - -LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 misc_flag, - BOOL item_is_multi) -{ - const std::string& icon_name = getIconName(asset_type, inventory_type, misc_flag, item_is_multi); - return LLUI::getUIImage(icon_name); -} - -LLUIImagePtr LLInventoryIcon::getIcon(EIconName idx) -{ - return LLUI::getUIImage(getIconName(idx)); -} - -const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 misc_flag, - BOOL item_is_multi) -{ - EIconName idx = ICONNAME_OBJECT; - if (item_is_multi) - { - idx = ICONNAME_OBJECT_MULTI; - return getIconName(idx); - } - - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? ICONNAME_SNAPSHOT : ICONNAME_TEXTURE; - break; - case LLAssetType::AT_SOUND: - idx = ICONNAME_SOUND; - break; - case LLAssetType::AT_CALLINGCARD: - idx = (misc_flag != 0) ? ICONNAME_CALLINGCARD_ONLINE : ICONNAME_CALLINGCARD_OFFLINE; - break; - case LLAssetType::AT_LANDMARK: - idx = (misc_flag != 0) ? ICONNAME_LANDMARK_VISITED : ICONNAME_LANDMARK; - break; - case LLAssetType::AT_SCRIPT: - case LLAssetType::AT_LSL_TEXT: - case LLAssetType::AT_LSL_BYTECODE: - idx = ICONNAME_SCRIPT; - break; - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - idx = assignWearableIcon(misc_flag); - break; - case LLAssetType::AT_NOTECARD: - idx = ICONNAME_NOTECARD; - break; - case LLAssetType::AT_ANIMATION: - idx = ICONNAME_ANIMATION; - break; - case LLAssetType::AT_GESTURE: - idx = ICONNAME_GESTURE; - break; - case LLAssetType::AT_LINK: - idx = ICONNAME_LINKITEM; - break; - case LLAssetType::AT_LINK_FOLDER: - idx = ICONNAME_LINKFOLDER; - break; - case LLAssetType::AT_OBJECT: - idx = ICONNAME_OBJECT; - break; - case LLAssetType::AT_MESH: - idx = ICONNAME_MESH; - default: - break; - } - - return getIconName(idx); -} - - -const std::string& LLInventoryIcon::getIconName(EIconName idx) -{ - const IconEntry *entry = LLIconDictionary::instance().lookup(idx); - return entry->mName; -} - -LLInventoryIcon::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) -{ - const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); - return LLWearableType::getIconName(wearable_type); -} diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h deleted file mode 100644 index c7e2998a20..0000000000 --- a/indra/newview/llinventoryicon.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file llinventoryfunctions.h - * @brief Miscellaneous inventory-related functions and classes - * class definition - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLINVENTORYICON_H -#define LL_LLINVENTORYICON_H - -#include "llassettype.h" -#include "llinventorytype.h" -#include "lluiimage.h" - -class LLInventoryIcon -{ -public: - enum EIconName - { - ICONNAME_TEXTURE, - ICONNAME_SOUND, - ICONNAME_CALLINGCARD_ONLINE, - ICONNAME_CALLINGCARD_OFFLINE, - ICONNAME_LANDMARK, - ICONNAME_LANDMARK_VISITED, - ICONNAME_SCRIPT, - ICONNAME_CLOTHING, - ICONNAME_OBJECT, - ICONNAME_OBJECT_MULTI, - ICONNAME_NOTECARD, - ICONNAME_BODYPART, - ICONNAME_SNAPSHOT, - - ICONNAME_BODYPART_SHAPE, - ICONNAME_BODYPART_SKIN, - ICONNAME_BODYPART_HAIR, - ICONNAME_BODYPART_EYES, - ICONNAME_CLOTHING_SHIRT, - ICONNAME_CLOTHING_PANTS, - ICONNAME_CLOTHING_SHOES, - ICONNAME_CLOTHING_SOCKS, - ICONNAME_CLOTHING_JACKET, - ICONNAME_CLOTHING_GLOVES, - ICONNAME_CLOTHING_UNDERSHIRT, - ICONNAME_CLOTHING_UNDERPANTS, - ICONNAME_CLOTHING_SKIRT, - ICONNAME_CLOTHING_ALPHA, - ICONNAME_CLOTHING_TATTOO, - - ICONNAME_ANIMATION, - ICONNAME_GESTURE, - - ICONNAME_CLOTHING_PHYSICS, - - ICONNAME_LINKITEM, - ICONNAME_LINKFOLDER, - ICONNAME_MESH, - - ICONNAME_INVALID, - ICONNAME_COUNT, - ICONNAME_NONE = -1 - }; - - static const std::string& getIconName(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - U32 misc_flag = 0, // different meanings depending on item type - BOOL item_is_multi = FALSE); - static const std::string& getIconName(EIconName idx); - - static LLUIImagePtr getIcon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - U32 misc_flag = 0, // different meanings depending on item type - BOOL item_is_multi = FALSE); - static LLUIImagePtr getIcon(EIconName idx); - -protected: - static EIconName assignWearableIcon(U32 misc_flag); -}; -#endif // LL_LLINVENTORYICON_H - - - diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 459e52c4f4..097c751386 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -55,7 +55,7 @@ #include "llviewerobject.h" #include "llface.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "llagentwearables.h" #include "lltexlayerparams.h" #include "llvovolume.h" @@ -483,7 +483,7 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp U32 count = gAgentWearables.getWearableCount(type); for(U32 wearable_iter = 0; wearable_iter < count; wearable_iter++) { - LLWearable* wearable = gAgentWearables.getWearable(type, wearable_iter); + LLViewerWearable* wearable = gAgentWearables.getWearable(type, wearable_iter); if (wearable) { std::vector texture_list = wearable->getLocalTextureListSeq(); diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index 7a23c7ef6e..df031de3cb 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -33,6 +33,7 @@ #include "llvoavatardefines.h" class LLScrollListCtrl; +class LLViewerObject; class LLLocalBitmap { diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp deleted file mode 100644 index 07ec0fab95..0000000000 --- a/indra/newview/lllocaltextureobject.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @file lllocaltextureobject.cpp - * - * $LicenseInfo:firstyear=2009&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 "lllocaltextureobject.h" - -#include "lltexlayer.h" -#include "llviewertexture.h" -#include "lltextureentry.h" -#include "lluuid.h" -#include "llwearable.h" - - -LLLocalTextureObject::LLLocalTextureObject() : - mIsBakedReady(FALSE), - mDiscard(MAX_DISCARD_LEVEL+1) -{ - mImage = NULL; -} - -LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id) : - mIsBakedReady(FALSE), - mDiscard(MAX_DISCARD_LEVEL+1) -{ - mImage = image; - gGL.getTexUnit(0)->bind(mImage); - mID = id; -} - -LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : - mImage(lto.mImage), - mID(lto.mID), - mIsBakedReady(lto.mIsBakedReady), - mDiscard(lto.mDiscard) -{ - U32 num_layers = lto.getNumTexLayers(); - mTexLayers.reserve(num_layers); - for (U32 index = 0; index < num_layers; index++) - { - LLTexLayer* original_layer = lto.getTexLayer(index); - if (!original_layer) - { - llerrs << "could not clone Local Texture Object: unable to extract texlayer!" << llendl; - continue; - } - - LLTexLayer* new_layer = new LLTexLayer(*original_layer); - new_layer->setLTO(this); - mTexLayers.push_back(new_layer); - } -} - -LLLocalTextureObject::~LLLocalTextureObject() -{ -} - -LLViewerFetchedTexture* LLLocalTextureObject::getImage() const -{ - return mImage; -} - -LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const -{ - if (index >= getNumTexLayers()) - { - return NULL; - } - - return mTexLayers[index]; -} - -LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) -{ - for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++) - { - LLTexLayer *layer = *iter; - if (layer->getName().compare(name) == 0) - { - return layer; - } - } - - return NULL; -} - -U32 LLLocalTextureObject::getNumTexLayers() const -{ - return mTexLayers.size(); -} - -LLUUID LLLocalTextureObject::getID() const -{ - return mID; -} - -S32 LLLocalTextureObject::getDiscard() const -{ - return mDiscard; -} - -BOOL LLLocalTextureObject::getBakedReady() const -{ - return mIsBakedReady; -} - -void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image) -{ - mImage = new_image; -} - -BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) -{ - if (index >= getNumTexLayers() ) - { - return FALSE; - } - - if (new_tex_layer == NULL) - { - return removeTexLayer(index); - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer); - layer->setLTO(this); - - if (mTexLayers[index]) - { - delete mTexLayers[index]; - } - mTexLayers[index] = layer; - - return TRUE; -} - -BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) -{ - if (new_tex_layer == NULL) - { - return FALSE; - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); - layer->setLTO(this); - mTexLayers.push_back(layer); - return TRUE; -} - -BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) -{ - if (new_tex_layer == NULL) - { - return FALSE; - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable); - layer->setLTO(this); - mTexLayers.push_back(layer); - return TRUE; -} - -BOOL LLLocalTextureObject::removeTexLayer(U32 index) -{ - if (index >= getNumTexLayers()) - { - return FALSE; - } - tex_layer_vec_t::iterator iter = mTexLayers.begin(); - iter += index; - - delete *iter; - mTexLayers.erase(iter); - return TRUE; -} - -void LLLocalTextureObject::setID(LLUUID new_id) -{ - mID = new_id; -} - -void LLLocalTextureObject::setDiscard(S32 new_discard) -{ - mDiscard = new_discard; -} - -void LLLocalTextureObject::setBakedReady(BOOL ready) -{ - mIsBakedReady = ready; -} - diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h deleted file mode 100644 index b9bfc5472f..0000000000 --- a/indra/newview/lllocaltextureobject.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file lllocaltextureobject.h - * @brief LLLocalTextureObject class header file - * - * $LicenseInfo:firstyear=2009&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_LOCALTEXTUREOBJECT_H -#define LL_LOCALTEXTUREOBJECT_H - -#include - -#include "llviewertexture.h" - -class LLUUID; -class LLTexLayer; -class LLTextureEntry; -class LLTexLayerTemplate; -class LLWearable; - -// Stores all relevant information for a single texture -// assumed to have ownership of all objects referred to - -// will delete objects when being replaced or if object is destroyed. -class LLLocalTextureObject -{ -public: - LLLocalTextureObject(); - LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id); - LLLocalTextureObject(const LLLocalTextureObject& lto); - ~LLLocalTextureObject(); - - LLViewerFetchedTexture* getImage() const; - LLTexLayer* getTexLayer(U32 index) const; - LLTexLayer* getTexLayer(const std::string &name); - U32 getNumTexLayers() const; - LLUUID getID() const; - S32 getDiscard() const; - BOOL getBakedReady() const; - - void setImage(LLViewerFetchedTexture* new_image); - BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index); - BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); - BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); - BOOL removeTexLayer(U32 index); - - void setID(LLUUID new_id); - void setDiscard(S32 new_discard); - void setBakedReady(BOOL ready); - -protected: - -private: - - LLPointer mImage; - // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer - // using shared pointers here only for smart assignment & cleanup - // do NOT create new shared pointers to these objects, or keep pointers to them around - typedef std::vector tex_layer_vec_t; - tex_layer_vec_t mTexLayers; - - LLUUID mID; - - BOOL mIsBakedReady; - S32 mDiscard; -}; - - #endif // LL_LOCALTEXTUREOBJECT_H - diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 6889b98ab1..862e4be203 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -55,6 +55,7 @@ #include "lltrans.h" #include "llscrollcontainer.h" #include "llstatusbar.h" +#include "llviewertexture.h" const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index d58d6d536c..44b56afb1a 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -28,7 +28,7 @@ #include "llpaneleditwearable.h" #include "llpanel.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "lluictrl.h" #include "llscrollingpanellist.h" #include "llvisualparam.h" @@ -865,7 +865,7 @@ void LLPanelEditWearable::setVisible(BOOL visible) LLPanel::setVisible(visible); } -void LLPanelEditWearable::setWearable(LLWearable *wearable, BOOL disable_camera_switch) +void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_camera_switch) { showWearable(mWearablePtr, FALSE, disable_camera_switch); mWearablePtr = wearable; @@ -922,7 +922,7 @@ void LLPanelEditWearable::onCommitSexChange() } bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; - LLWearable* wearable = gAgentWearables.getWearable(type, index); + LLViewerWearable* wearable = gAgentWearables.getWearable(type, index); if (wearable) { wearable->setVisualParamWeight(param->getID(), is_new_sex_male, FALSE); @@ -1069,7 +1069,7 @@ void LLPanelEditWearable::revertChanges() gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE); } -void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch) +void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch) { if (!wearable) { @@ -1445,7 +1445,7 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value { LLPanel::Params p; p.name("LLScrollingPanelParam"); - LLWearable *wearable = this->getWearable(); + LLViewerWearable *wearable = this->getWearable(); LLScrollingPanelParamBase *panel_param = NULL; if (wearable && wearable->getType() == LLWearableType::WT_PHYSICS) // Hack to show a different panel for physics. Should generalize this later. { diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 692a7ce90f..85e43c8ebd 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -35,7 +35,7 @@ class LLAccordionCtrl; class LLCheckBoxCtrl; -class LLWearable; +class LLViewerWearable; class LLTextBox; class LLViewerInventoryItem; class LLViewerVisualParam; @@ -58,8 +58,8 @@ public: // changes camera angle to default for selected subpart void changeCamera(U8 subpart); - LLWearable* getWearable() { return mWearablePtr; } - void setWearable(LLWearable *wearable, BOOL disable_camera_switch = FALSE); + LLViewerWearable* getWearable() { return mWearablePtr; } + void setWearable(LLViewerWearable *wearable, BOOL disable_camera_switch = FALSE); void saveChanges(bool force_save_as = false); void revertChanges(); @@ -80,7 +80,7 @@ public: private: typedef std::map value_map_t; - void showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE); + void showWearable(LLViewerWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE); void updateScrollingPanelUI(); LLPanel* getPanel(LLWearableType::EType type); void getSortedParams(value_map_t &sorted_params, const std::string &edit_group); @@ -115,7 +115,7 @@ private: void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel); // the pointer to the wearable we're editing. NULL means we're not editing a wearable. - LLWearable *mWearablePtr; + LLViewerWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; // these are constant no matter what wearable we're editing diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp index 4f2d6da7e5..aebe636f59 100644 --- a/indra/newview/llpostcard.cpp +++ b/indra/newview/llpostcard.cpp @@ -35,6 +35,7 @@ #include "message.h" #include "llagent.h" +#include "llassetstorage.h" #include "llassetuploadresponders.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 9267444534..6a692209e9 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -47,7 +47,7 @@ #include "llviewercontrol.h" #include "llviewerregion.h" #include "llvoavatarself.h" -#include "llwearable.h" +#include "llviewerwearable.h" static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); @@ -198,7 +198,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) if (is_outfit_edit_visible || is_wearable_edit_visible) { - const LLWearable *wearable_ptr = mEditWearable->getWearable(); + const LLViewerWearable *wearable_ptr = mEditWearable->getWearable(); if (!wearable_ptr) { llwarns << "Visibility change to invalid wearable" << llendl; @@ -326,7 +326,7 @@ void LLSidepanelAppearance::showOutfitEditPanel() toggleOutfitEditPanel(TRUE); } -void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/, BOOL disable_camera_switch) +void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) { toggleMyOutfitsPanel(FALSE); toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode @@ -379,7 +379,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam } } -void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable, BOOL disable_camera_switch) +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { if (!mEditWearable || mEditWearable->getVisible() == visible) { @@ -445,7 +445,7 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) } //static -void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch) +void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch) { LLFloaterSidePanelContainer::showPanel("appearance", LLSD()); diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 6dd3520266..32bbb8a776 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -36,7 +36,7 @@ class LLFilterEditor; class LLCurrentlyWornFetchObserver; class LLPanelEditWearable; -class LLWearable; +class LLViewerWearable; class LLPanelOutfitsInventory; class LLSidepanelAppearance : public LLPanel @@ -51,7 +51,7 @@ public: void refreshCurrentOutfitName(const std::string& name = ""); - static void editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE); + static void editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE); void fetchInventory(); void inventoryFetched(); @@ -59,7 +59,7 @@ public: void showOutfitsInventoryPanel(); void showOutfitEditPanel(); - void showWearableEditPanel(LLWearable *wearable = NULL, BOOL disable_camera_switch = FALSE); + void showWearableEditPanel(LLViewerWearable *wearable = NULL, BOOL disable_camera_switch = FALSE); void setWearablesLoading(bool val); void showDefaultSubpart(); void updateScrollingPanelList(); @@ -74,7 +74,7 @@ private: void toggleMyOutfitsPanel(BOOL visible); void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE); - void toggleWearableEditPanel(BOOL visible, LLWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); + void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp deleted file mode 100644 index ebe5ccd6c0..0000000000 --- a/indra/newview/lltexglobalcolor.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @file lltexlayerglobalcolor.cpp - * @brief Color for texture layers. - * - * $LicenseInfo:firstyear=2008&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 "llagent.h" -#include "lltexlayer.h" -#include "llvoavatar.h" -#include "llwearable.h" -#include "lltexglobalcolor.h" - -//----------------------------------------------------------------------------- -// LLTexGlobalColor -//----------------------------------------------------------------------------- - -LLTexGlobalColor::LLTexGlobalColor(LLVOAvatar* avatar) - : - mAvatar(avatar), - mInfo(NULL) -{ -} - -LLTexGlobalColor::~LLTexGlobalColor() -{ - // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter() - //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); -} - -BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) -{ - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); - for (param_color_info_list_t::iterator iter = mInfo->mParamColorInfoList.begin(); - iter != mInfo->mParamColorInfoList.end(); - iter++) - { - LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); - if (!param_color->setInfo(*iter, TRUE)) - { - mInfo = NULL; - return FALSE; - } - mParamGlobalColorList.push_back(param_color); - } - - return TRUE; -} - -LLColor4 LLTexGlobalColor::getColor() const -{ - // Sum of color params - if (mParamGlobalColorList.empty()) - return LLColor4(1.f, 1.f, 1.f, 1.f); - - LLColor4 net_color(0.f, 0.f, 0.f, 0.f); - LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color); - return net_color; -} - -const std::string& LLTexGlobalColor::getName() const -{ - return mInfo->mName; -} - -//----------------------------------------------------------------------------- -// LLTexParamGlobalColor -//----------------------------------------------------------------------------- -LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) : - LLTexLayerParamColor(tex_global_color->getAvatar()), - mTexGlobalColor(tex_global_color) -{ -} - -/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const -{ - LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor); - *new_param = *this; - return new_param; -} - -void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake) -{ - mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake); -} - -//----------------------------------------------------------------------------- -// LLTexGlobalColorInfo -//----------------------------------------------------------------------------- - -LLTexGlobalColorInfo::LLTexGlobalColorInfo() -{ -} - - -LLTexGlobalColorInfo::~LLTexGlobalColorInfo() -{ - for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); -} - -BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) -{ - // name attribute - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - llwarns << " element is missing name attribute." << llendl; - return FALSE; - } - // sub-element - for (LLXmlTreeNode* child = node->getChildByName("param"); - child; - child = node->getNextNamedChild()) - { - if (child->getChildByName("param_color")) - { - // - LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - mParamColorInfoList.push_back(info); - } - } - return TRUE; -} diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h deleted file mode 100644 index ae04798445..0000000000 --- a/indra/newview/lltexglobalcolor.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file lltexglobalcolor.h - * @brief This is global texture color info used by llvoavatar. - * - * $LicenseInfo:firstyear=2008&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_LLTEXGLOBALCOLOR_H -#define LL_LLTEXGLOBALCOLOR_H - -#include "lltexlayer.h" -#include "lltexlayerparams.h" - -class LLVOAvatar; -class LLWearable; -class LLTexGlobalColorInfo; - -class LLTexGlobalColor -{ -public: - LLTexGlobalColor( LLVOAvatar* avatar ); - ~LLTexGlobalColor(); - - LLTexGlobalColorInfo* getInfo() const { return mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexGlobalColorInfo *info); - - LLVOAvatar* getAvatar() const { return mAvatar; } - LLColor4 getColor() const; - const std::string& getName() const; - -private: - param_color_list_t mParamGlobalColorList; - LLVOAvatar* mAvatar; // just backlink, don't LLPointer - LLTexGlobalColorInfo *mInfo; -}; - -// Used by llvoavatar to determine skin/eye/hair color. -class LLTexGlobalColorInfo -{ - friend class LLTexGlobalColor; -public: - LLTexGlobalColorInfo(); - ~LLTexGlobalColorInfo(); - - BOOL parseXml(LLXmlTreeNode* node); - -private: - param_color_info_list_t mParamColorInfoList; - std::string mName; -}; - -class LLTexParamGlobalColor : public LLTexLayerParamColor -{ -public: - LLTexParamGlobalColor(LLTexGlobalColor *tex_color); - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; -protected: - /*virtual*/ void onGlobalColorChanged(bool upload_bake); -private: - LLTexGlobalColor* mTexGlobalColor; -}; - -#endif diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp deleted file mode 100644 index 467115c928..0000000000 --- a/indra/newview/lltexlayer.cpp +++ /dev/null @@ -1,2508 +0,0 @@ -/** - * @file lltexlayer.cpp - * @brief A texture layer. Used for avatars. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lltexlayer.h" - -#include "llagent.h" -#include "llimagej2c.h" -#include "llimagetga.h" -#include "llnotificationsutil.h" -#include "llvfile.h" -#include "llvfs.h" -#include "llviewerstats.h" -#include "llviewerregion.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "pipeline.h" -#include "llassetuploadresponders.h" -#include "lltexlayerparams.h" -#include "llui.h" -#include "llagentwearables.h" -#include "llwearable.h" -#include "llviewercontrol.h" -#include "llviewershadermgr.h" -#include "llviewervisualparam.h" - -//#include "../tools/imdebug/imdebug.h" - -using namespace LLVOAvatarDefines; - -static const S32 BAKE_UPLOAD_ATTEMPTS = 7; -static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt - -// runway consolidate -extern std::string self_av_string(); - -class LLTexLayerInfo -{ - friend class LLTexLayer; - friend class LLTexLayerTemplate; - friend class LLTexLayerInterface; -public: - LLTexLayerInfo(); - ~LLTexLayerInfo(); - - BOOL parseXml(LLXmlTreeNode* node); - BOOL createVisualParams(LLVOAvatar *avatar); - BOOL isUserSettable() { return mLocalTexture != -1; } - S32 getLocalTexture() const { return mLocalTexture; } - BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } - std::string getName() const { return mName; } - -private: - std::string mName; - - BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, - LLTexLayerInterface::ERenderPass mRenderPass; - - std::string mGlobalColor; - LLColor4 mFixedColor; - - S32 mLocalTexture; - std::string mStaticImageFileName; - BOOL mStaticImageIsMask; - BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask - BOOL mIsVisibilityMask; - - typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t; - morph_name_list_t mMorphNameList; - param_color_info_list_t mParamColorInfoList; - param_alpha_info_list_t mParamAlphaInfoList; -}; - -//----------------------------------------------------------------------------- -// LLBakedUploadData() -//----------------------------------------------------------------------------- -LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, - LLTexLayerSet* layerset, - const LLUUID& id, - bool highest_res) : - mAvatar(avatar), - mTexLayerSet(layerset), - mID(id), - mStartTime(LLFrameTimer::getTotalTime()), // Record starting time - mIsHighestRes(highest_res) -{ -} - -//----------------------------------------------------------------------------- -// LLTexLayerSetBuffer -// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. -//----------------------------------------------------------------------------- - -// static -S32 LLTexLayerSetBuffer::sGLByteCount = 0; - -LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner, - S32 width, S32 height) : - // ORDER_LAST => must render these after the hints are created. - LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), - mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates - mNeedsUpload(FALSE), - mNumLowresUploads(0), - mUploadFailCount(0), - mNeedsUpdate(TRUE), - mNumLowresUpdates(0), - mTexLayerSet(owner) -{ - LLTexLayerSetBuffer::sGLByteCount += getSize(); - mNeedsUploadTimer.start(); - mNeedsUpdateTimer.start(); -} - -LLTexLayerSetBuffer::~LLTexLayerSetBuffer() -{ - LLTexLayerSetBuffer::sGLByteCount -= getSize(); - destroyGLTexture(); - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. - } -} - -//virtual -S8 LLTexLayerSetBuffer::getType() const -{ - return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ; -} - -//virtual -void LLTexLayerSetBuffer::restoreGLTexture() -{ - LLViewerDynamicTexture::restoreGLTexture() ; -} - -//virtual -void LLTexLayerSetBuffer::destroyGLTexture() -{ - LLViewerDynamicTexture::destroyGLTexture() ; -} - -// static -void LLTexLayerSetBuffer::dumpTotalByteCount() -{ - llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; -} - -void LLTexLayerSetBuffer::requestUpdate() -{ - restartUpdateTimer(); - mNeedsUpdate = TRUE; - mNumLowresUpdates = 0; - // If we're in the middle of uploading a baked texture, we don't care about it any more. - // When it's downloaded, ignore it. - mUploadID.setNull(); -} - -void LLTexLayerSetBuffer::requestUpload() -{ - conditionalRestartUploadTimer(); - mNeedsUpload = TRUE; - mNumLowresUploads = 0; - mUploadPending = TRUE; -} - -void LLTexLayerSetBuffer::conditionalRestartUploadTimer() -{ - // If we requested a new upload but haven't even uploaded - // a low res version of our last upload request, then - // keep the timer ticking instead of resetting it. - if (mNeedsUpload && (mNumLowresUploads == 0)) - { - mNeedsUploadTimer.unpause(); - } - else - { - mNeedsUploadTimer.reset(); - mNeedsUploadTimer.start(); - } -} - -void LLTexLayerSetBuffer::restartUpdateTimer() -{ - mNeedsUpdateTimer.reset(); - mNeedsUpdateTimer.start(); -} - -void LLTexLayerSetBuffer::cancelUpload() -{ - mNeedsUpload = FALSE; - mUploadPending = FALSE; - mNeedsUploadTimer.pause(); - mUploadRetryTimer.reset(); -} - -void LLTexLayerSetBuffer::pushProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); -} - -void LLTexLayerSetBuffer::popProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); -} - -BOOL LLTexLayerSetBuffer::needsRender() -{ - llassert(mTexLayerSet->getAvatar() == gAgentAvatarp); - if (!isAgentAvatarValid()) return FALSE; - - const BOOL upload_now = mNeedsUpload && isReadyToUpload(); - const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); - - // Don't render if we don't want to (or aren't ready to) upload or update. - if (!(update_now || upload_now)) - { - return FALSE; - } - - // Don't render if we're animating our appearance. - if (gAgentAvatarp->getIsAppearanceAnimating()) - { - return FALSE; - } - - // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. - if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && - !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) - { - cancelUpload(); - return FALSE; - } - - // Render if we have at least minimal level of detail for each local texture. - return mTexLayerSet->isLocalTextureDataAvailable(); -} - -void LLTexLayerSetBuffer::preRender(BOOL clear_depth) -{ - // Set up an ortho projection - pushProjection(); - - // keep depth buffer, we don't need to clear it - LLViewerDynamicTexture::preRender(FALSE); -} - -void LLTexLayerSetBuffer::postRender(BOOL success) -{ - popProjection(); - - LLViewerDynamicTexture::postRender(success); -} - -BOOL LLTexLayerSetBuffer::render() -{ - // Default color mask for tex layer render - gGL.setColorMask(true, true); - - // do we need to upload, and do we have sufficient data to create an uploadable composite? - // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero? - const BOOL upload_now = mNeedsUpload && isReadyToUpload(); - const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); - - BOOL success = TRUE; - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if (use_shaders) - { - gAlphaMaskProgram.bind(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - LLVertexBuffer::unbind(); - - // Composite the color data - LLGLSUIDefault gls_ui; - success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); - gGL.flush(); - - if(upload_now) - { - if (!success) - { - llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl; - mUploadPending = FALSE; - } - else - { - if (mTexLayerSet->isVisible()) - { - mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. - doUpload(); - } - else - { - mUploadPending = FALSE; - mNeedsUpload = FALSE; - mNeedsUploadTimer.pause(); - mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE); - } - } - } - - if (update_now) - { - doUpdate(); - } - - if (use_shaders) - { - gAlphaMaskProgram.unbind(); - } - - LLVertexBuffer::unbind(); - - // reset GL state - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - // we have valid texture data now - mGLTexturep->setGLTextureCreated(true); - - return success; -} - -BOOL LLTexLayerSetBuffer::isInitialized(void) const -{ - return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); -} - -BOOL LLTexLayerSetBuffer::uploadPending() const -{ - return mUploadPending; -} - -BOOL LLTexLayerSetBuffer::uploadNeeded() const -{ - return mNeedsUpload; -} - -BOOL LLTexLayerSetBuffer::uploadInProgress() const -{ - return !mUploadID.isNull(); -} - -BOOL LLTexLayerSetBuffer::isReadyToUpload() const -{ - if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. - - BOOL ready = FALSE; - if (mTexLayerSet->isLocalTextureDataFinal()) - { - // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) - if (mUploadFailCount == 0) - { - ready = TRUE; - } - else - { - ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1)); - } - } - else - { - // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure - // we aren't doing uploads too frequently. - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); - if (texture_timeout != 0) - { - // The timeout period increases exponentially between every lowres upload in order to prevent - // spamming the server with frequent uploads. - const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); - - // If we hit our timeout and have textures available at even lower resolution, then upload. - const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); - ready = has_lower_lod && is_upload_textures_timeout; - } - } - - return ready; -} - -BOOL LLTexLayerSetBuffer::isReadyToUpdate() const -{ - // If we requested an update and have the final LOD ready, then update. - if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; - - // If we haven't done an update yet, then just do one now regardless of state of textures. - if (mNumLowresUpdates == 0) return TRUE; - - // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small - // since render unnecessarily doesn't cost much. - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout"); - if (texture_timeout != 0) - { - // If we hit our timeout and have textures available at even lower resolution, then update. - const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); - if (has_lower_lod && is_update_textures_timeout) return TRUE; - } - - return FALSE; -} - -BOOL LLTexLayerSetBuffer::requestUpdateImmediate() -{ - mNeedsUpdate = TRUE; - BOOL result = FALSE; - - if (needsRender()) - { - preRender(FALSE); - result = render(); - postRender(result); - } - - return result; -} - -// Create the baked texture, send it out to the server, then wait for it to come -// back so we can switch to using it. -void LLTexLayerSetBuffer::doUpload() -{ - llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); - - // Don't need caches since we're baked now. (note: we won't *really* be baked - // until this image is sent to the server and the Avatar Appearance message is received.) - mTexLayerSet->deleteCaches(); - - // Get the COLOR information from our texture - U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; - glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); - stop_glerror(); - - // Get the MASK information from our texture - LLGLSUIDefault gls_ui; - LLPointer baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); - U8* baked_mask_data = baked_mask_image->getData(); - mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); - - - // Create the baked image from our color and mask information - const S32 baked_image_components = 5; // red green blue [bump] clothing - LLPointer baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); - U8* baked_image_data = baked_image->getData(); - S32 i = 0; - for (S32 u=0; u < mFullWidth; u++) - { - for (S32 v=0; v < mFullHeight; v++) - { - baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; - baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; - baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. - baked_image_data[5*i + 4] = baked_mask_data[i]; - i++; - } - } - - LLPointer compressedImage = new LLImageJ2C; - const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) - if (compressedImage->encode(baked_image, comment_text)) - { - LLTransactionID tid; - tid.generate(); - const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), - gVFS, asset_id, LLAssetType::AT_TEXTURE)) - { - // Read back the file and validate. - BOOL valid = FALSE; - LLPointer integrity_test = new LLImageJ2C; - S32 file_size = 0; - U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size); - if (data) - { - valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' - } - else - { - integrity_test->setLastError("Unable to read entire file"); - } - - if (valid) - { - const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - // Baked_upload_data is owned by the responder and deleted after the request completes. - LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, - this->mTexLayerSet, - asset_id, - highest_lod); - // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. - mUploadID = asset_id; - - // Upload the image - const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); - if(!url.empty() - && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method - && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. - { - LLSD body = LLSD::emptyMap(); - // The responder will call LLTexLayerSetBuffer::onTextureUploadComplete() - LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); - llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; - } - else - { - gAssetStorage->storeAssetData(tid, - LLAssetType::AT_TEXTURE, - LLTexLayerSetBuffer::onTextureUploadComplete, - baked_upload_data, - TRUE, // temp_file - TRUE, // is_priority - TRUE); // store_local - llinfos << "Baked texture upload via Asset Store." << llendl; - } - - if (highest_lod) - { - // Sending the final LOD for the baked texture. All done, pause - // the upload timer so we know how long it took. - mNeedsUpload = FALSE; - mNeedsUploadTimer.pause(); - } - else - { - // Sending a lower level LOD for the baked texture. Restart the upload timer. - mNumLowresUploads++; - mNeedsUploadTimer.unpause(); - mNeedsUploadTimer.reset(); - } - - // Print out notification that we uploaded this texture. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); - args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); - args["RESOLUTION"] = lod_str; - LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; - } - } - else - { - // The read back and validate operation failed. Remove the uploaded file. - mUploadPending = FALSE; - LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); - file.remove(); - llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl; - } - } - } - else - { - // The VFS write file operation failed. - mUploadPending = FALSE; - llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl; - } - - delete [] baked_color_data; -} - -// Mostly bookkeeping; don't need to actually "do" anything since -// render() will actually do the update. -void LLTexLayerSetBuffer::doUpdate() -{ - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - if (highest_lod) - { - mNeedsUpdate = FALSE; - } - else - { - mNumLowresUpdates++; - } - - restartUpdateTimer(); - - // need to swtich to using this layerset if this is the first update - // after getting the lowest LOD - mTexLayerSet->getAvatar()->updateMeshTextures(); - - // Print out notification that we uploaded this texture. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); - const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); - args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); - args["RESOLUTION"] = lod_str; - LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; - } -} - -// static -void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, - void* userdata, - S32 result, - LLExtStat ext_status) // StoreAssetData callback (not fixed) -{ - LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; - - if (isAgentAvatarValid() && - !gAgentAvatarp->isDead() && - (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures. - (baked_upload_data->mTexLayerSet->hasComposite())) - { - LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); - S32 failures = layerset_buffer->mUploadFailCount; - layerset_buffer->mUploadFailCount = 0; - - if (layerset_buffer->mUploadID.isNull()) - { - // The upload got canceled, we should be in the - // process of baking a new texture so request an - // upload with the new data - - // BAP: does this really belong in this callback, as - // opposed to where the cancellation takes place? - // suspect this does nothing. - layerset_buffer->requestUpload(); - } - else if (baked_upload_data->mID == layerset_buffer->mUploadID) - { - // This is the upload we're currently waiting for. - layerset_buffer->mUploadID.setNull(); - const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName()); - const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res "; - if (result >= 0) - { - layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later - LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); - // Update baked texture info with the new UUID - U64 now = LLFrameTimer::getTotalTime(); // Record starting time - llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; - gAgentAvatarp->setNewBakedTexture(baked_te, uuid); - } - else - { - ++failures; - S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes - llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl; - if (failures < max_attempts) - { - layerset_buffer->mUploadFailCount = failures; - layerset_buffer->mUploadRetryTimer.start(); - layerset_buffer->requestUpload(); - } - } - } - else - { - llinfos << "Received baked texture out of date, ignored." << llendl; - } - - gAgentAvatarp->dirtyMesh(); - } - else - { - // Baked texture failed to upload (in which case since we - // didn't set the new baked texture, it means that they'll try - // and rebake it at some point in the future (after login?)), - // or this response to upload is out of date, in which case a - // current response should be on the way or already processed. - llwarns << "Baked upload failed" << llendl; - } - - delete baked_upload_data; -} - -//----------------------------------------------------------------------------- -// LLTexLayerSet -// An ordered set of texture layers that get composited into a single texture. -//----------------------------------------------------------------------------- - -LLTexLayerSetInfo::LLTexLayerSetInfo() : - mBodyRegion( "" ), - mWidth( 512 ), - mHeight( 512 ), - mClearAlpha( TRUE ) -{ -} - -LLTexLayerSetInfo::~LLTexLayerSetInfo( ) -{ - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); -} - -BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "layer_set" ) ); - if( !node->hasName( "layer_set" ) ) - { - return FALSE; - } - - // body_region - static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region"); - if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) - { - llwarns << " is missing body_region attribute" << llendl; - return FALSE; - } - - // width, height - static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); - if( !node->getFastAttributeS32( width_string, mWidth ) ) - { - return FALSE; - } - - static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); - if( !node->getFastAttributeS32( height_string, mHeight ) ) - { - return FALSE; - } - - // Optional alpha component to apply after all compositing is complete. - static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file"); - node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName ); - - static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha"); - node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha ); - - // - for (LLXmlTreeNode* child = node->getChildByName( "layer" ); - child; - child = node->getNextNamedChild()) - { - LLTexLayerInfo* info = new LLTexLayerInfo(); - if( !info->parseXml( child )) - { - delete info; - return FALSE; - } - mLayerInfoList.push_back( info ); - } - return TRUE; -} - -// creates visual params without generating layersets or layers -void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar) -{ - //layer_info_list_t mLayerInfoList; - for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin(); - layer_iter != mLayerInfoList.end(); - layer_iter++) - { - LLTexLayerInfo *layer_info = *layer_iter; - layer_info->createVisualParams(avatar); - } -} - -//----------------------------------------------------------------------------- -// LLTexLayerSet -// An ordered set of texture layers that get composited into a single texture. -//----------------------------------------------------------------------------- - -BOOL LLTexLayerSet::sHasCaches = FALSE; - -LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) : - mComposite( NULL ), - mAvatar( avatar ), - mUpdatesEnabled( FALSE ), - mIsVisible( TRUE ), - mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD), - mInfo( NULL ) -{ -} - -LLTexLayerSet::~LLTexLayerSet() -{ - deleteCaches(); - std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); - std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer()); -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) -{ - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - mLayerList.reserve(info->mLayerInfoList.size()); - for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin(); - iter != info->mLayerInfoList.end(); - iter++) - { - LLTexLayerInterface *layer = NULL; - if ( (*iter)->isUserSettable() ) - { - layer = new LLTexLayerTemplate( this ); - } - else - { - layer = new LLTexLayer(this); - } - // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar - if (!layer->setInfo(*iter, NULL)) - { - mInfo = NULL; - return FALSE; - } - if (!layer->isVisibilityMask()) - { - mLayerList.push_back( layer ); - } - else - { - mMaskLayerList.push_back(layer); - } - } - - requestUpdate(); - - stop_glerror(); - - return TRUE; -} - -#if 0 // obsolete -//----------------------------------------------------------------------------- -// parseData -//----------------------------------------------------------------------------- - -BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) -{ - LLTexLayerSetInfo *info = new LLTexLayerSetInfo; - - if (!info->parseXml(node)) - { - delete info; - return FALSE; - } - if (!setInfo(info)) - { - delete info; - return FALSE; - } - return TRUE; -} -#endif - -void LLTexLayerSet::deleteCaches() -{ - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - layer->deleteCaches(); - } - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) - { - LLTexLayerInterface* layer = *iter; - layer->deleteCaches(); - } -} - -// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. -BOOL LLTexLayerSet::isLocalTextureDataAvailable() const -{ - if (!mAvatar->isSelf()) return FALSE; - return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataAvailable(this); -} - - -// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. -BOOL LLTexLayerSet::isLocalTextureDataFinal() const -{ - if (!mAvatar->isSelf()) return FALSE; - return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataFinal(this); -} - - -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) -{ - BOOL success = TRUE; - mIsVisible = TRUE; - - if (mMaskLayerList.size() > 0) - { - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) - { - LLTexLayerInterface* layer = *iter; - if (layer->isInvisibleAlphaMask()) - { - mIsVisible = FALSE; - } - } - } - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); - gGL.setColorMask(true, true); - - // clear buffer area to ensure we don't pick up UI elements - { - gGL.flush(); - LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.0f); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - - gl_rect_2d_simple( width, height ); - - gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - - if (mIsVisible) - { - // composite color layers - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - if (layer->getRenderPass() == LLTexLayer::RP_COLOR) - { - gGL.flush(); - success &= layer->render(x, y, width, height); - gGL.flush(); - } - } - - renderAlphaMaskTextures(x, y, width, height, false); - - stop_glerror(); - } - else - { - gGL.flush(); - - gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 0.f ); - - gl_rect_2d_simple( width, height ); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - - return success; -} - - -BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const -{ - return mInfo->mBodyRegion == region; -} - -const std::string LLTexLayerSet::getBodyRegionName() const -{ - return mInfo->mBodyRegion; -} - -void LLTexLayerSet::requestUpdate() -{ - if( mUpdatesEnabled ) - { - createComposite(); - mComposite->requestUpdate(); - } -} - -void LLTexLayerSet::requestUpload() -{ - createComposite(); - mComposite->requestUpload(); -} - -void LLTexLayerSet::cancelUpload() -{ - if(mComposite) - { - mComposite->cancelUpload(); - } -} - -void LLTexLayerSet::createComposite() -{ - if(!mComposite) - { - S32 width = mInfo->mWidth; - S32 height = mInfo->mHeight; - // Composite other avatars at reduced resolution - if( !mAvatar->isSelf() ) - { - llerrs << "composites should not be created for non-self avatars!" << llendl; - } - mComposite = new LLTexLayerSetBuffer( this, width, height ); - } -} - -void LLTexLayerSet::destroyComposite() -{ - if( mComposite ) - { - mComposite = NULL; - } -} - -void LLTexLayerSet::setUpdatesEnabled( BOOL b ) -{ - mUpdatesEnabled = b; -} - - -void LLTexLayerSet::updateComposite() -{ - createComposite(); - mComposite->requestUpdateImmediate(); -} - -LLTexLayerSetBuffer* LLTexLayerSet::getComposite() -{ - if (!mComposite) - { - createComposite(); - } - return mComposite; -} - -const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const -{ - return mComposite; -} - -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) -{ - memset(data, 255, width * height); - - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); - } - - // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); -} - -void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) -{ - const LLTexLayerSetInfo *info = getInfo(); - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - gGL.setColorMask(false, true); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - // (Optionally) replace alpha with a single component image from a tga file. - if (!info->mStaticAlphaFileName.empty()) - { - gGL.flush(); - { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); - if( tex ) - { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->bind(tex); - gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); - gl_rect_2d_simple_tex( width, height ); - } - } - gGL.flush(); - } - else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0)) - { - // Set the alpha channel to one (clean up after previous blending) - gGL.flush(); - LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - - gl_rect_2d_simple( width, height ); - - gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - - // (Optional) Mask out part of the baked texture with alpha masks - // will still have an effect even if mClearAlpha is set or the alpha component was replaced - if (mMaskLayerList.size() > 0) - { - gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); - gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) - { - LLTexLayerInterface* layer = *iter; - gGL.flush(); - layer->blendAlphaTexture(x,y,width, height); - gGL.flush(); - } - - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); -} - -void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) -{ - mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); -} - -BOOL LLTexLayerSet::isMorphValid() const -{ - for(layer_list_t::const_iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - const LLTexLayerInterface* layer = *iter; - if (layer && !layer->isMorphValid()) - { - return FALSE; - } - } - return TRUE; -} - -void LLTexLayerSet::invalidateMorphMasks() -{ - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - if (layer) - { - layer->invalidateMorphMasks(); - } - } -} - - -//----------------------------------------------------------------------------- -// LLTexLayerInfo -//----------------------------------------------------------------------------- -LLTexLayerInfo::LLTexLayerInfo() : - mWriteAllChannels( FALSE ), - mRenderPass(LLTexLayer::RP_COLOR), - mFixedColor( 0.f, 0.f, 0.f, 0.f ), - mLocalTexture( -1 ), - mStaticImageIsMask( FALSE ), - mUseLocalTextureAlphaOnly(FALSE), - mIsVisibilityMask(FALSE) -{ -} - -LLTexLayerInfo::~LLTexLayerInfo( ) -{ - std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); - std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer()); -} - -BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "layer" ) ); - - // name attribute - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if( !node->getFastAttributeString( name_string, mName ) ) - { - return FALSE; - } - - static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); - node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels ); - - std::string render_pass_name; - static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass"); - if( node->getFastAttributeString( render_pass_string, render_pass_name ) ) - { - if( render_pass_name == "bump" ) - { - mRenderPass = LLTexLayer::RP_BUMP; - } - } - - // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a child. - // global color attribute (optional) - static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); - node->getFastAttributeString( global_color_string, mGlobalColor ); - - // Visibility mask (optional) - BOOL is_visibility; - static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); - if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) - { - mIsVisibilityMask = is_visibility; - } - - // color attribute (optional) - LLColor4U color4u; - static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); - if( node->getFastAttributeColor4U( fixed_color_string, color4u ) ) - { - mFixedColor.setVec( color4u ); - } - - // optional sub-element - for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" ); - texture_node; - texture_node = node->getNextNamedChild()) - { - std::string local_texture_name; - static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); - static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); - static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); - static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only"); - if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) - { - texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); - } - else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name)) - { - texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); - - /* if ("upper_shirt" == local_texture_name) - mLocalTexture = TEX_UPPER_SHIRT; */ - mLocalTexture = TEX_NUM_INDICES; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) - { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; - if (local_texture_name == texture_dict->mName) - { - mLocalTexture = iter->first; - break; - } - } - if (mLocalTexture == TEX_NUM_INDICES) - { - llwarns << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << llendl; - return FALSE; - } - } - else - { - llwarns << " element is missing a required attribute. " << mName << llendl; - return FALSE; - } - } - - for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" ); - maskNode; - maskNode = node->getNextNamedChild()) - { - std::string morph_name; - static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); - if (maskNode->getFastAttributeString(morph_name_string, morph_name)) - { - BOOL invert = FALSE; - static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); - maskNode->getFastAttributeBOOL(invert_string, invert); - mMorphNameList.push_back(std::pair(morph_name,invert)); - } - } - - // optional sub-element (color or alpha params) - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if( child->getChildByName( "param_color" ) ) - { - // - LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - mParamColorInfoList.push_back(info); - } - else if( child->getChildByName( "param_alpha" ) ) - { - // - LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( ); - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - mParamAlphaInfoList.push_back(info); - } - } - - return TRUE; -} - -BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar) -{ - BOOL success = TRUE; - for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin(); - color_info_iter != mParamColorInfoList.end(); - color_info_iter++) - { - LLTexLayerParamColorInfo * color_info = *color_info_iter; - LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar); - if (!param_color->setInfo(color_info, TRUE)) - { - llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl; - delete param_color; - success = FALSE; - } - } - - for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin(); - alpha_info_iter != mParamAlphaInfoList.end(); - alpha_info_iter++) - { - LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter; - LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar); - if (!param_alpha->setInfo(alpha_info, TRUE)) - { - llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl; - delete param_alpha; - success = FALSE; - } - } - - return success; -} - -LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): - mTexLayerSet( layer_set ), - mMorphMasksValid( FALSE ), - mInfo(NULL), - mHasMorph(FALSE) -{ -} - -LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable): - mTexLayerSet( layer.mTexLayerSet ), - mInfo(NULL) -{ - // don't add visual params for cloned layers - setInfo(layer.getInfo(), wearable); - - mHasMorph = layer.mHasMorph; -} - -BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions -{ - // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. - // Not a critical warning, but could be useful for debugging later issues. -Nyx - if (mInfo != NULL) - { - llwarns << "mInfo != NULL" << llendl; - } - mInfo = info; - //mID = info->mID; // No ID - - mParamColorList.reserve(mInfo->mParamColorInfoList.size()); - for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin(); - iter != mInfo->mParamColorInfoList.end(); - iter++) - { - LLTexLayerParamColor* param_color; - if (!wearable) - { - param_color = new LLTexLayerParamColor(this); - if (!param_color->setInfo(*iter, TRUE)) - { - mInfo = NULL; - return FALSE; - } - } - else - { - param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID()); - if (!param_color) - { - mInfo = NULL; - return FALSE; - } - } - mParamColorList.push_back( param_color ); - } - - mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); - for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin(); - iter != mInfo->mParamAlphaInfoList.end(); - iter++) - { - LLTexLayerParamAlpha* param_alpha; - if (!wearable) - { - param_alpha = new LLTexLayerParamAlpha( this ); - if (!param_alpha->setInfo(*iter, TRUE)) - { - mInfo = NULL; - return FALSE; - } - } - else - { - param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID()); - if (!param_alpha) - { - mInfo = NULL; - return FALSE; - } - } - mParamAlphaList.push_back( param_alpha ); - } - - return TRUE; -} - -/*virtual*/ void LLTexLayerInterface::requestUpdate() -{ - mTexLayerSet->requestUpdate(); -} - -const std::string& LLTexLayerInterface::getName() const -{ - return mInfo->mName; -} - -LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const -{ - return mInfo->mRenderPass; -} - -const std::string& LLTexLayerInterface::getGlobalColor() const -{ - return mInfo->mGlobalColor; -} - -BOOL LLTexLayerInterface::isVisibilityMask() const -{ - return mInfo->mIsVisibilityMask; -} - -void LLTexLayerInterface::invalidateMorphMasks() -{ - mMorphMasksValid = FALSE; -} - -LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const -{ - LLViewerVisualParam *result = NULL; - for (param_color_list_t::const_iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter) - { - if ((*color_iter)->getID() == index) - { - result = *color_iter; - } - } - for (param_alpha_list_t::const_iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter) - { - if ((*alpha_iter)->getID() == index) - { - result = *alpha_iter; - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// LLTexLayer -// A single texture layer, consisting of: -// * color, consisting of either -// * one or more color parameters (weighted colors) -// * a reference to a global color -// * a fixed color with non-zero alpha -// * opaque white (the default) -// * (optional) a texture defined by either -// * a GUID -// * a texture entry index (TE) -// * (optional) one or more alpha parameters (weighted alpha textures) -//----------------------------------------------------------------------------- -LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : - LLTexLayerInterface( layer_set ), - mLocalTextureObject(NULL) -{ -} - -LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) : - LLTexLayerInterface( layer, wearable ), - mLocalTextureObject(NULL) -{ -} - -LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) : - LLTexLayerInterface( layer_template, wearable ), - mLocalTextureObject(lto) -{ -} - -LLTexLayer::~LLTexLayer() -{ - // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get - // deleted with ~LLCharacter() - //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer()); - //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); - - for( alpha_cache_t::iterator iter = mAlphaCache.begin(); - iter != mAlphaCache.end(); iter++ ) - { - U8* alpha_data = iter->second; - delete [] alpha_data; - } - -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) -{ - return LLTexLayerInterface::setInfo(info, wearable); -} - -//static -void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) -{ - for (param_color_list_t::const_iterator iter = param_list.begin(); - iter != param_list.end(); iter++) - { - const LLTexLayerParamColor* param = *iter; - LLColor4 param_net = param->getNetColor(); - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); - switch(info->getOperation()) - { - case LLTexLayerParamColor::OP_ADD: - net_color += param_net; - break; - case LLTexLayerParamColor::OP_MULTIPLY: - net_color = net_color * param_net; - break; - case LLTexLayerParamColor::OP_BLEND: - net_color = lerp(net_color, param_net, param->getWeight()); - break; - default: - llassert(0); - break; - } - } - net_color.clamp(); -} - -/*virtual*/ void LLTexLayer::deleteCaches() -{ - // Only need to delete caches for alpha params. Color params don't hold extra memory - for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); - iter != mParamAlphaList.end(); iter++ ) - { - LLTexLayerParamAlpha* param = *iter; - param->deleteCaches(); - } -} - -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) -{ - LLGLEnable color_mat(GL_COLOR_MATERIAL); - gPipeline.disableLights(); - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - LLColor4 net_color; - BOOL color_specified = findNetColor(&net_color); - - if (mTexLayerSet->getAvatar()->mIsDummy) - { - color_specified = true; - net_color = LLVOAvatar::getDummyColor(); - } - - BOOL success = TRUE; - - // If you can't see the layer, don't render it. - if( is_approx_zero( net_color.mV[VW] ) ) - { - return success; - } - - BOOL alpha_mask_specified = FALSE; - param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); - if( iter != mParamAlphaList.end() ) - { - // If we have alpha masks, but we're skipping all of them, skip the whole layer. - // However, we can't do this optimization if we have morph masks that need updating. -/* if (!mHasMorph) - { - BOOL skip_layer = TRUE; - - while( iter != mParamAlphaList.end() ) - { - const LLTexLayerParamAlpha* param = *iter; - - if( !param->getSkip() ) - { - skip_layer = FALSE; - break; - } - - iter++; - } - - if( skip_layer ) - { - return success; - } - }//*/ - - renderMorphMasks(x, y, width, height, net_color); - alpha_mask_specified = TRUE; - gGL.flush(); - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); - } - - gGL.color4fv( net_color.mV); - - if( getInfo()->mWriteAllChannels ) - { - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - } - - if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) - { - { - LLViewerTexture* tex = NULL; - if (mLocalTextureObject && mLocalTextureObject->getImage()) - { - tex = mLocalTextureObject->getImage(); - if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR) - { - tex = NULL; - } - } - else - { - llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl; - } -// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) - { - if( tex ) - { - bool no_alpha_test = getInfo()->mWriteAllChannels; - LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0); - if (use_shaders && no_alpha_test) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex, TRUE); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (use_shaders && no_alpha_test) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - } - } -// else -// { -// success = FALSE; -// } - } - } - - if( !getInfo()->mStaticImageFileName.empty() ) - { - { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - gGL.getTexUnit(0)->bind(tex, TRUE); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - else - { - success = FALSE; - } - } - } - - if(((-1 == getInfo()->mLocalTexture) || - getInfo()->mUseLocalTextureAlphaOnly) && - getInfo()->mStaticImageFileName.empty() && - color_specified ) - { - LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( net_color.mV ); - gl_rect_2d_simple( width, height ); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - - if( alpha_mask_specified || getInfo()->mWriteAllChannels ) - { - // Restore standard blend func value - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - stop_glerror(); - } - - if( !success ) - { - llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl; - } - return success; -} - -const U8* LLTexLayer::getAlphaData() const -{ - LLCRC alpha_mask_crc; - const LLUUID& uuid = getUUID(); - alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - - for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) - { - const LLTexLayerParamAlpha* param = *iter; - // MULTI-WEARABLE: verify visual parameters used here - F32 param_weight = param->getWeight(); - alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); - } - - U32 cache_index = alpha_mask_crc.getCRC(); - - alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index); - return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; -} - -BOOL LLTexLayer::findNetColor(LLColor4* net_color) const -{ - // Color is either: - // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) - // * a reference to a global color - // * a fixed color with non-zero alpha - // * opaque white (the default) - - if( !mParamColorList.empty() ) - { - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); - } - else if (getInfo()->mFixedColor.mV[VW]) - { - net_color->setVec( getInfo()->mFixedColor ); - } - else - { - net_color->setVec( 0.f, 0.f, 0.f, 0.f ); - } - - calculateTexLayerColor(mParamColorList, *net_color); - return TRUE; - } - - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) ); - return TRUE; - } - - if( getInfo()->mFixedColor.mV[VW] ) - { - net_color->setVec( getInfo()->mFixedColor ); - return TRUE; - } - - net_color->setToWhite(); - - return FALSE; // No need to draw a separate colored polygon -} - -BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) -{ - BOOL success = TRUE; - - gGL.flush(); - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if( !getInfo()->mStaticImageFileName.empty() ) - { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); - if( tex ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - gGL.getTexUnit(0)->bind(tex, TRUE); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - else - { - success = FALSE; - } - } - else - { - if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) - { - LLViewerTexture* tex = mLocalTextureObject->getImage(); - if (tex) - { - LLGLSNoAlphaTest gls_no_alpha_test; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - gGL.getTexUnit(0)->bind(tex); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - success = TRUE; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - } - } - - return success; -} - -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) -{ - addAlphaMask(data, originX, originY, width, height); -} - -BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) -{ - BOOL success = TRUE; - - llassert( !mParamAlphaList.empty() ); - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - - gGL.setColorMask(false, true); - - LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); - // Note: if the first param is a mulitply, multiply against the current buffer's alpha - if( !first_param || !first_param->getMultiplyBlend() ) - { - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Clear the alpha - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - gGL.color4f( 0.f, 0.f, 0.f, 0.f ); - gl_rect_2d_simple( width, height ); - } - - // Accumulate alphas - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.color4f( 1.f, 1.f, 1.f, 1.f ); - for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) - { - LLTexLayerParamAlpha* param = *iter; - success &= param->render( x, y, width, height ); - } - - // Approximates a min() function - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); - - // Accumulate the alpha component of the texture - if( getInfo()->mLocalTexture != -1 ) - { - LLViewerTexture* tex = mLocalTextureObject->getImage(); - if( tex && (tex->getComponents() == 4) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex, TRUE); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } - - if( !getInfo()->mStaticImageFileName.empty() ) - { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - if( (tex->getComponents() == 4) || - ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(tex, TRUE); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } - } - - // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. - // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if (layer_color.mV[VW] != 1.f) - { - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv(layer_color.mV); - gl_rect_2d_simple( width, height ); - } - - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - LLGLSUIDefault gls_ui; - - gGL.setColorMask(true, true); - - if (hasMorph() && success) - { - LLCRC alpha_mask_crc; - const LLUUID& uuid = getUUID(); - alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - - for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++) - { - const LLTexLayerParamAlpha* param = *iter; - F32 param_weight = param->getWeight(); - alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); - } - - U32 cache_index = alpha_mask_crc.getCRC(); - U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL); - if (!alpha_data) - { - // clear out a slot if we have filled our cache - S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1; - while ((S32)mAlphaCache.size() >= max_cache_entries) - { - alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry - alpha_data = iter2->second; - delete [] alpha_data; - mAlphaCache.erase(iter2); - } - alpha_data = new U8[width * height]; - mAlphaCache[cache_index] = alpha_data; - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); - } - - getTexLayerSet()->getAvatar()->dirtyMesh(); - - mMorphMasksValid = TRUE; - getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); - } - - return success; -} - -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) -{ - S32 size = width * height; - const U8* alphaData = getAlphaData(); - if (!alphaData && hasAlphaParams()) - { - LLColor4 net_color; - findNetColor( &net_color ); - // TODO: eliminate need for layer morph mask valid flag - invalidateMorphMasks(); - renderMorphMasks(originX, originY, width, height, net_color); - alphaData = getAlphaData(); - } - if (alphaData) - { - for( S32 i = 0; i < size; i++ ) - { - U8 curAlpha = data[i]; - U16 resultAlpha = curAlpha; - resultAlpha *= (alphaData[i] + 1); - resultAlpha = resultAlpha >> 8; - data[i] = (U8)resultAlpha; - } - } -} - -/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask() const -{ - if (mLocalTextureObject) - { - if (mLocalTextureObject->getID() == IMG_INVISIBLE) - { - return TRUE; - } - } - - return FALSE; -} - -LLUUID LLTexLayer::getUUID() const -{ - LLUUID uuid; - if( getInfo()->mLocalTexture != -1 ) - { - LLViewerTexture* tex = mLocalTextureObject->getImage(); - if (tex) - { - uuid = mLocalTextureObject->getID(); - } - } - if( !getInfo()->mStaticImageFileName.empty() ) - { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - uuid = tex->getID(); - } - } - return uuid; -} - - -//----------------------------------------------------------------------------- -// LLTexLayerTemplate -// A single texture layer, consisting of: -// * color, consisting of either -// * one or more color parameters (weighted colors) -// * a reference to a global color -// * a fixed color with non-zero alpha -// * opaque white (the default) -// * (optional) a texture defined by either -// * a GUID -// * a texture entry index (TE) -// * (optional) one or more alpha parameters (weighted alpha textures) -//----------------------------------------------------------------------------- -LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) : - LLTexLayerInterface(layer_set) -{ -} - -LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : - LLTexLayerInterface(layer) -{ -} - -LLTexLayerTemplate::~LLTexLayerTemplate() -{ -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) -{ - return LLTexLayerInterface::setInfo(info, wearable); -} - -U32 LLTexLayerTemplate::updateWearableCache() const -{ - mWearableCache.clear(); - - S32 te = mInfo->mLocalTexture; - if (te == -1) - { - //this isn't a cloneable layer - return 0; - } - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te); - U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); - U32 added = 0; - for (U32 i = 0; i < num_wearables; i++) - { - LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i); - if (!wearable) - { - continue; - } - mWearableCache.push_back(wearable); - added++; - } - return added; -} -LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const -{ - if (mWearableCache.size() <= i) - { - return NULL; - } - LLWearable *wearable = mWearableCache[i]; - LLLocalTextureObject *lto = NULL; - LLTexLayer *layer = NULL; - if (wearable) - { - lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); - } - if (lto) - { - layer = lto->getTexLayer(getName()); - } - return layer; -} - -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) -{ - if(!mInfo) - { - return FALSE ; - } - - BOOL success = TRUE; - updateWearableCache(); - for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++) - { - LLWearable* wearable = NULL; - LLLocalTextureObject *lto = NULL; - LLTexLayer *layer = NULL; - wearable = *iter; - if (wearable) - { - lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); - } - if (lto) - { - layer = lto->getTexLayer(getName()); - } - if (layer) - { - wearable->writeToAvatar(); - layer->setLTO(lto); - success &= layer->render(x,y,width,height); - } - } - - return success; -} - -/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer -{ - BOOL success = TRUE; - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - success &= layer->blendAlphaTexture(x,y,width,height); - } - } - return success; -} - -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) -{ - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->addAlphaMask(data, originX, originY, width, height); - } - } -} - -/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval) -{ - mHasMorph = newval; - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->setHasMorph(newval); - } - } -} - -/*virtual*/ void LLTexLayerTemplate::deleteCaches() -{ - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->deleteCaches(); - } - } -} - -/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask() const -{ - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - if (layer->isInvisibleAlphaMask()) - { - return TRUE; - } - } - } - - return FALSE; -} - - -//----------------------------------------------------------------------------- -// finds a specific layer based on a passed in name -//----------------------------------------------------------------------------- -LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) -{ - for (layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - if (layer->getName() == name) - { - return layer; - } - } - for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - if (layer->getName() == name) - { - return layer; - } - } - return NULL; -} - -void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable) -{ - // initialize all texlayers with this texture type for this LTO - for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; - if (layer->getInfo()->getLocalTexture() == (S32) tex_index) - { - lto->addTexLayer(layer, wearable); - } - } - for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ ) - { - LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter; - if (layer->getInfo()->getLocalTexture() == (S32) tex_index) - { - lto->addTexLayer(layer, wearable); - } - } -} -//----------------------------------------------------------------------------- -// LLTexLayerStaticImageList -//----------------------------------------------------------------------------- - -LLTexLayerStaticImageList::LLTexLayerStaticImageList() : - mGLBytes(0), - mTGABytes(0), - mImageNames(16384) -{ -} - -LLTexLayerStaticImageList::~LLTexLayerStaticImageList() -{ - deleteCachedImages(); -} - -void LLTexLayerStaticImageList::dumpByteCount() const -{ - llinfos << "Avatar Static Textures " << - "KB GL:" << (mGLBytes / 1024) << - "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; -} - -void LLTexLayerStaticImageList::deleteCachedImages() -{ - if( mGLBytes || mTGABytes ) - { - llinfos << "Clearing Static Textures " << - "KB GL:" << (mGLBytes / 1024) << - "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; - - //mStaticImageLists uses LLPointers, clear() will cause deletion - - mStaticImageListTGA.clear(); - mStaticImageList.clear(); - - mGLBytes = 0; - mTGABytes = 0; - } -} - -// Note: in general, for a given image image we'll call either getImageTga() or getTexture(). -// We call getImageTga() if the image is used as an alpha gradient. -// Otherwise, we call getTexture() - -// Returns an LLImageTGA that contains the encoded data from a tga file named file_name. -// Caches the result to speed identical subsequent requests. -LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) -{ - const char *namekey = mImageNames.addString(file_name); - image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); - if( iter != mStaticImageListTGA.end() ) - { - return iter->second; - } - else - { - std::string path; - path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); - LLPointer image_tga = new LLImageTGA( path ); - if( image_tga->getDataSize() > 0 ) - { - mStaticImageListTGA[ namekey ] = image_tga; - mTGABytes += image_tga->getDataSize(); - return image_tga; - } - else - { - return NULL; - } - } -} - -// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. -// Caches the result to speed identical subsequent requests. -LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) -{ - LLPointer tex; - const char *namekey = mImageNames.addString(file_name); - - texture_map_t::const_iterator iter = mStaticImageList.find(namekey); - if( iter != mStaticImageList.end() ) - { - tex = iter->second; - } - else - { - tex = LLViewerTextureManager::getLocalTexture( FALSE ); - LLPointer image_raw = new LLImageRaw; - if( loadImageRaw( file_name, image_raw ) ) - { - if( (image_raw->getComponents() == 1) && is_mask ) - { - // Note: these are static, unchanging images so it's ok to assume - // that once an image is a mask it's always a mask. - tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); - } - tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL); - - gGL.getTexUnit(0)->bind(tex); - tex->setAddressMode(LLTexUnit::TAM_CLAMP); - - mStaticImageList [ namekey ] = tex; - mGLBytes += (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); - } - else - { - tex = NULL; - } - } - - return tex; -} - -// Reads a .tga file, decodes it, and puts the decoded data in image_raw. -// Returns TRUE if successful. -BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) -{ - BOOL success = FALSE; - std::string path; - path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); - LLPointer image_tga = new LLImageTGA( path ); - if( image_tga->getDataSize() > 0 ) - { - // Copy data from tga to raw. - success = image_tga->decode( image_raw ); - } - - return success; -} - -const std::string LLTexLayerSetBuffer::dumpTextureInfo() const -{ - if (!isAgentAvatarValid()) return ""; - - const BOOL is_high_res = !mNeedsUpload; - const U32 num_low_res = mNumLowresUploads; - const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32(); - const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet); - - std::string status = "CREATING "; - if (!uploadNeeded()) status = "DONE "; - if (uploadInProgress()) status = "UPLOADING"; - - std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s", - status.c_str(), - is_high_res, num_low_res, - upload_time, - local_texture_info.c_str()); - return text; -} diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h deleted file mode 100644 index 4f43547dae..0000000000 --- a/indra/newview/lltexlayer.h +++ /dev/null @@ -1,380 +0,0 @@ -/** - * @file lltexlayer.h - * @brief Texture layer classes. Used for avatars. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXLAYER_H -#define LL_LLTEXLAYER_H - -#include -#include "lldynamictexture.h" -#include "llvoavatardefines.h" -#include "lltexlayerparams.h" - -class LLVOAvatar; -class LLVOAvatarSelf; -class LLImageTGA; -class LLImageRaw; -class LLXmlTreeNode; -class LLTexLayerSet; -class LLTexLayerSetInfo; -class LLTexLayerInfo; -class LLTexLayerSetBuffer; -class LLWearable; -class LLViewerVisualParam; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerInterface -// -// Interface class to generalize functionality shared by LLTexLayer -// and LLTexLayerTemplate. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerInterface -{ -public: - enum ERenderPass - { - RP_COLOR, - RP_BUMP, - RP_SHINE - }; - - LLTexLayerInterface(LLTexLayerSet* const layer_set); - LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); - virtual ~LLTexLayerInterface() {} - - virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; - virtual void deleteCaches() = 0; - virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; - virtual BOOL isInvisibleAlphaMask() const = 0; - - const LLTexLayerInfo* getInfo() const { return mInfo; } - virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions - - const std::string& getName() const; - const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } - LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } - - void invalidateMorphMasks(); - virtual void setHasMorph(BOOL newval) { mHasMorph = newval; } - BOOL hasMorph() const { return mHasMorph; } - BOOL isMorphValid() const { return mMorphMasksValid; } - - void requestUpdate(); - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; - BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } - - ERenderPass getRenderPass() const; - BOOL isVisibilityMask() const; - -protected: - const std::string& getGlobalColor() const; - LLViewerVisualParam* getVisualParamPtr(S32 index) const; - -protected: - LLTexLayerSet* const mTexLayerSet; - const LLTexLayerInfo* mInfo; - BOOL mMorphMasksValid; - BOOL mHasMorph; - - // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. - param_color_list_t mParamColorList; - param_alpha_list_t mParamAlphaList; - // mGlobalColor name stored in mInfo - // mFixedColor value stored in mInfo -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerTemplate -// -// Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerTemplate : public LLTexLayerInterface -{ -public: - LLTexLayerTemplate(LLTexLayerSet* const layer_set); - LLTexLayerTemplate(const LLTexLayerTemplate &layer); - /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); - /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - /*virtual*/ void setHasMorph(BOOL newval); - /*virtual*/ void deleteCaches(); - /*virtual*/ BOOL isInvisibleAlphaMask() const; -protected: - U32 updateWearableCache() const; - LLTexLayer* getLayer(U32 i) const; -private: - typedef std::vector wearable_cache_t; - mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayer -// -// A single texture layer. Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayer : public LLTexLayerInterface -{ -public: - LLTexLayer(LLTexLayerSet* const layer_set); - LLTexLayer(const LLTexLayer &layer, LLWearable *wearable); - LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable); - /*virtual*/ ~LLTexLayer(); - - /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); - - /*virtual*/ void deleteCaches(); - const U8* getAlphaData() const; - - BOOL findNetColor(LLColor4* color) const; - /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - /*virtual*/ BOOL isInvisibleAlphaMask() const; - - void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } - LLLocalTextureObject* getLTO() { return mLocalTextureObject; } - - static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); -protected: - LLUUID getUUID() const; -private: - typedef std::map alpha_cache_t; - alpha_cache_t mAlphaCache; - LLLocalTextureObject* mLocalTextureObject; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSet -// -// An ordered set of texture layers that gets composited into a single texture. -// Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSet -{ - friend class LLTexLayerSetBuffer; -public: - LLTexLayerSet(LLVOAvatarSelf* const avatar); - ~LLTexLayerSet(); - - const LLTexLayerSetInfo* getInfo() const { return mInfo; } - BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - - BOOL render(S32 x, S32 y, S32 width, S32 height); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); - - BOOL isBodyRegion(const std::string& region) const; - LLTexLayerSetBuffer* getComposite(); - const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. - void requestUpdate(); - void requestUpload(); - void cancelUpload(); - void updateComposite(); - BOOL isLocalTextureDataAvailable() const; - BOOL isLocalTextureDataFinal() const; - void createComposite(); - void destroyComposite(); - void setUpdatesEnabled(BOOL b); - BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } - void deleteCaches(); - void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); - BOOL isMorphValid() const; - void invalidateMorphMasks(); - LLTexLayerInterface* findLayerByName(const std::string& name); - void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); - - LLVOAvatarSelf* getAvatar() const { return mAvatar; } - const std::string getBodyRegionName() const; - BOOL hasComposite() const { return (mComposite.notNull()); } - LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } - void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } - BOOL isVisible() const { return mIsVisible; } - - static BOOL sHasCaches; - -private: - typedef std::vector layer_list_t; - layer_list_t mLayerList; - layer_list_t mMaskLayerList; - LLPointer mComposite; - LLVOAvatarSelf* const mAvatar; // note: backlink only; don't make this an LLPointer. - BOOL mUpdatesEnabled; - BOOL mIsVisible; - - LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; - const LLTexLayerSetInfo* mInfo; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSetInfo -// -// Contains shared layer set data. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetInfo -{ - friend class LLTexLayerSet; -public: - LLTexLayerSetInfo(); - ~LLTexLayerSetInfo(); - BOOL parseXml(LLXmlTreeNode* node); - void createVisualParams(LLVOAvatar *avatar); -private: - std::string mBodyRegion; - S32 mWidth; - S32 mHeight; - std::string mStaticAlphaFileName; - BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) - typedef std::vector layer_info_list_t; - layer_info_list_t mLayerInfoList; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSetBuffer -// -// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetBuffer : public LLViewerDynamicTexture -{ - LOG_CLASS(LLTexLayerSetBuffer); - -public: - LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); - virtual ~LLTexLayerSetBuffer(); - -public: - /*virtual*/ S8 getType() const; - BOOL isInitialized(void) const; - static void dumpTotalByteCount(); - const std::string dumpTextureInfo() const; - virtual void restoreGLTexture(); - virtual void destroyGLTexture(); -protected: - void pushProjection() const; - void popProjection() const; -private: - LLTexLayerSet* const mTexLayerSet; - static S32 sGLByteCount; - - //-------------------------------------------------------------------- - // Render - //-------------------------------------------------------------------- -public: - /*virtual*/ BOOL needsRender(); -protected: - BOOL render(S32 x, S32 y, S32 width, S32 height); - virtual void preRender(BOOL clear_depth); - virtual void postRender(BOOL success); - virtual BOOL render(); - - //-------------------------------------------------------------------- - // Uploads - //-------------------------------------------------------------------- -public: - void requestUpload(); - void cancelUpload(); - BOOL uploadNeeded() const; // We need to upload a new texture - BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result - BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point - static void onTextureUploadComplete(const LLUUID& uuid, - void* userdata, - S32 result, LLExtStat ext_status); -protected: - BOOL isReadyToUpload() const; - void doUpload(); // Does a read back and upload. - void conditionalRestartUploadTimer(); -private: - BOOL mNeedsUpload; // Whether we need to send our baked textures to the server - U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server - BOOL mUploadPending; // Whether we have received back the new baked textures - LLUUID mUploadID; // The current upload process (null if none). - LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed. - S32 mUploadFailCount; // Number of consecutive upload failures - LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure. - - //-------------------------------------------------------------------- - // Updates - //-------------------------------------------------------------------- -public: - void requestUpdate(); - BOOL requestUpdateImmediate(); -protected: - BOOL isReadyToUpdate() const; - void doUpdate(); - void restartUpdateTimer(); -private: - BOOL mNeedsUpdate; // Whether we need to locally update our baked textures - U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures - LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed. -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerStaticImageList -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerStaticImageList : public LLSingleton -{ -public: - LLTexLayerStaticImageList(); - ~LLTexLayerStaticImageList(); - LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask); - LLImageTGA* getImageTGA(const std::string& file_name); - void deleteCachedImages(); - void dumpByteCount() const; -protected: - BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); -private: - LLStringTable mImageNames; - typedef std::map > texture_map_t; - texture_map_t mStaticImageList; - typedef std::map > image_tga_map_t; - image_tga_map_t mStaticImageListTGA; - S32 mGLBytes; - S32 mTGABytes; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLBakedUploadData -// -// Used by LLTexLayerSetBuffer for a callback. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -struct LLBakedUploadData -{ - LLBakedUploadData(const LLVOAvatarSelf* avatar, - LLTexLayerSet* layerset, - const LLUUID& id, - bool highest_res); - ~LLBakedUploadData() {} - const LLUUID mID; - const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer - LLTexLayerSet* mTexLayerSet; - const U64 mStartTime; // for measuring baked texture upload time - const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res -}; - -#endif // LL_LLTEXLAYER_H diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp deleted file mode 100644 index 8972827eff..0000000000 --- a/indra/newview/lltexlayerparams.cpp +++ /dev/null @@ -1,568 +0,0 @@ -/** - * @file lltexlayerparams.cpp - * @brief Texture layer parameters - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lltexlayerparams.h" - -#include "llagentcamera.h" -#include "llimagetga.h" -#include "lltexlayer.h" -#include "llvoavatarself.h" -#include "llwearable.h" -#include "llui.h" - -//----------------------------------------------------------------------------- -// LLTexLayerParam -//----------------------------------------------------------------------------- -LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : - mTexLayer(layer), - mAvatar(NULL) -{ - if (mTexLayer != NULL) - { - mAvatar = mTexLayer->getTexLayerSet()->getAvatar(); - } - else - { - llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl; - } -} - -LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) : - mTexLayer(NULL) -{ - mAvatar = avatar; -} - - -BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ) -{ - LLViewerVisualParam::setInfo(info); - - if (add_to_avatar) - { - mAvatar->addVisualParam( this); - } - - return TRUE; -} - - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- - -// static -LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; - -// static -void LLTexLayerParamAlpha::dumpCacheByteCount() -{ - S32 gl_bytes = 0; - getCacheByteCount( &gl_bytes); - llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl; -} - -// static -void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) -{ - *gl_bytes = 0; - - for (param_alpha_ptr_list_t::iterator iter = sInstances.begin(); - iter != sInstances.end(); iter++) - { - LLTexLayerParamAlpha* instance = *iter; - LLViewerTexture* tex = instance->mCachedProcessedTexture; - if (tex) - { - S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); - - if (tex->hasGLTexture()) - { - *gl_bytes += bytes; - } - } - } -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) : - LLTexLayerParam(layer), - mCachedProcessedTexture(NULL), - mNeedsCreateTexture(FALSE), - mStaticImageInvalid(FALSE), - mAvgDistortionVec(1.f, 1.f, 1.f), - mCachedEffectiveWeight(0.f) -{ - sInstances.push_front(this); -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLVOAvatar* avatar) : - LLTexLayerParam(avatar), - mCachedProcessedTexture(NULL), - mNeedsCreateTexture(FALSE), - mStaticImageInvalid(FALSE), - mAvgDistortionVec(1.f, 1.f, 1.f), - mCachedEffectiveWeight(0.f) -{ - sInstances.push_front(this); -} - - -LLTexLayerParamAlpha::~LLTexLayerParamAlpha() -{ - deleteCaches(); - sInstances.remove(this); -} - -/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const -{ - LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer); - *new_param = *this; - return new_param; -} - -void LLTexLayerParamAlpha::deleteCaches() -{ - mStaticImageTGA = NULL; // deletes image - mCachedProcessedTexture = NULL; - mStaticImageRaw = NULL; - mNeedsCreateTexture = FALSE; -} - -BOOL LLTexLayerParamAlpha::getMultiplyBlend() const -{ - return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; -} - -void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake) -{ - if (mIsAnimating || mTexLayer == NULL) - { - return; - } - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); - U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); - if (cur_u8 != new_u8) - { - mCurWeight = new_weight; - - if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. - { - if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) - { - upload_bake = FALSE; - } - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); - mTexLayer->invalidateMorphMasks(); - } - } -} - -void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake) -{ - // do not animate dummy parameters - if (mIsDummy) - { - setWeight(target_value, upload_bake); - return; - } - - mTargetWeight = target_value; - setWeight(target_value, upload_bake); - mIsAnimating = TRUE; - if (mNext) - { - mNext->setAnimationTarget(target_value, upload_bake); - } -} - -void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake) -{ - if (mNext) - { - mNext->animate(delta, upload_bake); - } -} - -BOOL LLTexLayerParamAlpha::getSkip() const -{ - if (!mTexLayer) - { - return TRUE; - } - - const LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar(); - - if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight) - { - F32 effective_weight = (avatar->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); - if (is_approx_zero(effective_weight)) - { - return TRUE; - } - } - - LLWearableType::EType type = (LLWearableType::EType)getWearableType(); - if ((type != LLWearableType::WT_INVALID) && !avatar->isWearingWearableType(type)) - { - return TRUE; - } - - return FALSE; -} - - -BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) -{ - BOOL success = TRUE; - - if (!mTexLayer) - { - return success; - } - - F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); - BOOL weight_changed = effective_weight != mCachedEffectiveWeight; - if (getSkip()) - { - return success; - } - - LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo(); - gGL.flush(); - if (info->mMultiplyBlend) - { - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function - } - else - { - gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function - } - - if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid) - { - if (mStaticImageTGA.isNull()) - { - // Don't load the image file until we actually need it the first time. Like now. - mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE; - - if (mStaticImageTGA.isNull()) - { - llwarns << "Unable to load static file: " << info->mStaticImageFileName << llendl; - mStaticImageInvalid = TRUE; // don't try again. - return FALSE; - } - } - - const S32 image_tga_width = mStaticImageTGA->getWidth(); - const S32 image_tga_height = mStaticImageTGA->getHeight(); - if (!mCachedProcessedTexture || - (mCachedProcessedTexture->getWidth() != image_tga_width) || - (mCachedProcessedTexture->getHeight() != image_tga_height) || - (weight_changed)) - { -// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; - mCachedEffectiveWeight = effective_weight; - - if (!mCachedProcessedTexture) - { - mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture(image_tga_width, image_tga_height, 1, FALSE); - - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE; - - mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - } - - // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. - mStaticImageRaw = NULL; - mStaticImageRaw = new LLImageRaw; - mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); - mNeedsCreateTexture = TRUE; - } - - if (mCachedProcessedTexture) - { - { - // Create the GL texture, and then hang onto it for future use. - if (mNeedsCreateTexture) - { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); - mNeedsCreateTexture = FALSE; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); - mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); - } - - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); - gl_rect_2d_simple_tex(width, height); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - stop_glerror(); - } - } - - // Don't keep the cache for other people's avatars - // (It's not really a "cache" in that case, but the logic is the same) - if (!mAvatar->isSelf()) - { - mCachedProcessedTexture = NULL; - } - } - else - { - LLGLDisable no_alpha(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f(0.f, 0.f, 0.f, effective_weight); - gl_rect_2d_simple(width, height); - } - - return success; -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlphaInfo -//----------------------------------------------------------------------------- -LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : - mMultiplyBlend(FALSE), - mSkipIfZeroWeight(FALSE), - mDomain(0.f) -{ -} - -BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) -{ - llassert(node->hasName("param") && node->getChildByName("param_alpha")); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; - - LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha"); - if (!param_alpha_node) - { - return FALSE; - } - - static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); - if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName)) - { - // Don't load the image file until it's actually needed. - } -// else -// { -// llwarns << " element is missing tga_file attribute." << llendl; -// } - - static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); - param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend); - - static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); - param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight); - - static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); - param_alpha_node->getFastAttributeF32(domain_string, mDomain); - - return TRUE; -} - - - - -LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) : - LLTexLayerParam(layer), - mAvgDistortionVec(1.f, 1.f, 1.f) -{ -} - -LLTexLayerParamColor::LLTexLayerParamColor(LLVOAvatar *avatar) : - LLTexLayerParam(avatar), - mAvgDistortionVec(1.f, 1.f, 1.f) -{ -} - -LLTexLayerParamColor::~LLTexLayerParamColor() -{ -} - -/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const -{ - LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer); - *new_param = *this; - return new_param; -} - -LLColor4 LLTexLayerParamColor::getNetColor() const -{ - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); - - llassert(info->mNumColors >= 1); - - F32 effective_weight = (mAvatar && (mAvatar->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); - - S32 index_last = info->mNumColors - 1; - F32 scaled_weight = effective_weight * index_last; - S32 index_start = (S32) scaled_weight; - S32 index_end = index_start + 1; - if (index_start == index_last) - { - return info->mColors[index_last]; - } - else - { - F32 weight = scaled_weight - index_start; - const LLColor4 *start = &info->mColors[ index_start ]; - const LLColor4 *end = &info->mColors[ index_end ]; - return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX], - (1.f - weight) * start->mV[VY] + weight * end->mV[VY], - (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], - (1.f - weight) * start->mV[VW] + weight * end->mV[VW]); - } -} - -void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake) -{ - if (mIsAnimating) - { - return; - } - - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); - U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); - if (cur_u8 != new_u8) - { - mCurWeight = new_weight; - - if (info->mNumColors <= 0) - { - // This will happen when we set the default weight the first time. - return; - } - - if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. - { - onGlobalColorChanged(upload_bake); - if (mTexLayer) - { - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); - } - } - -// llinfos << "param " << mName << " = " << new_weight << llendl; - } -} - -void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake) -{ - // set value first then set interpolating flag to ignore further updates - mTargetWeight = target_value; - setWeight(target_value, upload_bake); - mIsAnimating = TRUE; - if (mNext) - { - mNext->setAnimationTarget(target_value, upload_bake); - } -} - -void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake) -{ - if (mNext) - { - mNext->animate(delta, upload_bake); - } -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamColorInfo -//----------------------------------------------------------------------------- -LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : - mOperation(LLTexLayerParamColor::OP_ADD), - mNumColors(0) -{ -} - -BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) -{ - llassert(node->hasName("param") && node->getChildByName("param_color")); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; - - LLXmlTreeNode* param_color_node = node->getChildByName("param_color"); - if (!param_color_node) - { - return FALSE; - } - - std::string op_string; - static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); - if (param_color_node->getFastAttributeString(operation_string, op_string)) - { - LLStringUtil::toLower(op_string); - if (op_string == "add") mOperation = LLTexLayerParamColor::OP_ADD; - else if (op_string == "multiply") mOperation = LLTexLayerParamColor::OP_MULTIPLY; - else if (op_string == "blend") mOperation = LLTexLayerParamColor::OP_BLEND; - } - - mNumColors = 0; - - LLColor4U color4u; - for (LLXmlTreeNode* child = param_color_node->getChildByName("value"); - child; - child = param_color_node->getNextNamedChild()) - { - if ((mNumColors < MAX_COLOR_VALUES)) - { - static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); - if (child->getFastAttributeColor4U(color_string, color4u)) - { - mColors[ mNumColors ].setVec(color4u); - mNumColors++; - } - } - } - if (!mNumColors) - { - llwarns << " is missing sub-elements" << llendl; - return FALSE; - } - - if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1)) - { - llwarns << " with operation\"blend\" must have exactly one " << llendl; - return FALSE; - } - - return TRUE; -} diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h deleted file mode 100644 index 2c0da60b48..0000000000 --- a/indra/newview/lltexlayerparams.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file lltexlayerparams.h - * @brief Texture layer parameters, used by lltexlayer. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXLAYERPARAMS_H -#define LL_LLTEXLAYERPARAMS_H - -#include "llviewervisualparam.h" - -class LLImageRaw; -class LLImageTGA; -class LLTexLayer; -class LLTexLayerInterface; -class LLViewerTexture; -class LLVOAvatar; -class LLWearable; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParam -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerParam : public LLViewerVisualParam -{ -public: - LLTexLayerParam(LLTexLayerInterface *layer); - LLTexLayerParam(LLVOAvatar *avatar); - /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar ); - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; - -protected: - LLTexLayerInterface* mTexLayer; - LLVOAvatar* mAvatar; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParamAlpha -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerParamAlpha : public LLTexLayerParam -{ -public: - LLTexLayerParamAlpha( LLTexLayerInterface* layer ); - LLTexLayerParamAlpha( LLVOAvatar* avatar ); - /*virtual*/ ~LLTexLayerParamAlpha(); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); - /*virtual*/ void animate(F32 delta, BOOL upload_bake); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - BOOL render( S32 x, S32 y, S32 width, S32 height ); - BOOL getSkip() const; - void deleteCaches(); - BOOL getMultiplyBlend() const; - -private: - LLPointer mCachedProcessedTexture; - LLPointer mStaticImageTGA; - LLPointer mStaticImageRaw; - BOOL mNeedsCreateTexture; - BOOL mStaticImageInvalid; - LLVector4a mAvgDistortionVec; - F32 mCachedEffectiveWeight; - -public: - // Global list of instances for gathering statistics - static void dumpCacheByteCount(); - static void getCacheByteCount( S32* gl_bytes ); - - typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; - static param_alpha_ptr_list_t sInstances; -}; -class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo -{ - friend class LLTexLayerParamAlpha; -public: - LLTexLayerParamAlphaInfo(); - /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; - - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - -private: - std::string mStaticImageFileName; - BOOL mMultiplyBlend; - BOOL mSkipIfZeroWeight; - F32 mDomain; -}; -// -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParamColor -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerParamColor : public LLTexLayerParam -{ -public: - enum EColorOperation - { - OP_ADD = 0, - OP_MULTIPLY = 1, - OP_BLEND = 2, - OP_COUNT = 3 // Number of operations - }; - - LLTexLayerParamColor( LLTexLayerInterface* layer ); - LLTexLayerParamColor( LLVOAvatar* avatar ); - /* virtual */ ~LLTexLayerParamColor(); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); - /*virtual*/ void animate(F32 delta, BOOL upload_bake); - - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - LLColor4 getNetColor() const; -protected: - virtual void onGlobalColorChanged(bool upload_bake) {} -private: - LLVector4a mAvgDistortionVec; -}; - -class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo -{ - friend class LLTexLayerParamColor; - -public: - LLTexLayerParamColorInfo(); - virtual ~LLTexLayerParamColorInfo() {}; - BOOL parseXml( LLXmlTreeNode* node ); - LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } -private: - enum { MAX_COLOR_VALUES = 20 }; - LLTexLayerParamColor::EColorOperation mOperation; - LLColor4 mColors[MAX_COLOR_VALUES]; - S32 mNumColors; -}; - -typedef std::vector param_color_list_t; -typedef std::vector param_alpha_list_t; -typedef std::vector param_color_info_list_t; -typedef std::vector param_alpha_info_list_t; - -#endif diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index c60b4155a0..4611107bc2 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -40,7 +40,7 @@ #include "lltooltip.h" #include "llappviewer.h" #include "llselectmgr.h" -#include "lltexlayer.h" +#include "llviewertexlayer.h" #include "lltexturecache.h" #include "lltexturefetch.h" #include "llviewercontrol.h" @@ -423,7 +423,7 @@ void LLAvatarTexBar::draw() ++baked_iter) { const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); + const LLViewerTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) continue; diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 76e3833acb..531c0f765c 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -31,6 +31,7 @@ // Header Files //----------------------------------------------------------------------------- #include "lljoint.h" +#include "lljointpickname.h" class LLFace; class LLViewerJointMesh; @@ -103,21 +104,8 @@ public: F32 getLOD() { return mMinPixelArea; } void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } - // Sets the OpenGL selection stack name that is pushed and popped - // with this joint state. The default value indicates that no name - // should be pushed/popped. - enum PickName - { - PN_DEFAULT = -1, - PN_0 = 0, - PN_1 = 1, - PN_2 = 2, - PN_3 = 3, - PN_4 = 4, - PN_5 = 5 - }; - void setPickName(PickName name) { mPickName = name; } - PickName getPickName() { return mPickName; } + void setPickName(LLJointPickName name) { mPickName = name; } + LLJointPickName getPickName() { return mPickName; } virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); @@ -141,7 +129,7 @@ protected: BOOL mValid; U32 mComponents; F32 mMinPixelArea; - PickName mPickName; + LLJointPickName mPickName; BOOL mVisible; S32 mMeshID; }; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 5d1aa870a3..79800c1df3 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -42,7 +42,7 @@ #include "llface.h" #include "llgldbg.h" #include "llglheaders.h" -#include "lltexlayer.h" +#include "llviewertexlayer.h" #include "llviewercamera.h" #include "llviewercontrol.h" #include "llviewertexturelist.h" @@ -248,7 +248,7 @@ void LLViewerJointMesh::setTexture( LLViewerTexture *texture ) // LLViewerJointMesh::setLayerSet() // Sets the shape texture (takes precedence over normal texture) //-------------------------------------------------------------------- -void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set ) +void LLViewerJointMesh::setLayerSet( LLViewerTexLayerSet* layer_set ) { mLayerSet = layer_set; diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index dd5dae1dc1..ff6bed4f0f 100755 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -35,7 +35,7 @@ class LLDrawable; class LLFace; class LLCharacter; -class LLTexLayerSet; +class LLViewerTexLayerSet; typedef enum e_avatar_render_pass { @@ -67,7 +67,7 @@ protected: // LLColor4 mSpecular; // specular color (always white for now) F32 mShiny; // shiny value LLPointer mTexture; // ptr to a global texture - LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar + LLViewerTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar U32 mTestImageName; // handle to a temporary texture for previewing uploads LLPolyMesh* mMesh; // ptr to a global polymesh BOOL mCullBackFaces; // true by default @@ -109,7 +109,7 @@ public: void setTestTexture( U32 name ) { mTestImageName = name; } // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) - void setLayerSet( LLTexLayerSet* layer_set ); + void setLayerSet( LLViewerTexLayerSet* layer_set ); // Gets the poly mesh LLPolyMesh *getMesh(); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index d6dd645e8c..e3d28f2f5c 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -229,7 +229,6 @@ extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; -extern LLGLSLShader gAlphaMaskProgram; //output tex0[tc0] + tex1[tc1] extern LLGLSLShader gTwoTextureAddProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index d1c6b7ea79..f049130f3a 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -41,7 +41,6 @@ #include "lltexturefetch.h" #include "llviewerobjectlist.h" #include "llviewertexturelist.h" -#include "lltexlayer.h" #include "lltexlayerparams.h" #include "llsurface.h" #include "llvlmanager.h" @@ -55,6 +54,7 @@ #include "llviewerregion.h" #include "llvoavatar.h" #include "llvoavatarself.h" +#include "llviewertexlayer.h" #include "llviewerwindow.h" // *TODO: remove, only used for width/height #include "llworld.h" #include "llfeaturemanager.h" diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp new file mode 100644 index 0000000000..f805083aaa --- /dev/null +++ b/indra/newview/llviewertexlayer.cpp @@ -0,0 +1,791 @@ +/** + * @file llviewertexlayer.cpp + * @brief Viewer texture layer. Used for avatars. + * + * $LicenseInfo:firstyear=2012&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 "llagent.h" +#include "llassetuploadresponders.h" +#include "llavatarappearance.h" +#include "llglslshader.h" +#include "llimagej2c.h" +#include "llnotificationsutil.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llviewertexlayer.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llvoavatarself.h" +#include "pipeline.h" + +static const S32 BAKE_UPLOAD_ATTEMPTS = 7; +static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt + +// runway consolidate +extern std::string self_av_string(); + +LLViewerTexLayerSet::LLViewerTexLayerSet(LLAvatarAppearance* const appearance) : + LLTexLayerSet(appearance), + mComposite( NULL ), + mUpdatesEnabled( FALSE ) +{ +} + +// virtual +LLViewerTexLayerSet::~LLViewerTexLayerSet() +{ +} + +void LLViewerTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) +{ + memset(data, 255, width * height); + + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); + } + + // Set alpha back to that of our alpha masks. + renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); +} + +LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() +{ + if (!mComposite) + { + createComposite(); + } + return mComposite; +} + +const LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() const +{ + return mComposite; +} + +// virtual +void LLViewerTexLayerSet::requestUpdate() +{ + if( mUpdatesEnabled ) + { + createComposite(); + mComposite->requestUpdate(); + } +} + +void LLViewerTexLayerSet::requestUpload() +{ + createComposite(); + mComposite->requestUpload(); +} + +void LLViewerTexLayerSet::cancelUpload() +{ + if(mComposite) + { + mComposite->cancelUpload(); + } +} + + +void LLViewerTexLayerSet::createComposite() +{ + if(!mComposite) + { + S32 width = mInfo->getWidth(); + S32 height = mInfo->getHeight(); + // Composite other avatars at reduced resolution + if( !mAvatarAppearance->isSelf() ) + { + llerrs << "composites should not be created for non-self avatars!" << llendl; + } + mComposite = new LLTexLayerSetBuffer( this, width, height ); + } +} + +void LLViewerTexLayerSet::updateComposite() +{ + createComposite(); + mComposite->requestUpdateImmediate(); +} + +// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. +BOOL LLViewerTexLayerSet::isLocalTextureDataAvailable() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + LLVOAvatarSelf* self = dynamic_cast(mAvatarAppearance); + return self->isLocalTextureDataAvailable(this); +} + + +// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. +BOOL LLViewerTexLayerSet::isLocalTextureDataFinal() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + LLVOAvatarSelf* self = dynamic_cast(mAvatarAppearance); + return self->isLocalTextureDataFinal(this); +} + +void LLViewerTexLayerSet::destroyComposite() +{ + if( mComposite ) + { + mComposite = NULL; + } +} + +void LLViewerTexLayerSet::setUpdatesEnabled( BOOL b ) +{ + mUpdatesEnabled = b; +} + +LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const +{ + return dynamic_cast (mAvatarAppearance); +} + +//----------------------------------------------------------------------------- +// LLBakedUploadData() +//----------------------------------------------------------------------------- +LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLViewerTexLayerSet* layerset, + const LLUUID& id, + bool highest_res) : + mAvatar(avatar), + mTexLayerSet(layerset), + mID(id), + mStartTime(LLFrameTimer::getTotalTime()), // Record starting time + mIsHighestRes(highest_res) +{ +} + +//----------------------------------------------------------------------------- +// LLTexLayerSetBuffer +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. +//----------------------------------------------------------------------------- + +// static +S32 LLTexLayerSetBuffer::sGLByteCount = 0; + +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLViewerTexLayerSet* const owner, + S32 width, S32 height) : + // ORDER_LAST => must render these after the hints are created. + LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), + mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates + mNeedsUpload(FALSE), + mNumLowresUploads(0), + mUploadFailCount(0), + mNeedsUpdate(TRUE), + mNumLowresUpdates(0), + mTexLayerSet(owner) +{ + LLTexLayerSetBuffer::sGLByteCount += getSize(); + mNeedsUploadTimer.start(); + mNeedsUpdateTimer.start(); +} + +LLTexLayerSetBuffer::~LLTexLayerSetBuffer() +{ + LLTexLayerSetBuffer::sGLByteCount -= getSize(); + destroyGLTexture(); + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. + } +} + +//virtual +S8 LLTexLayerSetBuffer::getType() const +{ + return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ; +} + +//virtual +void LLTexLayerSetBuffer::restoreGLTexture() +{ + LLViewerDynamicTexture::restoreGLTexture() ; +} + +//virtual +void LLTexLayerSetBuffer::destroyGLTexture() +{ + LLViewerDynamicTexture::destroyGLTexture() ; +} + +// static +void LLTexLayerSetBuffer::dumpTotalByteCount() +{ + llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; +} + +void LLTexLayerSetBuffer::requestUpdate() +{ + restartUpdateTimer(); + mNeedsUpdate = TRUE; + mNumLowresUpdates = 0; + // If we're in the middle of uploading a baked texture, we don't care about it any more. + // When it's downloaded, ignore it. + mUploadID.setNull(); +} + +void LLTexLayerSetBuffer::requestUpload() +{ + conditionalRestartUploadTimer(); + mNeedsUpload = TRUE; + mNumLowresUploads = 0; + mUploadPending = TRUE; +} + +void LLTexLayerSetBuffer::conditionalRestartUploadTimer() +{ + // If we requested a new upload but haven't even uploaded + // a low res version of our last upload request, then + // keep the timer ticking instead of resetting it. + if (mNeedsUpload && (mNumLowresUploads == 0)) + { + mNeedsUploadTimer.unpause(); + } + else + { + mNeedsUploadTimer.reset(); + mNeedsUploadTimer.start(); + } +} + +void LLTexLayerSetBuffer::restartUpdateTimer() +{ + mNeedsUpdateTimer.reset(); + mNeedsUpdateTimer.start(); +} + +void LLTexLayerSetBuffer::cancelUpload() +{ + mNeedsUpload = FALSE; + mUploadPending = FALSE; + mNeedsUploadTimer.pause(); + mUploadRetryTimer.reset(); +} + +void LLTexLayerSetBuffer::pushProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); +} + +void LLTexLayerSetBuffer::popProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); +} + +// virtual +BOOL LLTexLayerSetBuffer::needsRender() +{ + llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp); + if (!isAgentAvatarValid()) return FALSE; + + const BOOL upload_now = mNeedsUpload && isReadyToUpload(); + const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); + + // Don't render if we don't want to (or aren't ready to) upload or update. + if (!(update_now || upload_now)) + { + return FALSE; + } + + // Don't render if we're animating our appearance. + if (gAgentAvatarp->getIsAppearanceAnimating()) + { + return FALSE; + } + + // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. + if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && + !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) + { + cancelUpload(); + return FALSE; + } + + // Render if we have at least minimal level of detail for each local texture. + return mTexLayerSet->isLocalTextureDataAvailable(); +} + +void LLTexLayerSetBuffer::preRender(BOOL clear_depth) +{ + // Set up an ortho projection + pushProjection(); + + // keep depth buffer, we don't need to clear it + LLViewerDynamicTexture::preRender(FALSE); +} + +void LLTexLayerSetBuffer::postRender(BOOL success) +{ + popProjection(); + + LLViewerDynamicTexture::postRender(success); +} + +BOOL LLTexLayerSetBuffer::render() +{ + // Default color mask for tex layer render + gGL.setColorMask(true, true); + + // do we need to upload, and do we have sufficient data to create an uploadable composite? + // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero? + const BOOL upload_now = mNeedsUpload && isReadyToUpload(); + const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); + + BOOL success = TRUE; + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + if (use_shaders) + { + gAlphaMaskProgram.bind(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + LLVertexBuffer::unbind(); + + // Composite the color data + LLGLSUIDefault gls_ui; + success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); + gGL.flush(); + + if(upload_now) + { + if (!success) + { + llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegionName() << llendl; + mUploadPending = FALSE; + } + else + { + if (mTexLayerSet->isVisible()) + { + mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. + doUpload(); + } + else + { + mUploadPending = FALSE; + mNeedsUpload = FALSE; + mNeedsUploadTimer.pause(); + mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE); + } + } + } + + if (update_now) + { + doUpdate(); + } + + if (use_shaders) + { + gAlphaMaskProgram.unbind(); + } + + LLVertexBuffer::unbind(); + + // reset GL state + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + // we have valid texture data now + mGLTexturep->setGLTextureCreated(true); + + return success; +} + +BOOL LLTexLayerSetBuffer::isInitialized(void) const +{ + return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); +} + +BOOL LLTexLayerSetBuffer::uploadPending() const +{ + return mUploadPending; +} + +BOOL LLTexLayerSetBuffer::uploadNeeded() const +{ + return mNeedsUpload; +} + +BOOL LLTexLayerSetBuffer::uploadInProgress() const +{ + return !mUploadID.isNull(); +} + +BOOL LLTexLayerSetBuffer::isReadyToUpload() const +{ + if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. + if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. + + BOOL ready = FALSE; + if (mTexLayerSet->isLocalTextureDataFinal()) + { + // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) + if (mUploadFailCount == 0) + { + ready = TRUE; + } + else + { + ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1)); + } + } + else + { + // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure + // we aren't doing uploads too frequently. + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); + if (texture_timeout != 0) + { + // The timeout period increases exponentially between every lowres upload in order to prevent + // spamming the server with frequent uploads. + const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads); + + // If we hit our timeout and have textures available at even lower resolution, then upload. + const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; + const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); + ready = has_lower_lod && is_upload_textures_timeout; + } + } + + return ready; +} + +BOOL LLTexLayerSetBuffer::isReadyToUpdate() const +{ + // If we requested an update and have the final LOD ready, then update. + if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; + + // If we haven't done an update yet, then just do one now regardless of state of textures. + if (mNumLowresUpdates == 0) return TRUE; + + // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small + // since render unnecessarily doesn't cost much. + const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedLocalTextureUpdateTimeout"); + if (texture_timeout != 0) + { + // If we hit our timeout and have textures available at even lower resolution, then update. + const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; + const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); + if (has_lower_lod && is_update_textures_timeout) return TRUE; + } + + return FALSE; +} + +BOOL LLTexLayerSetBuffer::requestUpdateImmediate() +{ + mNeedsUpdate = TRUE; + BOOL result = FALSE; + + if (needsRender()) + { + preRender(FALSE); + result = render(); + postRender(result); + } + + return result; +} + +// Create the baked texture, send it out to the server, then wait for it to come +// back so we can switch to using it. +void LLTexLayerSetBuffer::doUpload() +{ + llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); + + // Don't need caches since we're baked now. (note: we won't *really* be baked + // until this image is sent to the server and the Avatar Appearance message is received.) + mTexLayerSet->deleteCaches(); + + // Get the COLOR information from our texture + U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; + glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); + stop_glerror(); + + // Get the MASK information from our texture + LLGLSUIDefault gls_ui; + LLPointer baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); + U8* baked_mask_data = baked_mask_image->getData(); + mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); + + + // Create the baked image from our color and mask information + const S32 baked_image_components = 5; // red green blue [bump] clothing + LLPointer baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); + U8* baked_image_data = baked_image->getData(); + S32 i = 0; + for (S32 u=0; u < mFullWidth; u++) + { + for (S32 v=0; v < mFullHeight; v++) + { + baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; + baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; + baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; + baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. + baked_image_data[5*i + 4] = baked_mask_data[i]; + i++; + } + } + + LLPointer compressedImage = new LLImageJ2C; + const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) + if (compressedImage->encode(baked_image, comment_text)) + { + LLTransactionID tid; + tid.generate(); + const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), + gVFS, asset_id, LLAssetType::AT_TEXTURE)) + { + // Read back the file and validate. + BOOL valid = FALSE; + LLPointer integrity_test = new LLImageJ2C; + S32 file_size = 0; + U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size); + if (data) + { + valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' + } + else + { + integrity_test->setLastError("Unable to read entire file"); + } + + if (valid) + { + const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + // Baked_upload_data is owned by the responder and deleted after the request completes. + LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, + this->mTexLayerSet, + asset_id, + highest_lod); + // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. + mUploadID = asset_id; + + // Upload the image + const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); + if(!url.empty() + && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method + && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. + { + LLSD body = LLSD::emptyMap(); + // The responder will call LLTexLayerSetBuffer::onTextureUploadComplete() + LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); + llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; + } + else + { + gAssetStorage->storeAssetData(tid, + LLAssetType::AT_TEXTURE, + LLTexLayerSetBuffer::onTextureUploadComplete, + baked_upload_data, + TRUE, // temp_file + TRUE, // is_priority + TRUE); // store_local + llinfos << "Baked texture upload via Asset Store." << llendl; + } + + if (highest_lod) + { + // Sending the final LOD for the baked texture. All done, pause + // the upload timer so we know how long it took. + mNeedsUpload = FALSE; + mNeedsUploadTimer.pause(); + } + else + { + // Sending a lower level LOD for the baked texture. Restart the upload timer. + mNumLowresUploads++; + mNeedsUploadTimer.unpause(); + mNeedsUploadTimer.reset(); + } + + // Print out notification that we uploaded this texture. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); + args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); + args["RESOLUTION"] = lod_str; + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); + LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + } + } + else + { + // The read back and validate operation failed. Remove the uploaded file. + mUploadPending = FALSE; + LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); + file.remove(); + llinfos << "Unable to create baked upload file (reason: corrupted)." << llendl; + } + } + } + else + { + // The VFS write file operation failed. + mUploadPending = FALSE; + llinfos << "Unable to create baked upload file (reason: failed to write file)" << llendl; + } + + delete [] baked_color_data; +} + +// Mostly bookkeeping; don't need to actually "do" anything since +// render() will actually do the update. +void LLTexLayerSetBuffer::doUpdate() +{ + const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + if (highest_lod) + { + mNeedsUpdate = FALSE; + } + else + { + mNumLowresUpdates++; + } + + restartUpdateTimer(); + + // need to switch to using this layerset if this is the first update + // after getting the lowest LOD + mTexLayerSet->getAvatarAppearance()->updateMeshTextures(); + + // Print out notification that we updated this texture. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatarAppearance()->debugGetExistenceTimeElapsedF32()); + args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); + args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); + args["RESOLUTION"] = lod_str; + LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); + LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + } +} + +// static +void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (not fixed) +{ + LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata; + + if (isAgentAvatarValid() && + !gAgentAvatarp->isDead() && + (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures. + (baked_upload_data->mTexLayerSet->hasComposite())) + { + LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); + S32 failures = layerset_buffer->mUploadFailCount; + layerset_buffer->mUploadFailCount = 0; + + if (layerset_buffer->mUploadID.isNull()) + { + // The upload got canceled, we should be in the + // process of baking a new texture so request an + // upload with the new data + + // BAP: does this really belong in this callback, as + // opposed to where the cancellation takes place? + // suspect this does nothing. + layerset_buffer->requestUpload(); + } + else if (baked_upload_data->mID == layerset_buffer->mUploadID) + { + // This is the upload we're currently waiting for. + layerset_buffer->mUploadID.setNull(); + const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName()); + const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res "; + if (result >= 0) + { + layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later + LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); + // Update baked texture info with the new UUID + U64 now = LLFrameTimer::getTotalTime(); // Record starting time + llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; + gAgentAvatarp->setNewBakedTexture(baked_te, uuid); + } + else + { + ++failures; + S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes + llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl; + if (failures < max_attempts) + { + layerset_buffer->mUploadFailCount = failures; + layerset_buffer->mUploadRetryTimer.start(); + layerset_buffer->requestUpload(); + } + } + } + else + { + llinfos << "Received baked texture out of date, ignored." << llendl; + } + + gAgentAvatarp->dirtyMesh(); + } + else + { + // Baked texture failed to upload (in which case since we + // didn't set the new baked texture, it means that they'll try + // and rebake it at some point in the future (after login?)), + // or this response to upload is out of date, in which case a + // current response should be on the way or already processed. + llwarns << "Baked upload failed" << llendl; + } + + delete baked_upload_data; +} + + + + diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h new file mode 100644 index 0000000000..ff3def5a82 --- /dev/null +++ b/indra/newview/llviewertexlayer.h @@ -0,0 +1,172 @@ +/** + * @file llviewertexlayer.h + * @brief Viewer Texture layer classes. Used for avatars. + * + * $LicenseInfo:firstyear=2012&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_VIEWER_TEXLAYER_H +#define LL_VIEWER_TEXLAYER_H + +#include "lldynamictexture.h" +#include "lltexlayer.h" + +class LLTexLayerSetBuffer; +class LLVOAvatarSelf; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLViewerTexLayerSet +// +// An ordered set of texture layers that gets composited into a single texture. +// Only exists for llavatarappearanceself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLViewerTexLayerSet : public LLTexLayerSet +{ + friend class LLTexLayerSetBuffer; +public: + LLViewerTexLayerSet(LLAvatarAppearance* const appearance); + virtual ~LLViewerTexLayerSet(); + + LLTexLayerSetBuffer* getComposite(); + const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. + virtual void requestUpdate(); + void requestUpload(); + void cancelUpload(); + void updateComposite(); + BOOL isLocalTextureDataAvailable() const; + BOOL isLocalTextureDataFinal() const; + void createComposite(); + void destroyComposite(); + void setUpdatesEnabled(BOOL b); + BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } + void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); + + LLVOAvatarSelf* getAvatar() const; + BOOL hasComposite() const { return (mComposite.notNull()); } + +private: + LLPointer mComposite; + BOOL mUpdatesEnabled; + +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSetBuffer +// +// The composite image that a LLViewerTexLayerSet writes to. Each LLTexLayerSet has one. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSetBuffer : public LLViewerDynamicTexture +{ + LOG_CLASS(LLTexLayerSetBuffer); + +public: + LLTexLayerSetBuffer(LLViewerTexLayerSet* const owner, S32 width, S32 height); + virtual ~LLTexLayerSetBuffer(); + +public: + /*virtual*/ S8 getType() const; + BOOL isInitialized(void) const; + static void dumpTotalByteCount(); + const std::string dumpTextureInfo() const; + virtual void restoreGLTexture(); + virtual void destroyGLTexture(); +protected: + void pushProjection() const; + void popProjection() const; +private: + LLViewerTexLayerSet* const mTexLayerSet; + static S32 sGLByteCount; + + //-------------------------------------------------------------------- + // Render + //-------------------------------------------------------------------- +public: + /*virtual*/ BOOL needsRender(); +protected: + BOOL render(S32 x, S32 y, S32 width, S32 height); + virtual void preRender(BOOL clear_depth); + virtual void postRender(BOOL success); + virtual BOOL render(); + + //-------------------------------------------------------------------- + // Uploads + //-------------------------------------------------------------------- +public: + void requestUpload(); + void cancelUpload(); + BOOL uploadNeeded() const; // We need to upload a new texture + BOOL uploadInProgress() const; // We have started uploading a new texture and are awaiting the result + BOOL uploadPending() const; // We are expecting a new texture to be uploaded at some point + static void onTextureUploadComplete(const LLUUID& uuid, + void* userdata, + S32 result, LLExtStat ext_status); +protected: + BOOL isReadyToUpload() const; + void doUpload(); // Does a read back and upload. + void conditionalRestartUploadTimer(); +private: + BOOL mNeedsUpload; // Whether we need to send our baked textures to the server + U32 mNumLowresUploads; // Number of times we've sent a lowres version of our baked textures to the server + BOOL mUploadPending; // Whether we have received back the new baked textures + LLUUID mUploadID; // The current upload process (null if none). + LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed. + S32 mUploadFailCount; // Number of consecutive upload failures + LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure. + + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- +public: + void requestUpdate(); + BOOL requestUpdateImmediate(); +protected: + BOOL isReadyToUpdate() const; + void doUpdate(); + void restartUpdateTimer(); +private: + BOOL mNeedsUpdate; // Whether we need to locally update our baked textures + U32 mNumLowresUpdates; // Number of times we've locally updated with lowres version of our baked textures + LLFrameTimer mNeedsUpdateTimer; // Tracks time since update was requested and performed. +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLBakedUploadData +// +// Used by LLTexLayerSetBuffer for a callback. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +struct LLBakedUploadData +{ + LLBakedUploadData(const LLVOAvatarSelf* avatar, + LLViewerTexLayerSet* layerset, + const LLUUID& id, + bool highest_res); + ~LLBakedUploadData() {} + const LLUUID mID; + const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer + LLViewerTexLayerSet* mTexLayerSet; + const U64 mStartTime; // for measuring baked texture upload time + const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res +}; + +#endif // LL_VIEWER_TEXLAYER_H + diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8eb8717de2..c362269b81 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -59,6 +59,7 @@ #include "lltextureatlas.h" #include "lltextureatlasmanager.h" #include "lltextureentry.h" +#include "lltexturemanagerbridge.h" #include "llmediaentry.h" #include "llvovolume.h" #include "llviewermedia.h" @@ -305,6 +306,26 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const return gTextureList.getImageFromHost(image_id, host) ; } +// Create a bridge to the viewer texture manager. +class LLViewerTextureManagerBridge : public LLTextureManagerBridge +{ + /*virtual*/ LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(usemipmaps, generate_gl_tex); + } + + /*virtual*/ LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(width, height, components, usemipmaps, generate_gl_tex); + } + + /*virtual*/ LLTexture* getFetchedTexture(const LLUUID &image_id) + { + return LLViewerTextureManager::getFetchedTexture(image_id); + } +}; + + void LLViewerTextureManager::init() { { @@ -374,6 +395,9 @@ void LLViewerTextureManager::init() LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); LLViewerTexture::initClass() ; + + // Create a texture manager bridge. + gTextureManagerBridgep = new LLViewerTextureManagerBridge(); if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) { @@ -390,6 +414,7 @@ void LLViewerTextureManager::cleanup() { stop_glerror(); + delete gTextureManagerBridgep; LLImageGL::sDefaultGLTexture = NULL ; LLViewerTexture::sNullImagep = NULL; LLViewerTexture::sBlackImagep = NULL; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 2ea9a07e9a..4b92a2bf8a 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -107,39 +107,6 @@ public: INVALID_TEXTURE_TYPE }; - enum EBoostLevel - { - BOOST_NONE = 0, - BOOST_AVATAR_BAKED , - BOOST_AVATAR , - BOOST_CLOUDS , - BOOST_SCULPTED , - - BOOST_HIGH = 10, - BOOST_BUMP , - BOOST_TERRAIN , // has to be high priority for minimap / low detail - BOOST_SELECTED , - BOOST_AVATAR_BAKED_SELF , - BOOST_AVATAR_SELF , // needed for baking avatar - BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. - BOOST_HUD , - BOOST_ICON , - BOOST_UI , - BOOST_PREVIEW , - BOOST_MAP , - BOOST_MAP_VISIBLE , - BOOST_MAX_LEVEL, - - //other texture Categories - LOCAL = BOOST_MAX_LEVEL, - AVATAR_SCRATCH_TEX, - DYNAMIC_TEX, - MEDIA, - ATLAS, - OTHER, - MAX_GL_IMAGE_CATEGORY - }; - static S32 getTotalNumOfCategories() ; static S32 getIndexFromCategory(S32 category) ; static S32 getCategoryFromIndex(S32 index) ; @@ -168,7 +135,7 @@ public: /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; - const LLUUID& getID() const { return mID; } + /*virtual*/ const LLUUID& getID() const { return mID; } void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } @@ -205,24 +172,24 @@ public: /*virtual*/S32 getWidth(S32 discard_level = -1) const; /*virtual*/S32 getHeight(S32 discard_level = -1) const; - BOOL hasGLTexture() const ; + /*virtual*/BOOL hasGLTexture() const ; LLGLuint getTexName() const ; BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER); + /*virtual*/ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLTexture::OTHER); virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; void setFilteringOption(LLTexUnit::eTextureFilterOptions option); - void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); - void setAddressMode(LLTexUnit::eTextureAddressMode mode); + /*virtual*/ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); + /*virtual*/ void setAddressMode(LLTexUnit::eTextureAddressMode mode); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); void setGLTextureCreated (bool initialized); void setCategory(S32 category) ; - LLTexUnit::eTextureAddressMode getAddressMode(void) const ; + /*virtual*/ LLTexUnit::eTextureAddressMode getAddressMode(void) const ; S32 getMaxDiscardLevel() const; S32 getDiscardLevel() const; - S8 getComponents() const ; + /*virtual*/ S8 getComponents() const; BOOL getBoundRecently() const; S32 getTextureMemory() const ; LLGLenum getPrimaryFormat() const; @@ -761,6 +728,7 @@ public: static void init() ; static void cleanup() ; }; + // //this class is used for test/debug only //it tracks the activities of the texture pipeline diff --git a/indra/newview/llviewervisualparam.cpp b/indra/newview/llviewervisualparam.cpp deleted file mode 100644 index f0cf9b7692..0000000000 --- a/indra/newview/llviewervisualparam.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file llviewervisualparam.cpp - * @brief Implementation of LLViewerVisualParam class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" - -#include "llviewervisualparam.h" -#include "llxmltree.h" -#include "llui.h" -#include "llwearable.h" - -//----------------------------------------------------------------------------- -// LLViewerVisualParamInfo() -//----------------------------------------------------------------------------- -LLViewerVisualParamInfo::LLViewerVisualParamInfo() - : - mWearableType( LLWearableType::WT_INVALID ), - mCrossWearable(FALSE), - mCamDist( 0.5f ), - mCamAngle( 0.f ), - mCamElevation( 0.f ), - mEditGroupDisplayOrder( 0 ), - mShowSimple(FALSE), - mSimpleMin(0.f), - mSimpleMax(100.f) -{ -} - -LLViewerVisualParamInfo::~LLViewerVisualParamInfo() -{ -} - -//----------------------------------------------------------------------------- -// parseXml() -//----------------------------------------------------------------------------- -BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) -{ - llassert( node->hasName( "param" ) ); - - if (!LLVisualParamInfo::parseXml(node)) - return FALSE; - - // VIEWER SPECIFIC PARAMS - - std::string wearable; - static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable"); - if( node->getFastAttributeString( wearable_string, wearable) ) - { - mWearableType = LLWearableType::typeNameToType( wearable ); - } - - static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); - if (!node->getFastAttributeString( edit_group_string, mEditGroup)) - { - mEditGroup = ""; - } - - static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); - if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable)) - { - mCrossWearable = FALSE; - } - - // Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). - static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance"); - node->getFastAttributeF32( camera_distance_string, mCamDist ); - static LLStdStringHandle camera_angle_string = LLXmlTree::addAttributeString("camera_angle"); - node->getFastAttributeF32( camera_angle_string, mCamAngle ); // in degrees - static LLStdStringHandle camera_elevation_string = LLXmlTree::addAttributeString("camera_elevation"); - node->getFastAttributeF32( camera_elevation_string, mCamElevation ); - - mCamAngle += 180; - - static S32 params_loaded = 0; - - // By default, parameters are displayed in the order in which they appear in the xml file. - // "edit_group_order" overriddes. - static LLStdStringHandle edit_group_order_string = LLXmlTree::addAttributeString("edit_group_order"); - if( !node->getFastAttributeF32( edit_group_order_string, mEditGroupDisplayOrder ) ) - { - mEditGroupDisplayOrder = (F32)params_loaded; - } - - params_loaded++; - - return TRUE; -} - -/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out) -{ - LLVisualParamInfo::toStream(out); - - out << mWearableType << "\t"; - out << mEditGroup << "\t"; - out << mEditGroupDisplayOrder << "\t"; -} - -//----------------------------------------------------------------------------- -// LLViewerVisualParam() -//----------------------------------------------------------------------------- -LLViewerVisualParam::LLViewerVisualParam() -{ -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- - -BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight(), FALSE ); - return TRUE; -} - -/* -//============================================================================= -// These virtual functions should always be overridden, -// but are included here for use as templates -//============================================================================= - -//----------------------------------------------------------------------------- -// parseData() -//----------------------------------------------------------------------------- -BOOL LLViewerVisualParam::parseData(LLXmlTreeNode *node) -{ - LLViewerVisualParamInfo* info = new LLViewerVisualParamInfo; - - info->parseXml(node); - if (!setInfo(info)) - return FALSE; - - return TRUE; -} -*/ diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h deleted file mode 100644 index 3bc95cbfbf..0000000000 --- a/indra/newview/llviewervisualparam.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file llviewervisualparam.h - * @brief viewer side visual params (with data file parsing) - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLViewerVisualParam_H -#define LL_LLViewerVisualParam_H - -#include "v3math.h" -#include "llstring.h" -#include "llvisualparam.h" - -class LLWearable; - -//----------------------------------------------------------------------------- -// LLViewerVisualParamInfo -//----------------------------------------------------------------------------- -class LLViewerVisualParamInfo : public LLVisualParamInfo -{ - friend class LLViewerVisualParam; -public: - LLViewerVisualParamInfo(); - /*virtual*/ ~LLViewerVisualParamInfo(); - - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - - /*virtual*/ void toStream(std::ostream &out); - -protected: - S32 mWearableType; - BOOL mCrossWearable; - std::string mEditGroup; - F32 mCamDist; - F32 mCamAngle; // degrees - F32 mCamElevation; - F32 mEditGroupDisplayOrder; - BOOL mShowSimple; // show edit controls when in "simple ui" mode? - F32 mSimpleMin; // when in simple UI, apply this minimum, range 0.f to 100.f - F32 mSimpleMax; // when in simple UI, apply this maximum, range 0.f to 100.f -}; - -//----------------------------------------------------------------------------- -// LLViewerVisualParam -// VIRTUAL CLASS -// a viewer side interface class for a generalized parametric modification of the avatar mesh -//----------------------------------------------------------------------------- -class LLViewerVisualParam : public LLVisualParam -{ -public: - LLViewerVisualParam(); - /*virtual*/ ~LLViewerVisualParam(){}; - - // Special: These functions are overridden by child classes - LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; }; - // This sets mInfo and calls initialization functions - BOOL setInfo(LLViewerVisualParamInfo *info); - - virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - - // New Virtual functions - virtual F32 getTotalDistortion() = 0; - virtual const LLVector4a& getAvgDistortion() = 0; - virtual F32 getMaxDistortion() = 0; - virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; - virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; - virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; - - // interface methods - F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } - S32 getWearableType() const { return getInfo()->mWearableType; } - const std::string& getEditGroup() const { return getInfo()->mEditGroup; } - - F32 getCameraDistance() const { return getInfo()->mCamDist; } - F32 getCameraAngle() const { return getInfo()->mCamAngle; } // degrees - F32 getCameraElevation() const { return getInfo()->mCamElevation; } - - BOOL getShowSimple() const { return getInfo()->mShowSimple; } - F32 getSimpleMin() const { return getInfo()->mSimpleMin; } - F32 getSimpleMax() const { return getInfo()->mSimpleMax; } - - BOOL getCrossWearable() const { return getInfo()->mCrossWearable; } - -}; - -#endif // LL_LLViewerVisualParam_H diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp new file mode 100644 index 0000000000..b63f1f57cb --- /dev/null +++ b/indra/newview/llviewerwearable.cpp @@ -0,0 +1,900 @@ +/** + * @file llviewerwearable.cpp + * @brief LLViewerWearable class implementation + * + * $LicenseInfo:firstyear=2012&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 "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llfloatersidepanelcontainer.h" +#include "llnotificationsutil.h" +#include "llsidepanelappearance.h" +#include "lltextureentry.h" +#include "llviewercontrol.h" +#include "llviewertexlayer.h" +#include "llviewerwearable.h" +#include "llvoavatarself.h" +#include "llvoavatardefines.h" + +using namespace LLVOAvatarDefines; + +// support class - remove for 2.1 (hackity hack hack) +class LLOverrideBakedTextureUpdate +{ +public: + LLOverrideBakedTextureUpdate(bool temp_state) + { + U32 num_bakes = (U32) LLVOAvatarDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); + } + gAgentAvatarp->setCompositeUpdatesEnabled(temp_state); + } + + ~LLOverrideBakedTextureUpdate() + { + U32 num_bakes = (U32)LLVOAvatarDefines::BAKED_NUM_INDICES; + for( U32 index = 0; index < num_bakes; ++index ) + { + gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); + } + } +private: + bool composite_enabled[LLVOAvatarDefines::BAKED_NUM_INDICES]; +}; + +// Private local functions +static std::string asset_id_to_filename(const LLUUID &asset_id); + +LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id) : + LLWearable() +{ + mTransactionID = transaction_id; + mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); +} + +LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id) : + LLWearable() +{ + mAssetID = asset_id; + mTransactionID.setNull(); +} + +// virtual +LLViewerWearable::~LLViewerWearable() +{ +} + +void LLViewerWearable::setItemID(const LLUUID& item_id) +{ + mItemID = item_id; +} + +// virtual +BOOL LLViewerWearable::exportFile(LLFILE* file) const +{ + mTextureIDMap.clear(); + for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + const LLUUID& image_id = iter->second->getID(); + mTextureIDMap[te] = image_id; + } + return LLWearable::exportFile(file); +} + +// virtual +LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file ) +{ + // suppress texlayerset updates while wearables are being imported. Layersets will be updated + // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. + LLOverrideBakedTextureUpdate stop_bakes(false); + + LLWearable::EImportResult result = LLWearable::importFile(file); + if (LLWearable::FAILURE == result) return result; + if (LLWearable::BAD_HEADER == result) + { + // Shouldn't really log the asset id for security reasons, but + // we need it in this case. + llwarns << "Bad Wearable asset header: " << mAssetID << llendl; + //gVFS->dumpMap(); + return result; + } + + LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); + LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); + + texture_id_map_t::const_iterator iter = mTextureIDMap.begin(); + texture_id_map_t::const_iterator end = mTextureIDMap.end(); + for (; iter != end; ++iter) + { + S32 te = iter->first; + const LLUUID& textureid = iter->second; + if( mTEMap.find(te) != mTEMap.end() ) + { + delete mTEMap[te]; + } + if( mSavedTEMap.find(te) != mSavedTEMap.end() ) + { + delete mSavedTEMap[te]; + } + + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( textureid ); + if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) + { + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLVOAvatarDefines::ETextureIndex)te), NULL); + } + mTEMap[te] = new LLLocalTextureObject(image, textureid); + mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); + createLayers(te); + } + + // copy all saved param values to working params + revertValues(); + + return result; +} + +// Avatar parameter and texture definitions can change over time. +// This function returns true if parameters or textures have been added or removed +// since this wearable was created. +BOOL LLViewerWearable::isOldVersion() const +{ + if (!isAgentAvatarValid()) return FALSE; + + if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion ) + { + llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; + llassert(0); + } + + if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion ) + { + return TRUE; + } + + S32 param_count = 0; + for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) && (param->isTweakable() ) ) + { + param_count++; + if( !is_in_map(mVisualParamIndexMap, param->getID() ) ) + { + return TRUE; + } + } + } + if( param_count != mVisualParamIndexMap.size() ) + { + return TRUE; + } + + + S32 te_count = 0; + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_count++; + if( !is_in_map(mTEMap, te ) ) + { + return TRUE; + } + } + } + if( te_count != mTEMap.size() ) + { + return TRUE; + } + + return FALSE; +} + +// Avatar parameter and texture definitions can change over time. +// * If parameters or textures have been REMOVED since the wearable was created, +// they're just ignored, so we consider the wearable clean even though isOldVersion() +// will return true. +// * If parameters or textures have been ADDED since the wearable was created, +// they are taken to have default values, so we consider the wearable clean +// only if those values are the same as the defaults. +BOOL LLViewerWearable::isDirty() const +{ + if (!isAgentAvatarValid()) return FALSE; + + for( LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) + && (param->isTweakable() ) + && !param->getCrossWearable()) + { + F32 current_weight = getVisualParamWeight(param->getID()); + current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() ); + F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight()); + saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() ); + + U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() ); + U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() ); + if( a != b ) + { + return TRUE; + } + } + } + + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator current_iter = mTEMap.find(te); + if(current_iter != mTEMap.end()) + { + const LLUUID& current_image_id = current_iter->second->getID(); + te_map_t::const_iterator saved_iter = mSavedTEMap.find(te); + if(saved_iter != mSavedTEMap.end()) + { + const LLUUID& saved_image_id = saved_iter->second->getID(); + if (saved_image_id != current_image_id) + { + // saved vs current images are different, wearable is dirty + return TRUE; + } + } + else + { + // image found in current image list but not saved image list + return TRUE; + } + } + } + } + + return FALSE; +} + + +void LLViewerWearable::setParamsToDefaults() +{ + if (!isAgentAvatarValid()) return; + + for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + { + if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->isTweakable() ) ) + { + setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE); + } + } +} + +void LLViewerWearable::setTexturesToDefaults() +{ + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + LLUUID id = getDefaultTextureImageID((ETextureIndex) te); + LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); + if( mTEMap.find(te) == mTEMap.end() ) + { + mTEMap[te] = new LLLocalTextureObject(image, id); + createLayers(te); + } + else + { + // Local Texture Object already created, just set image and UUID + LLLocalTextureObject *lto = mTEMap[te]; + lto->setID(id); + lto->setImage(image); + } + } + } +} + + +//static +const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) +{ + const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const std::string &default_image_name = texture_dict->mDefaultImageName; + if (default_image_name == "") + { + return IMG_DEFAULT_AVATAR; + } + else + { + return LLUUID(gSavedSettings.getString(default_image_name)); + } +} + + +// Updates the user's avatar's appearance +void LLViewerWearable::writeToAvatar() +{ + if (!isAgentAvatarValid()) return; + + ESex old_sex = gAgentAvatarp->getSex(); + + // Pull params + for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + { + // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the + // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. + if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) + { + S32 param_id = param->getID(); + F32 weight = getVisualParamWeight(param_id); + + gAgentAvatarp->setVisualParamWeight( param_id, weight, FALSE ); + } + } + + // Pull texture entries + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = mTEMap.find(te); + LLUUID image_id; + if(iter != mTEMap.end()) + { + image_id = iter->second->getID(); + } + else + { + image_id = getDefaultTextureImageID((ETextureIndex) te); + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. + gAgentAvatarp->setLocalTextureTE(te, image, 0); + } + } + + ESex new_sex = gAgentAvatarp->getSex(); + if( old_sex != new_sex ) + { + gAgentAvatarp->updateSexDependentLayerSets( FALSE ); + } + +// if( upload_bake ) +// { +// gAgent.sendAgentSetAppearance(); +// } +} + + +// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. +// static +void LLViewerWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ) +{ + if (!isAgentAvatarValid()) return; + + // You can't just remove body parts. + if( (type == LLWearableType::WT_SHAPE) || + (type == LLWearableType::WT_SKIN) || + (type == LLWearableType::WT_HAIR) || + (type == LLWearableType::WT_EYES) ) + { + return; + } + + // Pull params + for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam() ) + { + if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->isTweakable() ) ) + { + S32 param_id = param->getID(); + gAgentAvatarp->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake ); + } + } + + if(gAgentCamera.cameraCustomizeAvatar()) + { + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); + } + + gAgentAvatarp->updateVisualParams(); + gAgentAvatarp->wearableUpdated(type, FALSE); + +// if( upload_bake ) +// { +// gAgent.sendAgentSetAppearance(); +// } +} + +// Does not copy mAssetID. +// Definition version is current: removes obsolete enties and creates default values for new ones. +void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) +{ + if (!isAgentAvatarValid()) return; + + mDefinitionVersion = LLWearable::sCurrentDefinitionVersion; + + mName = src->mName; + mDescription = src->mDescription; + mPermissions = src->mPermissions; + mSaleInfo = src->mSaleInfo; + + setType(src->mType); + + mSavedVisualParamMap.clear(); + // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam() ) + { + if( (param->getWearableType() == mType) ) + { + S32 id = param->getID(); + F32 weight = src->getVisualParamWeight(id); + mSavedVisualParamMap[id] = weight; + } + } + + destroyTextures(); + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + for (S32 te = 0; te < TEX_NUM_INDICES; te++) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src->mTEMap.find(te); + LLUUID image_id; + LLViewerFetchedTexture *image = NULL; + if(iter != src->mTEMap.end()) + { + image = dynamic_cast (src->getLocalTextureObject(te)->getImage()); + image_id = src->getLocalTextureObject(te)->getID(); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + mTEMap[te]->setBakedReady(src->getLocalTextureObject(te)->getBakedReady()); + mTEMap[te]->setDiscard(src->getLocalTextureObject(te)->getDiscard()); + } + else + { + image_id = getDefaultTextureImageID((ETextureIndex) te); + image = LLViewerTextureManager::getFetchedTexture( image_id ); + mTEMap[te] = new LLLocalTextureObject(image, image_id); + mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); + } + createLayers(te); + } + } + + // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable + // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) + revertValues(); +} + + +LLLocalTextureObject* LLViewerWearable::getLocalTextureObject(S32 index) +{ + te_map_t::iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +const LLLocalTextureObject* LLViewerWearable::getLocalTextureObject(S32 index) const +{ + te_map_t::const_iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + const LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +std::vector LLViewerWearable::getLocalTextureListSeq() +{ + std::vector result; + + for(te_map_t::const_iterator iter = mTEMap.begin(); + iter != mTEMap.end(); iter++) + { + LLLocalTextureObject* lto = iter->second; + result.push_back(lto); + } + + return result; +} + +void LLViewerWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) +{ + if( mTEMap.find(index) != mTEMap.end() ) + { + mTEMap.erase(index); + } + mTEMap[index] = new LLLocalTextureObject(lto); +} + +void LLViewerWearable::revertValues() +{ + //update saved settings so wearable is no longer dirty + // non-driver params first + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && !dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + //then driver params + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + // make sure that saved values are sane + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *param = getVisualParam(id); + if( param ) + { + mSavedVisualParamMap[id] = param->getWeight(); + } + } + + syncImages(mSavedTEMap, mTEMap); + + + LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + } +} + +BOOL LLViewerWearable::isOnTop() const +{ + return (this == gAgentWearables.getTopWearable(mType)); +} + +void LLViewerWearable::saveValues() +{ + //update saved settings so wearable is no longer dirty + mSavedVisualParamMap.clear(); + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + mSavedVisualParamMap[id] = value; + } + + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + syncImages(mTEMap, mSavedTEMap); + + + LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); + if( panel ) + { + panel->updateScrollingPanelList(); + } +} + +void LLViewerWearable::syncImages(te_map_t &src, te_map_t &dst) +{ + // Deep copy of src (copies only those tes that are current, filling in defaults where needed) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src.find(te); + LLUUID image_id; + LLViewerFetchedTexture *image = NULL; + LLLocalTextureObject *lto = NULL; + if(iter != src.end()) + { + // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. + lto = iter->second; + image = dynamic_cast (lto->getImage()); + image_id = lto->getID(); + } + else + { + // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. + image_id = getDefaultTextureImageID((ETextureIndex) te); + image = LLViewerTextureManager::getFetchedTexture( image_id ); + } + + if( dst.find(te) != dst.end() ) + { + // there's already an entry in the destination map for the texture. Just update its values. + dst[te]->setImage(image); + dst[te]->setID(image_id); + } + else + { + // no entry found in the destination map, we need to create a new Local Texture Object + dst[te] = new LLLocalTextureObject(image, image_id); + } + + if( lto ) + { + // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. + dst[te]->setBakedReady(lto->getBakedReady()); + dst[te]->setDiscard(lto->getDiscard()); + } + } + } +} + +void LLViewerWearable::destroyTextures() +{ + for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mTEMap.clear(); + for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mSavedTEMap.clear(); +} + +void LLViewerWearable::pullCrossWearableValues() +{ + // scan through all of the avatar's visual parameters + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) + { + if( param ) + { + LLDriverParam *driver_param = dynamic_cast(param); + if(driver_param) + { + // parameter is a driver parameter, have it update its + driver_param->updateCrossDrivenParams(getType()); + } + } + } +} + + +void LLViewerWearable::setLabelUpdated() const +{ + gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); +} + + +void LLViewerWearable::refreshName() +{ + LLUUID item_id = getItemID(); + LLInventoryItem* item = gInventory.getItem(item_id); + if( item ) + { + mName = item->getName(); + } +} + +struct LLWearableSaveData +{ + LLWearableType::EType mType; +}; + +void LLViewerWearable::saveNewAsset() const +{ +// llinfos << "LLViewerWearable::saveNewAsset() type: " << getTypeName() << llendl; + //llinfos << *this << llendl; + + const std::string filename = asset_id_to_filename(mAssetID); + LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ + BOOL successful_save = FALSE; + if(fp && exportFile(fp)) + { + successful_save = TRUE; + } + if(fp) + { + fclose(fp); + fp = NULL; + } + if(!successful_save) + { + std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str()); + llwarns << buffer << llendl; + + LLSD args; + args["NAME"] = mName; + LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args); + return; + } + + // save it out to database + if( gAssetStorage ) + { + /* + std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + if (!url.empty()) + { + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); + body["asset_type"] = LLAssetType::lookup(getAssetType()); + body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); + body["name"] = getName(); + body["description"] = getDescription(); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); + } + else + { + } + */ + LLWearableSaveData* data = new LLWearableSaveData; + data->mType = mType; + gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), + &LLViewerWearable::onSaveNewAssetComplete, + (void*)data); + } +} + +// static +void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ + LLWearableSaveData* data = (LLWearableSaveData*)userdata; + const std::string& type_name = LLWearableType::getTypeName(data->mType); + if(0 == status) + { + // Success + llinfos << "Saved wearable " << type_name << llendl; + } + else + { + std::string buffer = llformat("Unable to save %s to central asset store.", type_name.c_str()); + llwarns << buffer << " Status: " << status << llendl; + LLSD args; + args["NAME"] = type_name; + LLNotificationsUtil::add("CannotSaveToAssetStore", args); + } + + // Delete temp file + const std::string src_filename = asset_id_to_filename(new_asset_id); + LLFile::remove(src_filename); + + // delete the context data + delete data; + +} + +void LLViewerWearable::createLayers(S32 te) +{ + LLViewerTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); + if (layer_set) + { + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + } + else + { + llerrs << "could not find layerset for LTO in wearable!" << llendl; + } +} + +void LLViewerWearable::createVisualParams() +{ + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) + { + if (param->getWearableType() == mType) + { + addVisualParam(param->cloneParam(this)); + } + } + + // resync driver parameters to point to the newly cloned driven parameters + for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) + { + LLVisualParam* param = param_iter->second; + LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; + // need this line to disambiguate between versions of LLCharacter::getVisualParam() + LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; + param->resetDrivenParams(); + if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + { + if( !param->linkDrivenParams(boost::bind(param_function,gAgentAvatarp.get(),_1 ), true)) + { + llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; + continue; + } + } + } +} + +void LLViewerWearable::setVisualParams() +{ + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + gAgentAvatarp->setVisualParamWeight(id, value, FALSE); + } +} + + + +std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) +{ + s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; + s << " Name: " << w.mName << "\n"; + s << " Desc: " << w.mDescription << "\n"; + //w.mPermissions + //w.mSaleInfo + + s << " Params:" << "\n"; + for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); + iter != w.mVisualParamIndexMap.end(); ++iter) + { + S32 param_id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 param_weight = wearable_param->getWeight(); + s << " " << param_id << " " << param_weight << "\n"; + } + + s << " Textures:" << "\n"; + for (LLViewerWearable::te_map_t::const_iterator iter = w.mTEMap.begin(); + iter != w.mTEMap.end(); ++iter) + { + S32 te = iter->first; + const LLUUID& image_id = iter->second->getID(); + s << " " << te << " " << image_id << "\n"; + } + return s; +} + +std::string asset_id_to_filename(const LLUUID &asset_id) +{ + std::string asset_id_string; + asset_id.toString(asset_id_string); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl"; + return filename; +} + diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h new file mode 100644 index 0000000000..857900f583 --- /dev/null +++ b/indra/newview/llviewerwearable.h @@ -0,0 +1,116 @@ +/** + * @file llviewerwearable.h + * @brief LLViewerWearable class header file + * + * $LicenseInfo:firstyear=2012&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_VIEWER_WEARABLE_H +#define LL_VIEWER_WEARABLE_H + +#include "llwearable.h" +#include "llvoavatardefines.h" + +class LLViewerWearable : public LLWearable +{ + friend class LLWearableList; + + //-------------------------------------------------------------------- + // Constructors and destructors + //-------------------------------------------------------------------- +private: + // Private constructors used by LLViewerWearableList + LLViewerWearable(const LLTransactionID& transactionID); + LLViewerWearable(const LLAssetID& assetID); +public: + virtual ~LLViewerWearable(); + + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + const LLUUID& getItemID() const { return mItemID; } + const LLAssetID& getAssetID() const { return mAssetID; } + const LLTransactionID& getTransactionID() const { return mTransactionID; } + void setItemID(const LLUUID& item_id); + +public: + /*virtual*/ BOOL exportFile(LLFILE* file) const; + /*virtual*/ EImportResult importFile(LLFILE* file); + + BOOL isDirty() const; + BOOL isOldVersion() const; + + /*virtual*/ void writeToAvatar(); + void removeFromAvatar( BOOL upload_bake ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); } + static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); + + void setParamsToDefaults(); + void setTexturesToDefaults(); + + static const LLUUID getDefaultTextureImageID(LLVOAvatarDefines::ETextureIndex index); + + + void saveNewAsset() const; + static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); + + void copyDataFrom(const LLViewerWearable* src); + + friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w); + + /*virtual*/ LLLocalTextureObject* getLocalTextureObject(S32 index); + const LLLocalTextureObject* getLocalTextureObject(S32 index) const; + std::vector getLocalTextureListSeq(); + void setLocalTextureObject(S32 index, LLLocalTextureObject <o); + + void revertValues(); + void saveValues(); + void pullCrossWearableValues(); + + BOOL isOnTop() const; + + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). + void setLabelUpdated() const; + + // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, + // not the wearable asset itself. + void refreshName(); + +protected: + void createLayers(S32 te); + /*virtual*/void createVisualParams(); + void setVisualParams(); + + typedef std::map te_map_t; + void syncImages(te_map_t &src, te_map_t &dst); + void destroyTextures(); + LLTransactionID mTransactionID; + LLAssetID mAssetID; + LLUUID mItemID; // ID of the inventory item in the agent's inventory + + te_map_t mTEMap; // maps TE to LocalTextureObject + te_map_t mSavedTEMap; // last saved version of TEMap +}; + + +#endif // LL_VIEWER_WEARABLE_H + diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4894f21e67..dac479b2e0 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -77,15 +77,16 @@ #include "llselectmgr.h" #include "llsprite.h" #include "lltargetingmotion.h" -#include "lltexlayer.h" #include "lltoolmorph.h" #include "llviewercamera.h" +#include "llviewertexlayer.h" #include "llviewertexturelist.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewershadermgr.h" #include "llviewerstats.h" +#include "llviewerwearable.h" #include "llvoavatarself.h" #include "llvovolume.h" #include "llworld.h" @@ -192,8 +193,6 @@ const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; -const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); - enum ERenderName { RENDER_NAME_NEVER, @@ -645,8 +644,8 @@ static F32 calc_bouncy_animation(F32 x); LLVOAvatar::LLVOAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLAvatarAppearance(), LLViewerObject(id, pcode, regionp), - mIsDummy(FALSE), mSpecialRenderMode(0), mAttachmentGeometryBytes(0), mAttachmentSurfaceArea(0.f), @@ -678,9 +677,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFirstAppearanceMessageReceived( FALSE ), mCulled( FALSE ), mVisibilityRank(0), - mTexSkinColor( NULL ), - mTexHairColor( NULL ), - mTexEyeColor( NULL ), mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), @@ -768,7 +764,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthTimer.reset(); mRuthDebugTimer.reset(); - mDebugExistenceTimer.reset(); mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); mLastPelvisToFoot = 0.0f; mPelvisFixup = 0.0f; @@ -1133,7 +1128,7 @@ void LLVOAvatar::resetImpostors() // static void LLVOAvatar::deleteCachedImages(bool clearAll) { - if (LLTexLayerSet::sHasCaches) + if (LLViewerTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; for (std::vector::iterator iter = LLCharacter::sInstances.begin(); @@ -1142,7 +1137,7 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->deleteLayerSetCaches(clearAll); } - LLTexLayerSet::sHasCaches = FALSE; + LLViewerTexLayerSet::sHasCaches = FALSE; } LLVOAvatarSelf::deleteScratchTextures(); LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); @@ -5864,6 +5859,30 @@ void LLVOAvatar::updateVisualParams() updateHeadOffset(); } +// virtual +U32 LLVOAvatar::getWearableCount(const LLWearableType::EType type) const +{ + return gAgentWearables.getWearableCount(type); +} + +// virtual +U32 LLVOAvatar::getWearableCount(const U32 tex_index) const +{ + return gAgentWearables.getWearableCount(tex_index); +} + +// virtual +LLWearable* LLVOAvatar::getWearable(const LLWearableType::EType type, U32 index /*= 0*/) +{ + return gAgentWearables.getWearable(type, index); +} + +// virtual +const LLWearable* LLVOAvatar::getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const +{ + return gAgentWearables.getWearable(type, index); +} + //----------------------------------------------------------------------------- // isActive() //----------------------------------------------------------------------------- @@ -6453,26 +6472,6 @@ S32 LLVOAvatar::getAttachmentCount() return count; } -LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const -{ - if (color_name=="skin_color" && mTexSkinColor) - { - return mTexSkinColor->getColor(); - } - else if(color_name=="hair_color" && mTexHairColor) - { - return mTexHairColor->getColor(); - } - if(color_name=="eye_color" && mTexEyeColor) - { - return mTexEyeColor->getColor(); - } - else - { -// return LLColor4( .5f, .5f, .5f, .5f ); - return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color - } -} // virtual void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) @@ -6483,6 +6482,7 @@ void LLVOAvatar::invalidateAll() { } +// virtual void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake ) { if (global_color == mTexSkinColor) @@ -6682,6 +6682,7 @@ LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const // updateMeshTextures() // Uses the current TE values to set the meshes' and layersets' textures. //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::updateMeshTextures() { // llinfos << "updateMeshTextures" << llendl; @@ -6903,7 +6904,7 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde { if (isSelf()) { - LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet; + LLViewerTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet; if (layer_set) { return !layer_set->isMorphValid(); @@ -6973,112 +6974,6 @@ void LLVOAvatar::releaseComponentTextures() } } -//static -BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name ) -{ - switch( te ) - { - case TEX_UPPER_SHIRT: - param_name[0] = 803; //"shirt_red"; - param_name[1] = 804; //"shirt_green"; - param_name[2] = 805; //"shirt_blue"; - break; - - case TEX_LOWER_PANTS: - param_name[0] = 806; //"pants_red"; - param_name[1] = 807; //"pants_green"; - param_name[2] = 808; //"pants_blue"; - break; - - case TEX_LOWER_SHOES: - param_name[0] = 812; //"shoes_red"; - param_name[1] = 813; //"shoes_green"; - param_name[2] = 817; //"shoes_blue"; - break; - - case TEX_LOWER_SOCKS: - param_name[0] = 818; //"socks_red"; - param_name[1] = 819; //"socks_green"; - param_name[2] = 820; //"socks_blue"; - break; - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - param_name[0] = 834; //"jacket_red"; - param_name[1] = 835; //"jacket_green"; - param_name[2] = 836; //"jacket_blue"; - break; - - case TEX_UPPER_GLOVES: - param_name[0] = 827; //"gloves_red"; - param_name[1] = 829; //"gloves_green"; - param_name[2] = 830; //"gloves_blue"; - break; - - case TEX_UPPER_UNDERSHIRT: - param_name[0] = 821; //"undershirt_red"; - param_name[1] = 822; //"undershirt_green"; - param_name[2] = 823; //"undershirt_blue"; - break; - - case TEX_LOWER_UNDERPANTS: - param_name[0] = 824; //"underpants_red"; - param_name[1] = 825; //"underpants_green"; - param_name[2] = 826; //"underpants_blue"; - break; - - case TEX_SKIRT: - param_name[0] = 921; //"skirt_red"; - param_name[1] = 922; //"skirt_green"; - param_name[2] = 923; //"skirt_blue"; - break; - - case TEX_HEAD_TATTOO: - case TEX_LOWER_TATTOO: - case TEX_UPPER_TATTOO: - param_name[0] = 1071; //"tattoo_red"; - param_name[1] = 1072; //"tattoo_green"; - param_name[2] = 1073; //"tattoo_blue"; - break; - - default: - llassert(0); - return FALSE; - } - - return TRUE; -} - -void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) -{ - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake ); - setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake ); - setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake ); - } -} - -LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) -{ - LLColor4 color; - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - color.mV[VX] = getVisualParamWeight( param_name[0] ); - color.mV[VY] = getVisualParamWeight( param_name[1] ); - color.mV[VZ] = getVisualParamWeight( param_name[2] ); - } - return color; -} - -// static -LLColor4 LLVOAvatar::getDummyColor() -{ - return DUMMY_COLOR; -} - void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; @@ -8787,7 +8682,7 @@ BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 ind } //virtual -BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const { // non-self avatars don't have wearables return FALSE; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 3f65dec11c..023711d81b 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -25,8 +25,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLVOAVATAR_H -#define LL_LLVOAVATAR_H +#ifndef LL_VOAVATAR_H +#define LL_VOAVATAR_H #include #include @@ -36,6 +36,7 @@ #include #include "imageids.h" // IMG_INVISIBLE +#include "llavatarappearance.h" #include "llchat.h" #include "lldrawpoolalpha.h" #include "llviewerobject.h" @@ -62,7 +63,8 @@ extern const LLUUID ANIM_AGENT_PELVIS_FIX; extern const LLUUID ANIM_AGENT_TARGET; extern const LLUUID ANIM_AGENT_WALK_ADJUST; -class LLTexLayerSet; +class LLViewerTexLayerSet; +class LLViewerWearable; class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; @@ -75,8 +77,8 @@ class LLVOAvatarSkeletonInfo; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLVOAvatar : + public LLAvatarAppearance, public LLViewerObject, - public LLCharacter, public boost::signals2::trackable { LOG_CLASS(LLVOAvatar); @@ -222,8 +224,20 @@ public: public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + /*virtual*/BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode bool isBuilt() const { return mIsBuilt; } +/******************************************************************************** + ** ** + ** WEARABLES + **/ +public: + /*virtual*/ U32 getWearableCount(const LLWearableType::EType type) const; + /*virtual*/ U32 getWearableCount(const U32 tex_index) const; + + /*virtual*/ LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); + /*virtual*/ const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; + private: //aligned members LL_ALIGN_16(LLVector4a mImpostorExtents[2]); @@ -440,7 +454,7 @@ public: static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); - BOOL mIsDummy; // for special views + BOOL mIsDummy; // for special views S32 mSpecialRenderMode; // special lighting U32 mAttachmentGeometryBytes; //number of bytes in attached geometry F32 mAttachmentSurfaceArea; //estimated surface area of attachments @@ -460,7 +474,14 @@ private: public: BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); //-------------------------------------------------------------------- // Visibility @@ -563,7 +584,7 @@ public: public: virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; + virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const; BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); @@ -586,7 +607,7 @@ protected: struct BakedTextureData { LLUUID mLastTextureIndex; - LLTexLayerSet* mTexLayerSet; // Only exists for self + LLViewerTexLayerSet* mTexLayerSet; // Only exists for self bool mIsLoaded; bool mIsUsed; LLVOAvatarDefines::ETextureIndex mTextureIndex; @@ -668,15 +689,15 @@ private: **/ public: - void updateMeshTextures(); + virtual void updateMeshTextures(); void updateSexDependentLayerSets(BOOL upload_bake); - void dirtyMesh(); // Dirty the avatar mesh + virtual void dirtyMesh(); // Dirty the avatar mesh void updateMeshData(); protected: void releaseMeshData(); virtual void restoreMeshData(); private: - void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + virtual void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD BOOL mMeshTexturesDirty; @@ -710,7 +731,6 @@ public: //-------------------------------------------------------------------- public: BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } - BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode private: BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; @@ -719,25 +739,6 @@ private: BOOL mUseLocalAppearance; // flag for if we're using a local composite BOOL mUseServerBakes; // flag for if baked textures should be fetched from baking service (false if they're temporary uploads) - //-------------------------------------------------------------------- - // Clothing colors (convenience functions to access visual parameters) - //-------------------------------------------------------------------- -public: - void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); - LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); - static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); - - //-------------------------------------------------------------------- - // Global colors - //-------------------------------------------------------------------- -public: - LLColor4 getGlobalColor(const std::string& color_name ) const; - void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); -private: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; - //-------------------------------------------------------------------- // Visibility //-------------------------------------------------------------------- @@ -746,7 +747,6 @@ public: void setVisibilityRank(U32 rank); U32 getVisibilityRank() const { return mVisibilityRank; } // unused static S32 sNumVisibleAvatars; // Number of instances of this class - static LLColor4 getDummyColor(); /** Appearance ** ** *******************************************************************************/ @@ -1038,11 +1038,9 @@ private: //-------------------------------------------------------------------- public: void debugAvatarRezTime(std::string notification_name, std::string comment = ""); - F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez - LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. /** Diagnostics ** ** @@ -1163,4 +1161,5 @@ protected: // Shared with LLVOAvatarSelf extern const F32 SELF_ADDITIONAL_PRI; extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; -#endif // LL_VO_AVATAR_H +#endif // LL_VOAVATAR_H + diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp deleted file mode 100644 index ef96a9e923..0000000000 --- a/indra/newview/llvoavatardefines.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/** - * @file llvoavatar.cpp - * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llvoavatardefines.h" -#include "llviewercontrol.h" // gSavedSettings - -const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; -const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; -const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; - -using namespace LLVOAvatarDefines; - -/********************************************************************************* - * Edit this function to add/remove/change textures and mesh definitions for avatars. - */ - -LLVOAvatarDictionary::Textures::Textures() -{ - addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); - addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); - addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); - addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); - addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); - addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); - addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); - addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); - addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); - addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); - - addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - - addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); -} - -LLVOAvatarDictionary::BakedTextures::BakedTextures() -{ - // Baked textures - addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, - "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", - 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, - 5, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, - "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", - 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, - TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, - 8, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, - "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", - 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, - TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, - 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, - "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", - 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, - 2, LLWearableType::WT_EYES, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, - "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", - 1, TEX_SKIRT, - 1, LLWearableType::WT_SKIRT)); - - addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, - "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", - 2, TEX_HAIR, TEX_HAIR_ALPHA, - 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); -} - -LLVOAvatarDictionary::Meshes::Meshes() -{ - // Meshes - addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4)); - addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5)); - addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0)); // no baked mesh associated currently - addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1)); - addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2)); - addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3)); - addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3)); - addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5)); -} - -/* - * - *********************************************************************************/ - -LLVOAvatarDictionary::LLVOAvatarDictionary() -{ - createAssociations(); -} - -//virtual -LLVOAvatarDictionary::~LLVOAvatarDictionary() -{ -} - -// Baked textures are composites of textures; for each such composited texture, -// map it to the baked texture. -void LLVOAvatarDictionary::createAssociations() -{ - for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) - { - const EBakedTextureIndex baked_index = (iter->first); - const BakedEntry *dict = (iter->second); - - // For each texture that this baked texture index affects, associate those textures - // with this baked texture index. - for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); - local_texture_iter != dict->mLocalTextures.end(); - local_texture_iter++) - { - const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; - mTextures[local_texture_index]->mIsUsedByBakedTexture = true; - mTextures[local_texture_index]->mBakedTextureIndex = baked_index; - } - } - -} - -LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name, - bool is_local_texture, - EBakedTextureIndex baked_texture_index, - const std::string &default_image_name, - LLWearableType::EType wearable_type) : - LLDictionaryEntry(name), - mIsLocalTexture(is_local_texture), - mIsBakedTexture(!is_local_texture), - mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), - mBakedTextureIndex(baked_texture_index), - mDefaultImageName(default_image_name), - mWearableType(wearable_type) -{ -} - -LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, - U8 level, - LLViewerJoint::PickName pick) : - LLDictionaryEntry(name), - mBakedID(baked_index), - mLOD(level), - mPickName(pick) -{ -} -LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, - const std::string &name, - const std::string &hash_name, - U32 num_local_textures, - ... ) : - LLDictionaryEntry(name), - mWearablesHashID(LLUUID(hash_name)), - mTextureIndex(tex_index) -{ - va_list argp; - - va_start(argp, num_local_textures); - - // Read in local textures - for (U8 i=0; i < num_local_textures; i++) - { - ETextureIndex t = (ETextureIndex)va_arg(argp,int); - mLocalTextures.push_back(t); - } - - // Read in number of wearables - const U32 num_wearables = (U32)va_arg(argp,int); - // Read in wearables - for (U8 i=0; i < num_wearables; i++) - { - LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); - mWearables.push_back(t); - } -} - -// static -ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) -{ - return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; -} - -//static -EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) -{ - U8 index = 0; - while (index < BAKED_NUM_INDICES) - { - const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); - if (be && be->mName.compare(name) == 0) - { - // baked texture found - return (EBakedTextureIndex) index; - } - index++; - } - // baked texture could not be found - return BAKED_NUM_INDICES; -} - -//static -const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index) -{ - const TextureEntry *texture_dict = getInstance()->getTexture(index); - const std::string &default_image_name = texture_dict->mDefaultImageName; - if (default_image_name == "") - { - return IMG_DEFAULT_AVATAR; - } - else - { - return LLUUID(gSavedSettings.getString(default_image_name)); - } -} - -// static -LLWearableType::EType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index ) -{ - return getInstance()->getTexture(index)->mWearableType; -} - diff --git a/indra/newview/llvoavatardefines.h b/indra/newview/llvoavatardefines.h deleted file mode 100644 index 35bb37463a..0000000000 --- a/indra/newview/llvoavatardefines.h +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @file llvoavatar.h - * @brief Declaration of LLVOAvatar class which is a derivation fo - * LLViewerObject - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLVOAVATAR_DEFINES_H -#define LLVOAVATAR_DEFINES_H - -#include -#include "llwearable.h" -#include "llviewerjoint.h" -#include "lldictionary.h" - -namespace LLVOAvatarDefines -{ - -extern const S32 SCRATCH_TEX_WIDTH; -extern const S32 SCRATCH_TEX_HEIGHT; -extern const S32 IMPOSTOR_PERIOD; - -//-------------------------------------------------------------------- -// Enums -//-------------------------------------------------------------------- -enum ETextureIndex -{ - TEX_HEAD_BODYPAINT = 0, - TEX_UPPER_SHIRT, - TEX_LOWER_PANTS, - TEX_EYES_IRIS, - TEX_HAIR, - TEX_UPPER_BODYPAINT, - TEX_LOWER_BODYPAINT, - TEX_LOWER_SHOES, - TEX_HEAD_BAKED, // Pre-composited - TEX_UPPER_BAKED, // Pre-composited - TEX_LOWER_BAKED, // Pre-composited - TEX_EYES_BAKED, // Pre-composited - TEX_LOWER_SOCKS, - TEX_UPPER_JACKET, - TEX_LOWER_JACKET, - TEX_UPPER_GLOVES, - TEX_UPPER_UNDERSHIRT, - TEX_LOWER_UNDERPANTS, - TEX_SKIRT, - TEX_SKIRT_BAKED, // Pre-composited - TEX_HAIR_BAKED, // Pre-composited - TEX_LOWER_ALPHA, - TEX_UPPER_ALPHA, - TEX_HEAD_ALPHA, - TEX_EYES_ALPHA, - TEX_HAIR_ALPHA, - TEX_HEAD_TATTOO, - TEX_UPPER_TATTOO, - TEX_LOWER_TATTOO, - TEX_NUM_INDICES -}; - -enum EBakedTextureIndex -{ - BAKED_HEAD = 0, - BAKED_UPPER, - BAKED_LOWER, - BAKED_EYES, - BAKED_SKIRT, - BAKED_HAIR, - BAKED_NUM_INDICES -}; - -// Reference IDs for each mesh. Used as indices for vector of joints -enum EMeshIndex -{ - MESH_ID_HAIR = 0, - MESH_ID_HEAD, - MESH_ID_EYELASH, - MESH_ID_UPPER_BODY, - MESH_ID_LOWER_BODY, - MESH_ID_EYEBALL_LEFT, - MESH_ID_EYEBALL_RIGHT, - MESH_ID_SKIRT, - MESH_ID_NUM_INDICES -}; - -//-------------------------------------------------------------------- -// Vector Types -//-------------------------------------------------------------------- -typedef std::vector texture_vec_t; -typedef std::vector bakedtexture_vec_t; -typedef std::vector mesh_vec_t; -typedef std::vector wearables_vec_t; - -//------------------------------------------------------------------------ -// LLVOAvatarDictionary -// -// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. -// information that is common to all avatars. -// -// This holds const data - it is initialized once and the contents never change after that. -//------------------------------------------------------------------------ -class LLVOAvatarDictionary : public LLSingleton -{ - //-------------------------------------------------------------------- - // Constructors and Destructors - //-------------------------------------------------------------------- -public: - LLVOAvatarDictionary(); - virtual ~LLVOAvatarDictionary(); -private: - void createAssociations(); - - //-------------------------------------------------------------------- - // Local and baked textures - //-------------------------------------------------------------------- -public: - struct TextureEntry : public LLDictionaryEntry - { - TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml - bool is_local_texture, - EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, - const std::string& default_image_name = "", - LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); - const std::string mDefaultImageName; - const LLWearableType::EType mWearableType; - // It's either a local texture xor baked - BOOL mIsLocalTexture; - BOOL mIsBakedTexture; - // If it's a local texture, it may be used by a baked texture - BOOL mIsUsedByBakedTexture; - EBakedTextureIndex mBakedTextureIndex; - }; - - struct Textures : public LLDictionary - { - Textures(); - } mTextures; - const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } - const Textures& getTextures() const { return mTextures; } - - //-------------------------------------------------------------------- - // Meshes - //-------------------------------------------------------------------- -public: - struct MeshEntry : public LLDictionaryEntry - { - MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, // names of mesh types as they are used in avatar_lad.xml - U8 level, - LLViewerJoint::PickName pick); - // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml - // Otherwise meshes will be unable to be found, or levels of detail will be ignored - const U8 mLOD; - const EBakedTextureIndex mBakedID; - const LLViewerJoint::PickName mPickName; - }; - - struct Meshes : public LLDictionary - { - Meshes(); - } mMeshes; - const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } - const Meshes& getMeshes() const { return mMeshes; } - - //-------------------------------------------------------------------- - // Baked Textures - //-------------------------------------------------------------------- -public: - struct BakedEntry : public LLDictionaryEntry - { - BakedEntry(ETextureIndex tex_index, - const std::string &name, // unused, but necessary for templating. - const std::string &hash_name, - U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list - // Local Textures - const ETextureIndex mTextureIndex; - texture_vec_t mLocalTextures; - // Wearables - const LLUUID mWearablesHashID; - wearables_vec_t mWearables; - }; - - struct BakedTextures: public LLDictionary - { - BakedTextures(); - } mBakedTextures; - const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } - const BakedTextures& getBakedTextures() const { return mBakedTextures; } - - //-------------------------------------------------------------------- - // Convenience Functions - //-------------------------------------------------------------------- -public: - // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED - static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t); - - // find a baked texture index based on its name - static EBakedTextureIndex findBakedByRegionName(std::string name); - - static const LLUUID getDefaultTextureImageID(ETextureIndex index); - - // Given a texture entry, determine which wearable type owns it. - static LLWearableType::EType getTEWearableType(ETextureIndex index); - -}; // End LLVOAvatarDictionary - -} // End namespace LLVOAvatarDefines - -#endif //LL_VO_AVATARDEFINES_H diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 3604a373ad..0fcf43a501 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -55,6 +55,8 @@ #include "llviewerobjectlist.h" #include "llviewerstats.h" #include "llviewerregion.h" +#include "llviewertexlayer.h" +#include "llviewerwearable.h" #include "llappearancemgr.h" #include "llmeshrepository.h" #include "llvovolume.h" @@ -595,7 +597,7 @@ BOOL LLVOAvatarSelf::loadLayersets() { // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. const LLTexLayerSetInfo *info = *iter; - LLTexLayerSet* layer_set = new LLTexLayerSet( this ); + LLViewerTexLayerSet* layer_set = new LLViewerTexLayerSet( this ); if (!layer_set->setInfo(info)) { @@ -734,7 +736,7 @@ BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL U32 size = gAgentWearables.getWearableCount(type); for (U32 count = 0; count < size; ++count) { - LLWearable *wearable = gAgentWearables.getWearable(type,count); + LLViewerWearable *wearable = gAgentWearables.getWearable(type,count); if (wearable) { wearable->setVisualParamWeight(param->getID(), weight, upload_bake); @@ -760,7 +762,7 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation() // apply wearable visual params to avatar for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) { - LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); + LLViewerWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); if (wearable) { wearable->writeToAvatar(); @@ -1375,7 +1377,7 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex { return FALSE; } - *tex_pp = local_tex_obj->getImage(); + *tex_pp = dynamic_cast (local_tex_obj->getImage()); return TRUE; } @@ -1395,7 +1397,7 @@ LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETe { return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); } - return local_tex_obj->getImage(); + return dynamic_cast (local_tex_obj->getImage()); } const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const @@ -1416,7 +1418,7 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c // Returns true if at least the lowest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const +BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const { /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ @@ -1454,7 +1456,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) // Returns true if the highest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) const +BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const { const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels. @@ -1515,7 +1517,7 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const { - const LLTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; + const LLViewerTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; if (!layerset) return FALSE; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) return FALSE; @@ -1568,7 +1570,7 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 } //virtual -BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const +BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const { if (isIndexBakedTexture(type)) { @@ -1611,7 +1613,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - LLTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; + LLViewerTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; if (layerset && layerset->getComposite() && layerset->getComposite()->uploadPending()) { return true; @@ -1620,7 +1622,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const return false; } -void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) +void LLVOAvatarSelf::invalidateComposite( LLViewerTexLayerSet* layerset, BOOL upload_result ) { if( !layerset || !layerset->getUpdatesEnabled() ) { @@ -1712,11 +1714,12 @@ S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index); if (local_tex_obj) { + const LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); if (type >= 0 && local_tex_obj->getID() != IMG_DEFAULT_AVATAR - && !local_tex_obj->getImage()->isMissingAsset()) + && !image->isMissingAsset()) { - return local_tex_obj->getImage()->getDiscardLevel(); + return image->getDiscardLevel(); } else { @@ -1741,7 +1744,7 @@ void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); if (local_tex_obj) { - const LLViewerFetchedTexture* image_gl = local_tex_obj->getImage(); + const LLViewerFetchedTexture* image_gl = dynamic_cast( local_tex_obj->getImage() ); if (image_gl) { S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); @@ -1790,7 +1793,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te return; } - LLTexLayerSet *layer_set = getLayerSet(type); + LLViewerTexLayerSet *layer_set = getLayerSet(type); if (layer_set) { layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index)); @@ -1814,15 +1817,15 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te if (isSelf()) { if (gAgentAvatarp->isUsingBakedTextures()) - { - requestLayerSetUpdate(type); - } + { + requestLayerSetUpdate(type); + } else - { - LLVisualParamHint::requestHintUpdates(); + { + LLVisualParamHint::requestHintUpdates(); + } } } - } else { tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); @@ -1887,7 +1890,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const } else { - const LLViewerFetchedTexture* image = local_tex_obj->getImage(); + const LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -2060,7 +2063,7 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); } -const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const +const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; @@ -2283,7 +2286,7 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) { - LLWearable *wearable = gAgentWearables.getWearable(wearable_type, wearable_index); + LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, wearable_index); if (wearable) { const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); @@ -2358,7 +2361,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const { LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); - LLWearable* wearable = gAgentWearables.getWearable(type, wearable_index); + LLViewerWearable* wearable = gAgentWearables.getWearable(type, wearable_index); if (wearable) { return wearable->getLocalTextureObject(i); @@ -2371,7 +2374,7 @@ LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::E // getBakedTE() // Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) //----------------------------------------------------------------------------- -ETextureIndex LLVOAvatarSelf::getBakedTE( const LLTexLayerSet* layerset ) const +ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset ) const { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { @@ -2512,7 +2515,7 @@ void LLVOAvatarSelf::outputRezDiagnostics() const ++baked_iter) { const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLTexLayerSet *layerset = debugGetLayerSet(baked_index); + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) continue; @@ -2590,7 +2593,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) { if (texture_id == gAgentAvatarp->getTEImage(index)->getID()) { - LLTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index); + LLViewerTexLayerSet* layer_set = gAgentAvatarp->getLayerSet(index); if (layer_set) { llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; @@ -2622,7 +2625,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; - LLTexLayerSet* layer_set = getLayerSet(baked_index); + LLViewerTexLayerSet* layer_set = getLayerSet(baked_index); if (layer_set) { if (slam_for_debug) @@ -2664,7 +2667,7 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) } } -LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const +LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const { /* switch(index) case TEX_HEAD_BAKED: @@ -2679,7 +2682,7 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const return NULL; } -LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const +LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const { /* switch(index) case TEX_HEAD_BAKED: diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 92d59dc9e1..26662e8a25 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -197,13 +197,13 @@ public: /*virtual*/ bool hasPendingBakedUploads() const; S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const; bool areTexturesCurrent() const; - BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const; - BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const; + BOOL isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const; + BOOL isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const; BOOL isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const; // If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const; /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; + /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const; //-------------------------------------------------------------------- @@ -233,7 +233,7 @@ private: // Baked textures //-------------------------------------------------------------------- public: - LLVOAvatarDefines::ETextureIndex getBakedTE(const LLTexLayerSet* layerset ) const; + LLVOAvatarDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const; void setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid); void setNewBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); void setCachedBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); @@ -249,14 +249,14 @@ public: void requestLayerSetUploads(); void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + LLViewerTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; + LLViewerTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- // Composites //-------------------------------------------------------------------- public: - /* virtual */ void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); + /* virtual */ void invalidateComposite(LLViewerTexLayerSet* layerset, BOOL upload_result); /* virtual */ void invalidateAll(); /* virtual */ void setCompositeUpdatesEnabled(bool b); // only works for self /* virtual */ void setCompositeUpdatesEnabled(U32 index, bool b); @@ -388,8 +388,8 @@ public: BOOL isAllLocalTextureDataFinal() const; - const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } - const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer + const LLViewerTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } + const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD LLSD metricsData(); void sendAppearanceChangeMetrics(); // send data associated with completing a change. diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 6f6411ce3c..9f04fbecf0 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -42,7 +42,7 @@ struct LLWearableArrivedData { LLWearableArrivedData(LLAssetType::EType asset_type, const std::string& wearable_name, - void(*asset_arrived_callback)(LLWearable*, void* userdata), + void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata) : mAssetType( asset_type ), mCallback( asset_arrived_callback ), @@ -52,7 +52,7 @@ struct LLWearableArrivedData {} LLAssetType::EType mAssetType; - void (*mCallback)(LLWearable*, void* userdata); + void (*mCallback)(LLViewerWearable*, void* userdata); void* mUserdata; std::string mName; S32 mRetries; @@ -72,10 +72,10 @@ void LLWearableList::cleanup() mList.clear(); } -void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata) +void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata) { llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) ); - LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL ); + LLViewerWearable* instance = get_if_there(mList, assetID, (LLViewerWearable*)NULL ); if( instance ) { asset_arrived_callback( instance, userdata ); @@ -95,7 +95,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID { BOOL isNewWearable = FALSE; LLWearableArrivedData* data = (LLWearableArrivedData*) userdata; - LLWearable* wearable = NULL; // NULL indicates failure + LLViewerWearable* wearable = NULL; // NULL indicates failure if( !filename ) { @@ -111,7 +111,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID } else { - wearable = new LLWearable(uuid); + wearable = new LLViewerWearable(uuid); bool res = wearable->importFile( fp ); if (!res) { @@ -203,11 +203,11 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID } -LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name) +LLViewerWearable* LLWearableList::createCopy(const LLViewerWearable* old_wearable, const std::string& new_name) { lldebugs << "LLWearableList::createCopy()" << llendl; - LLWearable *wearable = generateNewWearable(); + LLViewerWearable *wearable = generateNewWearable(); wearable->copyDataFrom(old_wearable); LLPermissions perm(old_wearable->getPermissions()); @@ -222,11 +222,11 @@ LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std return wearable; } -LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) +LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) { lldebugs << "LLWearableList::createNewWearable()" << llendl; - LLWearable *wearable = generateNewWearable(); + LLViewerWearable *wearable = generateNewWearable(); wearable->setType( type ); std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) ); @@ -251,13 +251,13 @@ LLWearable* LLWearableList::createNewWearable( LLWearableType::EType type ) return wearable; } -LLWearable *LLWearableList::generateNewWearable() +LLViewerWearable *LLWearableList::generateNewWearable() { LLTransactionID tid; tid.generate(); LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - LLWearable* wearable = new LLWearable(tid); + LLViewerWearable* wearable = new LLViewerWearable(tid); mList[new_asset_id] = wearable; return wearable; } diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index 12d0037aee..0f3078facf 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -28,7 +28,7 @@ #define LL_LLWEARABLELIST_H #include "llmemory.h" -#include "llwearable.h" +#include "llviewerwearable.h" #include "lluuid.h" #include "llassetstorage.h" @@ -51,19 +51,19 @@ public: void getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, - void(*asset_arrived_callback)(LLWearable*, void* userdata), + void(*asset_arrived_callback)(LLViewerWearable*, void* userdata), void* userdata); - LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string()); - LLWearable* createNewWearable(LLWearableType::EType type); + LLViewerWearable* createCopy(const LLViewerWearable* old_wearable, const std::string& new_name = std::string()); + LLViewerWearable* createNewWearable(LLWearableType::EType type); // Callback static void processGetAssetReply(const char* filename, const LLAssetID& assetID, void* user_data, S32 status, LLExtStat ext_status); protected: - LLWearable* generateNewWearable(); // used for the create... functions + LLViewerWearable* generateNewWearable(); // used for the create... functions private: - std::map mList; + std::map mList; }; #endif // LL_LLWEARABLELIST_H diff --git a/indra/newview/llwearabletype.cpp b/indra/newview/llwearabletype.cpp deleted file mode 100644 index c090ab5c3d..0000000000 --- a/indra/newview/llwearabletype.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @file llwearabletype.cpp - * @brief LLWearableType class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llwearabletype.h" -#include "llinventoryfunctions.h" -#include "lltrans.h" - -struct WearableEntry : public LLDictionaryEntry -{ - WearableEntry(const std::string &name, - const std::string& default_new_name, - LLAssetType::EType assetType, - LLInventoryIcon::EIconName iconName, - BOOL disable_camera_switch = FALSE, - BOOL allow_multiwear = TRUE) : - LLDictionaryEntry(name), - mAssetType(assetType), - mDefaultNewName(default_new_name), - mLabel(LLTrans::getString(name)), - mIconName(iconName), - mDisableCameraSwitch(disable_camera_switch), - mAllowMultiwear(allow_multiwear) - { - - } - const LLAssetType::EType mAssetType; - const std::string mLabel; - const std::string mDefaultNewName; //keep mLabel for backward compatibility - LLInventoryIcon::EIconName mIconName; - BOOL mDisableCameraSwitch; - BOOL mAllowMultiwear; -}; - -class LLWearableDictionary : public LLSingleton, - public LLDictionary -{ -public: - LLWearableDictionary(); -}; - -LLWearableDictionary::LLWearableDictionary() -{ - addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); - addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); - - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - - addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); - addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); -} - -// static -LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const LLWearableType::EType wearable = dict->lookup(type_name); - return wearable; -} - -// static -const std::string& LLWearableType::getTypeName(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return getTypeName(WT_INVALID); - return entry->mName; -} - -//static -const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return getTypeDefaultNewName(WT_INVALID); - return entry->mDefaultNewName; -} - -// static -const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return getTypeLabel(WT_INVALID); - return entry->mLabel; -} - -// static -LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return getAssetType(WT_INVALID); - return entry->mAssetType; -} - -// static -LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return getIconName(WT_INVALID); - return entry->mIconName; -} - -// static -BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return FALSE; - return entry->mDisableCameraSwitch; -} - -// static -BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) -{ - const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); - const WearableEntry *entry = dict->lookup(type); - if (!entry) return FALSE; - return entry->mAllowMultiwear; -} - diff --git a/indra/newview/llwearabletype.h b/indra/newview/llwearabletype.h deleted file mode 100644 index d633b4807e..0000000000 --- a/indra/newview/llwearabletype.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file llwearabletype.h - * @brief LLWearableType class header file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLWEARABLETYPE_H -#define LL_LLWEARABLETYPE_H - -#include "llassettype.h" -#include "lldictionary.h" -#include "llinventoryicon.h" -#include "llsingleton.h" - -class LLWearableType -{ -public: - enum EType - { - WT_SHAPE = 0, - WT_SKIN = 1, - WT_HAIR = 2, - WT_EYES = 3, - WT_SHIRT = 4, - WT_PANTS = 5, - WT_SHOES = 6, - WT_SOCKS = 7, - WT_JACKET = 8, - WT_GLOVES = 9, - WT_UNDERSHIRT = 10, - WT_UNDERPANTS = 11, - WT_SKIRT = 12, - WT_ALPHA = 13, - WT_TATTOO = 14, - WT_PHYSICS = 15, - WT_COUNT = 16, - - WT_INVALID = 255, - WT_NONE = -1, - }; - - static const std::string& getTypeName(EType type); - static const std::string& getTypeDefaultNewName(EType type); - static const std::string& getTypeLabel(EType type); - static LLAssetType::EType getAssetType(EType type); - static EType typeNameToType(const std::string& type_name); - static LLInventoryIcon::EIconName getIconName(EType type); - static BOOL getDisableCameraSwitch(EType type); - static BOOL getAllowMultiwear(EType type); - -protected: - LLWearableType() {} - ~LLWearableType() {} -}; - -#endif // LL_LLWEARABLETYPE_H -- cgit v1.2.3 From 1bd5fd8c50eb299ea96720db8cf0f9b25ec6e941 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Mon, 3 Sep 2012 07:00:56 +0000 Subject: Fixed typo in cmake file --- indra/llappearance/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index bc4748b87f..8d2334c566 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -59,7 +59,7 @@ set(llappearance_HEADER_FILES CMakeLists.txt llavatarappearance.h - llinventoryicon.cpp + llinventoryicon.h lljointpickname.h lllocaltextureobject.h lltexglobalcolor.h -- cgit v1.2.3 From 0c7623f628cbba999860379a2f5c302d94c1d287 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Mon, 3 Sep 2012 08:37:58 +0000 Subject: Cleanup of llappearance refactor file definition order for easier diff'ing --- indra/llappearance/llavatarappearance.cpp | 1 - indra/llappearance/llavatarappearance.h | 9 - indra/llappearance/lltexlayer.cpp | 7 - indra/llappearance/lltexlayerparams.cpp | 1 - indra/llappearance/llvoavatardefines.cpp | 3 - indra/llappearance/llvoavatardefines.h | 2 +- indra/llappearance/llwearable.cpp | 13 +- indra/llappearance/llwearable.h | 10 +- indra/llappearance/llwearabletype.cpp | 2 - indra/newview/llviewertexlayer.cpp | 280 ++++++++++++++++-------------- indra/newview/llviewertexlayer.h | 2 +- indra/newview/llviewerwearable.cpp | 134 +++++++------- indra/newview/llviewerwearable.h | 14 +- indra/newview/llvoavatar.cpp | 1 + indra/newview/llvoavatar.h | 3 + 15 files changed, 237 insertions(+), 245 deletions(-) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 1ca0161d7e..044ea8fbf0 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -38,7 +38,6 @@ LLAvatarAppearance::LLAvatarAppearance() : mTexEyeColor( NULL ), mIsDummy(FALSE) { - mDebugExistenceTimer.reset(); } using namespace LLVOAvatarDefines; diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index cb2ae7aeef..1b0e0ad270 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -111,15 +111,6 @@ public: virtual BOOL isWearingWearableType(LLWearableType::EType type ) const = 0; - //-------------------------------------------------------------------- - // Avatar Rez Metrics - //-------------------------------------------------------------------- -public: - F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } - -protected: - LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. - public: static LLColor4 getDummyColor(); virtual void updateMeshTextures() = 0; diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 3bb31d3721..6522976be1 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -33,20 +33,13 @@ #include "imageids.h" #include "llimagej2c.h" #include "llimagetga.h" -//#include "llnotificationsutil.h" #include "lldir.h" #include "llvfile.h" #include "llvfs.h" -//#include "llviewerstats.h" -//#include "llviewerregion.h" -//#include "pipeline.h" #include "lltexlayerparams.h" #include "lltexturemanagerbridge.h" #include "llui.h" -//#include "llagentwearables.h" #include "llwearable.h" -//#include "llviewercontrol.h" -//#include "llviewershadermgr.h" #include "llviewervisualparam.h" //#include "../tools/imdebug/imdebug.h" diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index c843367357..4f0456f315 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -29,7 +29,6 @@ #include "lltexlayerparams.h" #include "llavatarappearance.h" -//#include "llagentcamera.h" #include "llimagetga.h" #include "llquantize.h" #include "lltexlayer.h" diff --git a/indra/llappearance/llvoavatardefines.cpp b/indra/llappearance/llvoavatardefines.cpp index 48ef63ab64..29891986f5 100644 --- a/indra/llappearance/llvoavatardefines.cpp +++ b/indra/llappearance/llvoavatardefines.cpp @@ -24,11 +24,8 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" - #include "llvoavatardefines.h" -//#include "llviewercontrol.h" // gSavedSettings const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; diff --git a/indra/llappearance/llvoavatardefines.h b/indra/llappearance/llvoavatardefines.h index 7b0442bffb..7745775f9f 100644 --- a/indra/llappearance/llvoavatardefines.h +++ b/indra/llappearance/llvoavatardefines.h @@ -29,8 +29,8 @@ #define LLVOAVATAR_DEFINES_H #include -#include "lljointpickname.h" #include "llwearable.h" +#include "lljointpickname.h" #include "lldictionary.h" namespace LLVOAvatarDefines diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 64bd921ec5..77f1f27cb0 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -27,24 +27,12 @@ #include "linden_common.h" #include "llavatarappearance.h" -//#include "llagentwearables.h" -//#include "lldictionary.h" -//#include "llfloatersidepanelcontainer.h" #include "lllocaltextureobject.h" -//#include "llnotificationsutil.h" -//#include "llviewertexturelist.h" -//#include "llinventorymodel.h" -//#include "llinventoryobserver.h" -//#include "llsidepanelappearance.h" #include "lltexlayer.h" -//#include "lltexglobalcolor.h" #include "lltexturemanagerbridge.h" -//#include "lltrans.h" -//#include "llviewerregion.h" #include "llvisualparam.h" #include "llvoavatardefines.h" #include "llwearable.h" -//#include "llviewercontrol.h" using namespace LLVOAvatarDefines; @@ -170,6 +158,7 @@ LLWearable::EImportResult LLWearable::importFile( LLFILE* file ) return LLWearable::BAD_HEADER; } + // Temporary hack to allow wearables with definition version 24 to still load. // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 // the extra check for version == 24 can be removed before release, once internal testers diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index 56c931e43b..8a99debac8 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -28,19 +28,16 @@ #define LL_LLWEARABLE_H #include "llextendedstatus.h" -//#include "lluuid.h" -//#include "llstring.h" #include "llpermissions.h" #include "llsaleinfo.h" -//#include "llassetstorage.h" #include "llwearabletype.h" -//#include "llfile.h" #include "lllocaltextureobject.h" class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; +// Abstract class. class LLWearable { //-------------------------------------------------------------------- @@ -72,6 +69,8 @@ public: public: typedef std::vector visual_param_vec_t; + virtual void writeToAvatar() = 0; + enum EImportResult { FAILURE = 0, @@ -81,12 +80,11 @@ public: virtual BOOL exportFile(LLFILE* file) const; virtual EImportResult importFile(LLFILE* file); - virtual LLLocalTextureObject* getLocalTextureObject(S32 index) = 0; - virtual void writeToAvatar() = 0; static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } + virtual LLLocalTextureObject* getLocalTextureObject(S32 index) = 0; void addVisualParam(LLVisualParam *param); void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); F32 getVisualParamWeight(S32 index) const; diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index d47702ff4d..009a3b631a 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -24,11 +24,9 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" #include "llwearabletype.h" -//#include "llinventoryfunctions.h" #include "llinventoryicon.h" #include "lltrans.h" diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index f805083aaa..3a3cae4047 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -26,19 +26,19 @@ #include "llviewerprecompiledheaders.h" +#include "llviewertexlayer.h" + #include "llagent.h" -#include "llassetuploadresponders.h" -#include "llavatarappearance.h" -#include "llglslshader.h" #include "llimagej2c.h" #include "llnotificationsutil.h" -#include "llviewercontrol.h" -#include "llviewerregion.h" -#include "llviewertexlayer.h" #include "llvfile.h" #include "llvfs.h" +#include "llviewerregion.h" +#include "llglslshader.h" #include "llvoavatarself.h" #include "pipeline.h" +#include "llassetuploadresponders.h" +#include "llviewercontrol.h" static const S32 BAKE_UPLOAD_ATTEMPTS = 7; static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt @@ -46,126 +46,6 @@ static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power o // runway consolidate extern std::string self_av_string(); -LLViewerTexLayerSet::LLViewerTexLayerSet(LLAvatarAppearance* const appearance) : - LLTexLayerSet(appearance), - mComposite( NULL ), - mUpdatesEnabled( FALSE ) -{ -} - -// virtual -LLViewerTexLayerSet::~LLViewerTexLayerSet() -{ -} - -void LLViewerTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) -{ - memset(data, 255, width * height); - - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) - { - LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); - } - - // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); -} - -LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() -{ - if (!mComposite) - { - createComposite(); - } - return mComposite; -} - -const LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() const -{ - return mComposite; -} - -// virtual -void LLViewerTexLayerSet::requestUpdate() -{ - if( mUpdatesEnabled ) - { - createComposite(); - mComposite->requestUpdate(); - } -} - -void LLViewerTexLayerSet::requestUpload() -{ - createComposite(); - mComposite->requestUpload(); -} - -void LLViewerTexLayerSet::cancelUpload() -{ - if(mComposite) - { - mComposite->cancelUpload(); - } -} - - -void LLViewerTexLayerSet::createComposite() -{ - if(!mComposite) - { - S32 width = mInfo->getWidth(); - S32 height = mInfo->getHeight(); - // Composite other avatars at reduced resolution - if( !mAvatarAppearance->isSelf() ) - { - llerrs << "composites should not be created for non-self avatars!" << llendl; - } - mComposite = new LLTexLayerSetBuffer( this, width, height ); - } -} - -void LLViewerTexLayerSet::updateComposite() -{ - createComposite(); - mComposite->requestUpdateImmediate(); -} - -// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. -BOOL LLViewerTexLayerSet::isLocalTextureDataAvailable() const -{ - if (!mAvatarAppearance->isSelf()) return FALSE; - LLVOAvatarSelf* self = dynamic_cast(mAvatarAppearance); - return self->isLocalTextureDataAvailable(this); -} - - -// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. -BOOL LLViewerTexLayerSet::isLocalTextureDataFinal() const -{ - if (!mAvatarAppearance->isSelf()) return FALSE; - LLVOAvatarSelf* self = dynamic_cast(mAvatarAppearance); - return self->isLocalTextureDataFinal(this); -} - -void LLViewerTexLayerSet::destroyComposite() -{ - if( mComposite ) - { - mComposite = NULL; - } -} - -void LLViewerTexLayerSet::setUpdatesEnabled( BOOL b ) -{ - mUpdatesEnabled = b; -} - -LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const -{ - return dynamic_cast (mAvatarAppearance); -} //----------------------------------------------------------------------------- // LLBakedUploadData() @@ -693,7 +573,7 @@ void LLTexLayerSetBuffer::doUpdate() // need to switch to using this layerset if this is the first update // after getting the lowest LOD - mTexLayerSet->getAvatarAppearance()->updateMeshTextures(); + mTexLayerSet->getAvatar()->updateMeshTextures(); // Print out notification that we updated this texture. if (gSavedSettings.getBOOL("DebugAvatarRezTime")) @@ -701,7 +581,7 @@ void LLTexLayerSetBuffer::doUpdate() const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatarAppearance()->debugGetExistenceTimeElapsedF32()); + args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); args["RESOLUTION"] = lod_str; @@ -786,6 +666,150 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, delete baked_upload_data; } +//----------------------------------------------------------------------------- +// LLViewerTexLayerSet +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +LLViewerTexLayerSet::LLViewerTexLayerSet(LLAvatarAppearance* const appearance) : + LLTexLayerSet(appearance), + mComposite( NULL ), + mUpdatesEnabled( FALSE ) +{ +} + +// virtual +LLViewerTexLayerSet::~LLViewerTexLayerSet() +{ +} + +// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. +BOOL LLViewerTexLayerSet::isLocalTextureDataAvailable() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + return getAvatar()->isLocalTextureDataAvailable(this); +} + + +// Returns TRUE if all of the data for the textures that this layerset depends on have arrived. +BOOL LLViewerTexLayerSet::isLocalTextureDataFinal() const +{ + if (!mAvatarAppearance->isSelf()) return FALSE; + return getAvatar()->isLocalTextureDataFinal(this); +} + +// virtual +void LLViewerTexLayerSet::requestUpdate() +{ + if( mUpdatesEnabled ) + { + createComposite(); + mComposite->requestUpdate(); + } +} + +void LLViewerTexLayerSet::requestUpload() +{ + createComposite(); + mComposite->requestUpload(); +} + +void LLViewerTexLayerSet::cancelUpload() +{ + if(mComposite) + { + mComposite->cancelUpload(); + } +} + +void LLViewerTexLayerSet::createComposite() +{ + if(!mComposite) + { + S32 width = mInfo->getWidth(); + S32 height = mInfo->getHeight(); + // Composite other avatars at reduced resolution + if( !mAvatarAppearance->isSelf() ) + { + llerrs << "composites should not be created for non-self avatars!" << llendl; + } + mComposite = new LLTexLayerSetBuffer( this, width, height ); + } +} + +void LLViewerTexLayerSet::destroyComposite() +{ + if( mComposite ) + { + mComposite = NULL; + } +} + +void LLViewerTexLayerSet::setUpdatesEnabled( BOOL b ) +{ + mUpdatesEnabled = b; +} + +void LLViewerTexLayerSet::updateComposite() +{ + createComposite(); + mComposite->requestUpdateImmediate(); +} +LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() +{ + if (!mComposite) + { + createComposite(); + } + return mComposite; +} +const LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() const +{ + return mComposite; +} + +void LLViewerTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) +{ + memset(data, 255, width * height); + + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); + } + + // Set alpha back to that of our alpha masks. + renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); +} + + +LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const +{ + return dynamic_cast (mAvatarAppearance); +} + + + +const std::string LLTexLayerSetBuffer::dumpTextureInfo() const +{ + if (!isAgentAvatarValid()) return ""; + + const BOOL is_high_res = !mNeedsUpload; + const U32 num_low_res = mNumLowresUploads; + const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32(); + const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet); + + std::string status = "CREATING "; + if (!uploadNeeded()) status = "DONE "; + if (uploadInProgress()) status = "UPLOADING"; + + std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s", + status.c_str(), + is_high_res, num_low_res, + upload_time, + local_texture_info.c_str()); + return text; +} diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index ff3def5a82..125bf82adf 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -30,8 +30,8 @@ #include "lldynamictexture.h" #include "lltexlayer.h" -class LLTexLayerSetBuffer; class LLVOAvatarSelf; +class LLTexLayerSetBuffer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLViewerTexLayerSet diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index b63f1f57cb..2b6649a7ec 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -33,11 +33,11 @@ #include "llnotificationsutil.h" #include "llsidepanelappearance.h" #include "lltextureentry.h" -#include "llviewercontrol.h" #include "llviewertexlayer.h" -#include "llviewerwearable.h" #include "llvoavatarself.h" #include "llvoavatardefines.h" +#include "llviewerwearable.h" +#include "llviewercontrol.h" using namespace LLVOAvatarDefines; @@ -89,11 +89,6 @@ LLViewerWearable::~LLViewerWearable() { } -void LLViewerWearable::setItemID(const LLUUID& item_id) -{ - mItemID = item_id; -} - // virtual BOOL LLViewerWearable::exportFile(LLFILE* file) const { @@ -107,6 +102,40 @@ BOOL LLViewerWearable::exportFile(LLFILE* file) const return LLWearable::exportFile(file); } + +void LLViewerWearable::createVisualParams() +{ + for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) + { + if (param->getWearableType() == mType) + { + addVisualParam(param->cloneParam(this)); + } + } + + // resync driver parameters to point to the newly cloned driven parameters + for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) + { + LLVisualParam* param = param_iter->second; + LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; + // need this line to disambiguate between versions of LLCharacter::getVisualParam() + LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; + param->resetDrivenParams(); + if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + { + if( !param->linkDrivenParams(boost::bind(param_function,gAgentAvatarp.get(),_1 ), true)) + { + llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; + continue; + } + } + } +} + // virtual LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file ) { @@ -159,6 +188,7 @@ LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file ) return result; } + // Avatar parameter and texture definitions can change over time. // This function returns true if parameters or textures have been added or removed // since this wearable was created. @@ -492,6 +522,11 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) revertValues(); } +void LLViewerWearable::setItemID(const LLUUID& item_id) +{ + mItemID = item_id; +} + LLLocalTextureObject* LLViewerWearable::getLocalTextureObject(S32 index) { @@ -538,6 +573,17 @@ void LLViewerWearable::setLocalTextureObject(S32 index, LLLocalTextureObject < mTEMap[index] = new LLLocalTextureObject(lto); } +void LLViewerWearable::setVisualParams() +{ + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->second; + F32 value = wearable_param->getWeight(); + gAgentAvatarp->setVisualParamWeight(id, value, FALSE); + } +} + void LLViewerWearable::revertValues() { //update saved settings so wearable is no longer dirty @@ -591,6 +637,19 @@ BOOL LLViewerWearable::isOnTop() const return (this == gAgentWearables.getTopWearable(mType)); } +void LLViewerWearable::createLayers(S32 te) +{ + LLViewerTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); + if (layer_set) + { + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + } + else + { + llerrs << "could not find layerset for LTO in wearable!" << llendl; + } +} + void LLViewerWearable::saveValues() { //update saved settings so wearable is no longer dirty @@ -702,7 +761,6 @@ void LLViewerWearable::setLabelUpdated() const gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); } - void LLViewerWearable::refreshName() { LLUUID item_id = getItemID(); @@ -802,65 +860,6 @@ void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* } -void LLViewerWearable::createLayers(S32 te) -{ - LLViewerTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); - if (layer_set) - { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); - } - else - { - llerrs << "could not find layerset for LTO in wearable!" << llendl; - } -} - -void LLViewerWearable::createVisualParams() -{ - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if (param->getWearableType() == mType) - { - addVisualParam(param->cloneParam(this)); - } - } - - // resync driver parameters to point to the newly cloned driven parameters - for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin(); - param_iter != mVisualParamIndexMap.end(); - ++param_iter) - { - LLVisualParam* param = param_iter->second; - LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; - // need this line to disambiguate between versions of LLCharacter::getVisualParam() - LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; - param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) - { - if( !param->linkDrivenParams(boost::bind(param_function,gAgentAvatarp.get(),_1 ), true)) - { - llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; - continue; - } - } - } -} - -void LLViewerWearable::setVisualParams() -{ - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - gAgentAvatarp->setVisualParamWeight(id, value, FALSE); - } -} - - - std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) { s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n"; @@ -897,4 +896,3 @@ std::string asset_id_to_filename(const LLUUID &asset_id) std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl"; return filename; } - diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 857900f583..a921f82e7d 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -54,8 +54,6 @@ public: void setItemID(const LLUUID& item_id); public: - /*virtual*/ BOOL exportFile(LLFILE* file) const; - /*virtual*/ EImportResult importFile(LLFILE* file); BOOL isDirty() const; BOOL isOldVersion() const; @@ -64,6 +62,9 @@ public: void removeFromAvatar( BOOL upload_bake ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); } static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); + /*virtual*/ BOOL exportFile(LLFILE* file) const; + /*virtual*/ EImportResult importFile(LLFILE* file); + void setParamsToDefaults(); void setTexturesToDefaults(); @@ -81,6 +82,7 @@ public: const LLLocalTextureObject* getLocalTextureObject(S32 index) const; std::vector getLocalTextureListSeq(); void setLocalTextureObject(S32 index, LLLocalTextureObject <o); + void setVisualParams(); void revertValues(); void saveValues(); @@ -96,19 +98,19 @@ public: void refreshName(); protected: + typedef std::map te_map_t; + void createLayers(S32 te); /*virtual*/void createVisualParams(); - void setVisualParams(); - typedef std::map te_map_t; void syncImages(te_map_t &src, te_map_t &dst); void destroyTextures(); - LLTransactionID mTransactionID; LLAssetID mAssetID; - LLUUID mItemID; // ID of the inventory item in the agent's inventory + LLTransactionID mTransactionID; te_map_t mTEMap; // maps TE to LocalTextureObject te_map_t mSavedTEMap; // last saved version of TEMap + LLUUID mItemID; // ID of the inventory item in the agent's inventory }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index dac479b2e0..e3d8f9135e 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -764,6 +764,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthTimer.reset(); mRuthDebugTimer.reset(); + mDebugExistenceTimer.reset(); mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); mLastPelvisToFoot = 0.0f; mPelvisFixup = 0.0f; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 023711d81b..512522803a 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1038,9 +1038,12 @@ private: //-------------------------------------------------------------------- public: void debugAvatarRezTime(std::string notification_name, std::string comment = ""); + F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } + protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez + LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. /** Diagnostics ** ** -- cgit v1.2.3 From 21c364c4d455cc05ec176032e8c090be0cc4ed50 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Mon, 3 Sep 2012 09:10:24 +0000 Subject: Renamed LLVOAvatarDefines to LLAvatarAppearanceDefines --- indra/llappearance/CMakeLists.txt | 4 +- indra/llappearance/llavatarappearance.cpp | 2 +- indra/llappearance/llavatarappearance.h | 10 +- indra/llappearance/llavatarappearancedefines.cpp | 246 +++++++++++++++++++++++ indra/llappearance/llavatarappearancedefines.h | 226 +++++++++++++++++++++ indra/llappearance/lltexlayer.cpp | 14 +- indra/llappearance/lltexlayer.h | 10 +- indra/llappearance/llvoavatardefines.cpp | 246 ----------------------- indra/llappearance/llvoavatardefines.h | 226 --------------------- indra/llappearance/llwearable.cpp | 8 +- indra/newview/llagent.cpp | 10 +- indra/newview/llagent.h | 4 +- indra/newview/llagentcamera.cpp | 2 +- indra/newview/llagentwearables.cpp | 12 +- indra/newview/llagentwearables.h | 6 +- indra/newview/llappearance.h | 8 +- indra/newview/llavatariconctrl.cpp | 2 +- indra/newview/llfloateravatartextures.cpp | 10 +- indra/newview/llfloateravatartextures.h | 4 +- indra/newview/lllocalbitmaps.cpp | 100 ++++----- indra/newview/lllocalbitmaps.h | 4 +- indra/newview/llpaneleditwearable.cpp | 20 +- indra/newview/llpaneleditwearable.h | 12 +- indra/newview/lltextureview.cpp | 6 +- indra/newview/llviewermenu.cpp | 4 +- indra/newview/llviewertexlayer.cpp | 4 +- indra/newview/llviewerwearable.cpp | 26 +-- indra/newview/llviewerwearable.h | 4 +- indra/newview/llvoavatar.cpp | 102 +++++----- indra/newview/llvoavatar.h | 30 +-- indra/newview/llvoavatarself.cpp | 132 ++++++------ indra/newview/llvoavatarself.h | 58 +++--- 32 files changed, 776 insertions(+), 776 deletions(-) create mode 100644 indra/llappearance/llavatarappearancedefines.cpp create mode 100644 indra/llappearance/llavatarappearancedefines.h delete mode 100644 indra/llappearance/llvoavatardefines.cpp delete mode 100644 indra/llappearance/llvoavatardefines.h diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 8d2334c566..f77c7e6440 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -52,7 +52,7 @@ set(llappearance_SOURCE_FILES llwearable.cpp llwearabletype.cpp llviewervisualparam.cpp - llvoavatardefines.cpp + llavatarappearancedefines.cpp ) set(llappearance_HEADER_FILES @@ -69,7 +69,7 @@ set(llappearance_HEADER_FILES llwearable.h llwearabletype.h llviewervisualparam.h - llvoavatardefines.h + llavatarappearancedefines.h ) set_source_files_properties(${llappearance_HEADER_FILES} diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 044ea8fbf0..2cc38ae2ab 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -40,7 +40,7 @@ LLAvatarAppearance::LLAvatarAppearance() : { } -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; //static BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 1b0e0ad270..0ab3960e64 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -29,7 +29,7 @@ #include "llcharacter.h" #include "llframetimer.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLTexGlobalColor; class LLTexLayerSet; @@ -50,9 +50,9 @@ public: // Clothing colors (convenience functions to access visual parameters) //-------------------------------------------------------------------- public: - void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); - LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); - static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); + void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); + LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); + static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors @@ -69,7 +69,7 @@ protected: // Morph masks //-------------------------------------------------------------------- public: - virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES) = 0; + virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; //-------------------------------------------------------------------- // Composites diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp new file mode 100644 index 0000000000..2c3cf781c1 --- /dev/null +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -0,0 +1,246 @@ +/** + * @file llavatarappearancedefines.cpp + * @brief Implementation of LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llavatarappearancedefines.h" + +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 512; +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 512; +const S32 LLAvatarAppearanceDefines::IMPOSTOR_PERIOD = 2; + +using namespace LLAvatarAppearanceDefines; + +/********************************************************************************* + * Edit this function to add/remove/change textures and mesh definitions for avatars. + */ + +LLAvatarAppearanceDictionary::Textures::Textures() +{ + addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); + addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); + addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); + addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); + addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); + addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); + addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); + addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); + addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); + addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); + + addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + + addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); +} + +LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() +{ + // Baked textures + addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, + "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", + 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, + 5, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, + "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", + 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, + TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, + 8, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, + "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", + 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, + TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, + 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, + "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", + 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, + 2, LLWearableType::WT_EYES, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, + "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", + 1, TEX_SKIRT, + 1, LLWearableType::WT_SKIRT)); + + addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, + "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", + 2, TEX_HAIR, TEX_HAIR_ALPHA, + 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); +} + +LLAvatarAppearanceDictionary::Meshes::Meshes() +{ + // Meshes + addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); + addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); + addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently + addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); + addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); + addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); + addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); + addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); +} + +/* + * + *********************************************************************************/ + +LLAvatarAppearanceDictionary::LLAvatarAppearanceDictionary() +{ + createAssociations(); +} + +//virtual +LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary() +{ +} + +// Baked textures are composites of textures; for each such composited texture, +// map it to the baked texture. +void LLAvatarAppearanceDictionary::createAssociations() +{ + for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) + { + const EBakedTextureIndex baked_index = (iter->first); + const BakedEntry *dict = (iter->second); + + // For each texture that this baked texture index affects, associate those textures + // with this baked texture index. + for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); + local_texture_iter != dict->mLocalTextures.end(); + local_texture_iter++) + { + const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; + mTextures[local_texture_index]->mIsUsedByBakedTexture = true; + mTextures[local_texture_index]->mBakedTextureIndex = baked_index; + } + } + +} + +LLAvatarAppearanceDictionary::TextureEntry::TextureEntry(const std::string &name, + bool is_local_texture, + EBakedTextureIndex baked_texture_index, + const std::string &default_image_name, + LLWearableType::EType wearable_type) : + LLDictionaryEntry(name), + mIsLocalTexture(is_local_texture), + mIsBakedTexture(!is_local_texture), + mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), + mBakedTextureIndex(baked_texture_index), + mDefaultImageName(default_image_name), + mWearableType(wearable_type) +{ +} + +LLAvatarAppearanceDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, + U8 level, + LLJointPickName pick) : + LLDictionaryEntry(name), + mBakedID(baked_index), + mLOD(level), + mPickName(pick) +{ +} +LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, + const std::string &name, + const std::string &hash_name, + U32 num_local_textures, + ... ) : + LLDictionaryEntry(name), + mWearablesHashID(LLUUID(hash_name)), + mTextureIndex(tex_index) +{ + va_list argp; + + va_start(argp, num_local_textures); + + // Read in local textures + for (U8 i=0; i < num_local_textures; i++) + { + ETextureIndex t = (ETextureIndex)va_arg(argp,int); + mLocalTextures.push_back(t); + } + + // Read in number of wearables + const U32 num_wearables = (U32)va_arg(argp,int); + // Read in wearables + for (U8 i=0; i < num_wearables; i++) + { + LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); + mWearables.push_back(t); + } +} + +// static +ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) +{ + return LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; +} + +//static +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) +{ + U8 index = 0; + while (index < BAKED_NUM_INDICES) + { + const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); + if (be && be->mName.compare(name) == 0) + { + // baked texture found + return (EBakedTextureIndex) index; + } + index++; + } + // baked texture could not be found + return BAKED_NUM_INDICES; +} + +// static +LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) +{ + return getInstance()->getTexture(index)->mWearableType; +} + diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h new file mode 100644 index 0000000000..c5285ddc02 --- /dev/null +++ b/indra/llappearance/llavatarappearancedefines.h @@ -0,0 +1,226 @@ +/** + * @file llavatarappearancedefines.h + * @brief Various LLAvatarAppearance related definitions + * LLViewerObject + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_AVATARAPPEARANCE_DEFINES_H +#define LL_AVATARAPPEARANCE_DEFINES_H + +#include +#include "llwearable.h" +#include "lljointpickname.h" +#include "lldictionary.h" + +namespace LLAvatarAppearanceDefines +{ + +extern const S32 SCRATCH_TEX_WIDTH; +extern const S32 SCRATCH_TEX_HEIGHT; +extern const S32 IMPOSTOR_PERIOD; + +//-------------------------------------------------------------------- +// Enums +//-------------------------------------------------------------------- +enum ETextureIndex +{ + TEX_HEAD_BODYPAINT = 0, + TEX_UPPER_SHIRT, + TEX_LOWER_PANTS, + TEX_EYES_IRIS, + TEX_HAIR, + TEX_UPPER_BODYPAINT, + TEX_LOWER_BODYPAINT, + TEX_LOWER_SHOES, + TEX_HEAD_BAKED, // Pre-composited + TEX_UPPER_BAKED, // Pre-composited + TEX_LOWER_BAKED, // Pre-composited + TEX_EYES_BAKED, // Pre-composited + TEX_LOWER_SOCKS, + TEX_UPPER_JACKET, + TEX_LOWER_JACKET, + TEX_UPPER_GLOVES, + TEX_UPPER_UNDERSHIRT, + TEX_LOWER_UNDERPANTS, + TEX_SKIRT, + TEX_SKIRT_BAKED, // Pre-composited + TEX_HAIR_BAKED, // Pre-composited + TEX_LOWER_ALPHA, + TEX_UPPER_ALPHA, + TEX_HEAD_ALPHA, + TEX_EYES_ALPHA, + TEX_HAIR_ALPHA, + TEX_HEAD_TATTOO, + TEX_UPPER_TATTOO, + TEX_LOWER_TATTOO, + TEX_NUM_INDICES +}; + +enum EBakedTextureIndex +{ + BAKED_HEAD = 0, + BAKED_UPPER, + BAKED_LOWER, + BAKED_EYES, + BAKED_SKIRT, + BAKED_HAIR, + BAKED_NUM_INDICES +}; + +// Reference IDs for each mesh. Used as indices for vector of joints +enum EMeshIndex +{ + MESH_ID_HAIR = 0, + MESH_ID_HEAD, + MESH_ID_EYELASH, + MESH_ID_UPPER_BODY, + MESH_ID_LOWER_BODY, + MESH_ID_EYEBALL_LEFT, + MESH_ID_EYEBALL_RIGHT, + MESH_ID_SKIRT, + MESH_ID_NUM_INDICES +}; + +//-------------------------------------------------------------------- +// Vector Types +//-------------------------------------------------------------------- +typedef std::vector texture_vec_t; +typedef std::vector bakedtexture_vec_t; +typedef std::vector mesh_vec_t; +typedef std::vector wearables_vec_t; + +//------------------------------------------------------------------------ +// LLAvatarAppearanceDictionary +// +// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. +// information that is common to all avatars. +// +// This holds const data - it is initialized once and the contents never change after that. +//------------------------------------------------------------------------ +class LLAvatarAppearanceDictionary : public LLSingleton +{ + //-------------------------------------------------------------------- + // Constructors and Destructors + //-------------------------------------------------------------------- +public: + LLAvatarAppearanceDictionary(); + virtual ~LLAvatarAppearanceDictionary(); +private: + void createAssociations(); + + //-------------------------------------------------------------------- + // Local and baked textures + //-------------------------------------------------------------------- +public: + struct TextureEntry : public LLDictionaryEntry + { + TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml + bool is_local_texture, + EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, + const std::string& default_image_name = "", + LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); + const std::string mDefaultImageName; + const LLWearableType::EType mWearableType; + // It's either a local texture xor baked + BOOL mIsLocalTexture; + BOOL mIsBakedTexture; + // If it's a local texture, it may be used by a baked texture + BOOL mIsUsedByBakedTexture; + EBakedTextureIndex mBakedTextureIndex; + }; + + struct Textures : public LLDictionary + { + Textures(); + } mTextures; + const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } + const Textures& getTextures() const { return mTextures; } + + //-------------------------------------------------------------------- + // Meshes + //-------------------------------------------------------------------- +public: + struct MeshEntry : public LLDictionaryEntry + { + MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, // names of mesh types as they are used in avatar_lad.xml + U8 level, + LLJointPickName pick); + // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml + // Otherwise meshes will be unable to be found, or levels of detail will be ignored + const U8 mLOD; + const EBakedTextureIndex mBakedID; + const LLJointPickName mPickName; + }; + + struct Meshes : public LLDictionary + { + Meshes(); + } mMeshes; + const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } + const Meshes& getMeshes() const { return mMeshes; } + + //-------------------------------------------------------------------- + // Baked Textures + //-------------------------------------------------------------------- +public: + struct BakedEntry : public LLDictionaryEntry + { + BakedEntry(ETextureIndex tex_index, + const std::string &name, // unused, but necessary for templating. + const std::string &hash_name, + U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list + // Local Textures + const ETextureIndex mTextureIndex; + texture_vec_t mLocalTextures; + // Wearables + const LLUUID mWearablesHashID; + wearables_vec_t mWearables; + }; + + struct BakedTextures: public LLDictionary + { + BakedTextures(); + } mBakedTextures; + const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } + const BakedTextures& getBakedTextures() const { return mBakedTextures; } + + //-------------------------------------------------------------------- + // Convenience Functions + //-------------------------------------------------------------------- +public: + // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED + static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t); + + // find a baked texture index based on its name + static EBakedTextureIndex findBakedByRegionName(std::string name); + + // Given a texture entry, determine which wearable type owns it. + static LLWearableType::EType getTEWearableType(ETextureIndex index); + +}; // End LLAvatarAppearanceDictionary + +} // End namespace LLAvatarAppearanceDefines + +#endif //LL_AVATARAPPEARANCE_DEFINES_H diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 6522976be1..bf2fd1e30d 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -44,7 +44,7 @@ //#include "../tools/imdebug/imdebug.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; static const S32 BAKE_UPLOAD_ATTEMPTS = 7; static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt @@ -183,7 +183,7 @@ BOOL LLTexLayerSet::sHasCaches = FALSE; LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : mAvatarAppearance( appearance ), mIsVisible( TRUE ), - mBakedTexIndex(LLVOAvatarDefines::BAKED_HEAD), + mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD), mInfo( NULL ) { } @@ -567,11 +567,11 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) /* if ("upper_shirt" == local_texture_name) mLocalTexture = TEX_UPPER_SHIRT; */ mLocalTexture = TEX_NUM_INDICES; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); iter++) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (local_texture_name == texture_dict->mName) { mLocalTexture = iter->first; @@ -1450,7 +1450,7 @@ U32 LLTexLayerTemplate::updateWearableCache() const //this isn't a cloneable layer return 0; } - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te); U32 num_wearables = getAvatarAppearance()->getWearableCount(wearable_type); U32 added = 0; for (U32 i = 0; i < num_wearables; i++) @@ -1617,7 +1617,7 @@ LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) return NULL; } -void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable) +void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable) { // initialize all texlayers with this texture type for this LTO for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 5ee08e67ec..5a413e929f 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -30,7 +30,7 @@ #include #include "lltexture.h" #include "llframetimer.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "lltexlayerparams.h" class LLAvatarAppearance; @@ -195,12 +195,12 @@ public: void invalidateMorphMasks(); void deleteCaches(); LLTexLayerInterface* findLayerByName(const std::string& name); - void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); + void cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable* wearable); LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } const std::string getBodyRegionName() const; - LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } - void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } + LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } + void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } BOOL isVisible() const { return mIsVisible; } static BOOL sHasCaches; @@ -212,7 +212,7 @@ protected: LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. BOOL mIsVisible; - LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex; + LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex; const LLTexLayerSetInfo* mInfo; }; diff --git a/indra/llappearance/llvoavatardefines.cpp b/indra/llappearance/llvoavatardefines.cpp deleted file mode 100644 index 29891986f5..0000000000 --- a/indra/llappearance/llvoavatardefines.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @file llvoavatardefines.cpp - * @brief Implementation of LLVOAvatarDefines::LLVOAvatarDictionary - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llvoavatardefines.h" - -const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; -const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; -const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; - -using namespace LLVOAvatarDefines; - -/********************************************************************************* - * Edit this function to add/remove/change textures and mesh definitions for avatars. - */ - -LLVOAvatarDictionary::Textures::Textures() -{ - addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); - addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); - addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); - addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); - addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); - addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); - addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); - addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); - addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); - addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); - - addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - - addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); -} - -LLVOAvatarDictionary::BakedTextures::BakedTextures() -{ - // Baked textures - addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, - "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", - 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, - 5, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, - "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", - 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, - TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, - 8, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, - "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", - 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, - TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, - 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, - "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", - 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, - 2, LLWearableType::WT_EYES, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, - "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", - 1, TEX_SKIRT, - 1, LLWearableType::WT_SKIRT)); - - addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, - "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", - 2, TEX_HAIR, TEX_HAIR_ALPHA, - 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); -} - -LLVOAvatarDictionary::Meshes::Meshes() -{ - // Meshes - addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); - addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); - addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently - addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); - addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); - addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); - addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); - addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); -} - -/* - * - *********************************************************************************/ - -LLVOAvatarDictionary::LLVOAvatarDictionary() -{ - createAssociations(); -} - -//virtual -LLVOAvatarDictionary::~LLVOAvatarDictionary() -{ -} - -// Baked textures are composites of textures; for each such composited texture, -// map it to the baked texture. -void LLVOAvatarDictionary::createAssociations() -{ - for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++) - { - const EBakedTextureIndex baked_index = (iter->first); - const BakedEntry *dict = (iter->second); - - // For each texture that this baked texture index affects, associate those textures - // with this baked texture index. - for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); - local_texture_iter != dict->mLocalTextures.end(); - local_texture_iter++) - { - const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; - mTextures[local_texture_index]->mIsUsedByBakedTexture = true; - mTextures[local_texture_index]->mBakedTextureIndex = baked_index; - } - } - -} - -LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name, - bool is_local_texture, - EBakedTextureIndex baked_texture_index, - const std::string &default_image_name, - LLWearableType::EType wearable_type) : - LLDictionaryEntry(name), - mIsLocalTexture(is_local_texture), - mIsBakedTexture(!is_local_texture), - mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), - mBakedTextureIndex(baked_texture_index), - mDefaultImageName(default_image_name), - mWearableType(wearable_type) -{ -} - -LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, - U8 level, - LLJointPickName pick) : - LLDictionaryEntry(name), - mBakedID(baked_index), - mLOD(level), - mPickName(pick) -{ -} -LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, - const std::string &name, - const std::string &hash_name, - U32 num_local_textures, - ... ) : - LLDictionaryEntry(name), - mWearablesHashID(LLUUID(hash_name)), - mTextureIndex(tex_index) -{ - va_list argp; - - va_start(argp, num_local_textures); - - // Read in local textures - for (U8 i=0; i < num_local_textures; i++) - { - ETextureIndex t = (ETextureIndex)va_arg(argp,int); - mLocalTextures.push_back(t); - } - - // Read in number of wearables - const U32 num_wearables = (U32)va_arg(argp,int); - // Read in wearables - for (U8 i=0; i < num_wearables; i++) - { - LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); - mWearables.push_back(t); - } -} - -// static -ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) -{ - return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; -} - -//static -EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) -{ - U8 index = 0; - while (index < BAKED_NUM_INDICES) - { - const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index); - if (be && be->mName.compare(name) == 0) - { - // baked texture found - return (EBakedTextureIndex) index; - } - index++; - } - // baked texture could not be found - return BAKED_NUM_INDICES; -} - -// static -LLWearableType::EType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index ) -{ - return getInstance()->getTexture(index)->mWearableType; -} - diff --git a/indra/llappearance/llvoavatardefines.h b/indra/llappearance/llvoavatardefines.h deleted file mode 100644 index 7745775f9f..0000000000 --- a/indra/llappearance/llvoavatardefines.h +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file llvoavatardefines.h - * @brief Various LLAvatarAppearance related definitions - * LLViewerObject - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLVOAVATAR_DEFINES_H -#define LLVOAVATAR_DEFINES_H - -#include -#include "llwearable.h" -#include "lljointpickname.h" -#include "lldictionary.h" - -namespace LLVOAvatarDefines -{ - -extern const S32 SCRATCH_TEX_WIDTH; -extern const S32 SCRATCH_TEX_HEIGHT; -extern const S32 IMPOSTOR_PERIOD; - -//-------------------------------------------------------------------- -// Enums -//-------------------------------------------------------------------- -enum ETextureIndex -{ - TEX_HEAD_BODYPAINT = 0, - TEX_UPPER_SHIRT, - TEX_LOWER_PANTS, - TEX_EYES_IRIS, - TEX_HAIR, - TEX_UPPER_BODYPAINT, - TEX_LOWER_BODYPAINT, - TEX_LOWER_SHOES, - TEX_HEAD_BAKED, // Pre-composited - TEX_UPPER_BAKED, // Pre-composited - TEX_LOWER_BAKED, // Pre-composited - TEX_EYES_BAKED, // Pre-composited - TEX_LOWER_SOCKS, - TEX_UPPER_JACKET, - TEX_LOWER_JACKET, - TEX_UPPER_GLOVES, - TEX_UPPER_UNDERSHIRT, - TEX_LOWER_UNDERPANTS, - TEX_SKIRT, - TEX_SKIRT_BAKED, // Pre-composited - TEX_HAIR_BAKED, // Pre-composited - TEX_LOWER_ALPHA, - TEX_UPPER_ALPHA, - TEX_HEAD_ALPHA, - TEX_EYES_ALPHA, - TEX_HAIR_ALPHA, - TEX_HEAD_TATTOO, - TEX_UPPER_TATTOO, - TEX_LOWER_TATTOO, - TEX_NUM_INDICES -}; - -enum EBakedTextureIndex -{ - BAKED_HEAD = 0, - BAKED_UPPER, - BAKED_LOWER, - BAKED_EYES, - BAKED_SKIRT, - BAKED_HAIR, - BAKED_NUM_INDICES -}; - -// Reference IDs for each mesh. Used as indices for vector of joints -enum EMeshIndex -{ - MESH_ID_HAIR = 0, - MESH_ID_HEAD, - MESH_ID_EYELASH, - MESH_ID_UPPER_BODY, - MESH_ID_LOWER_BODY, - MESH_ID_EYEBALL_LEFT, - MESH_ID_EYEBALL_RIGHT, - MESH_ID_SKIRT, - MESH_ID_NUM_INDICES -}; - -//-------------------------------------------------------------------- -// Vector Types -//-------------------------------------------------------------------- -typedef std::vector texture_vec_t; -typedef std::vector bakedtexture_vec_t; -typedef std::vector mesh_vec_t; -typedef std::vector wearables_vec_t; - -//------------------------------------------------------------------------ -// LLVOAvatarDictionary -// -// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. -// information that is common to all avatars. -// -// This holds const data - it is initialized once and the contents never change after that. -//------------------------------------------------------------------------ -class LLVOAvatarDictionary : public LLSingleton -{ - //-------------------------------------------------------------------- - // Constructors and Destructors - //-------------------------------------------------------------------- -public: - LLVOAvatarDictionary(); - virtual ~LLVOAvatarDictionary(); -private: - void createAssociations(); - - //-------------------------------------------------------------------- - // Local and baked textures - //-------------------------------------------------------------------- -public: - struct TextureEntry : public LLDictionaryEntry - { - TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml - bool is_local_texture, - EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, - const std::string& default_image_name = "", - LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); - const std::string mDefaultImageName; - const LLWearableType::EType mWearableType; - // It's either a local texture xor baked - BOOL mIsLocalTexture; - BOOL mIsBakedTexture; - // If it's a local texture, it may be used by a baked texture - BOOL mIsUsedByBakedTexture; - EBakedTextureIndex mBakedTextureIndex; - }; - - struct Textures : public LLDictionary - { - Textures(); - } mTextures; - const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } - const Textures& getTextures() const { return mTextures; } - - //-------------------------------------------------------------------- - // Meshes - //-------------------------------------------------------------------- -public: - struct MeshEntry : public LLDictionaryEntry - { - MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, // names of mesh types as they are used in avatar_lad.xml - U8 level, - LLJointPickName pick); - // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml - // Otherwise meshes will be unable to be found, or levels of detail will be ignored - const U8 mLOD; - const EBakedTextureIndex mBakedID; - const LLJointPickName mPickName; - }; - - struct Meshes : public LLDictionary - { - Meshes(); - } mMeshes; - const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } - const Meshes& getMeshes() const { return mMeshes; } - - //-------------------------------------------------------------------- - // Baked Textures - //-------------------------------------------------------------------- -public: - struct BakedEntry : public LLDictionaryEntry - { - BakedEntry(ETextureIndex tex_index, - const std::string &name, // unused, but necessary for templating. - const std::string &hash_name, - U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list - // Local Textures - const ETextureIndex mTextureIndex; - texture_vec_t mLocalTextures; - // Wearables - const LLUUID mWearablesHashID; - wearables_vec_t mWearables; - }; - - struct BakedTextures: public LLDictionary - { - BakedTextures(); - } mBakedTextures; - const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } - const BakedTextures& getBakedTextures() const { return mBakedTextures; } - - //-------------------------------------------------------------------- - // Convenience Functions - //-------------------------------------------------------------------- -public: - // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED - static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t); - - // find a baked texture index based on its name - static EBakedTextureIndex findBakedByRegionName(std::string name); - - // Given a texture entry, determine which wearable type owns it. - static LLWearableType::EType getTEWearableType(ETextureIndex index); - -}; // End LLVOAvatarDictionary - -} // End namespace LLVOAvatarDefines - -#endif //LL_VO_AVATARDEFINES_H diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 77f1f27cb0..ea14c6320f 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -31,10 +31,10 @@ #include "lltexlayer.h" #include "lltexturemanagerbridge.h" #include "llvisualparam.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "llwearable.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; // static S32 LLWearable::sCurrentDefinitionVersion = 1; @@ -420,7 +420,7 @@ LLColor4 LLWearable::getClothesColor(S32 te) const { LLColor4 color; U32 param_name[3]; - if( LLAvatarAppearance::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) { for( U8 index = 0; index < 3; index++ ) { @@ -433,7 +433,7 @@ LLColor4 LLWearable::getClothesColor(S32 te) const void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) { U32 param_name[3]; - if( LLAvatarAppearance::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) { for( U8 index = 0; index < 3; index++ ) { diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2379c23969..4e05836bca 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -92,7 +92,7 @@ #include "llworldmap.h" #include "stringize.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; extern LLMenuBarGL* gMenuBarView; @@ -3654,7 +3654,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * if ((S32)texture_index < TEX_NUM_INDICES ) { - const LLVOAvatarDictionary::TextureEntry *texture_entry = LLVOAvatarDictionary::instance().getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index); if (texture_entry) { EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex; @@ -4303,7 +4303,7 @@ void LLAgent::sendAgentSetAppearance() for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) { - const ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); // if we're not wearing a skirt, we don't need the texture to be baked if (texture_index == TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) @@ -4326,7 +4326,7 @@ void LLAgent::sendAgentSetAppearance() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { BOOL generate_valid_hash = TRUE; - if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index)) + if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLAvatarAppearanceDefines::EBakedTextureIndex)baked_index)) { generate_valid_hash = FALSE; LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL; @@ -4335,7 +4335,7 @@ void LLAgent::sendAgentSetAppearance() const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); if (hash.notNull()) { - ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); + ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); msg->nextBlockFast(_PREHASH_WearableData); msg->addUUIDFast(_PREHASH_CacheID, hash); msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 99904e118c..f784262e90 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -33,7 +33,7 @@ #include "llagentdata.h" // gAgentID, gAgentSessionID #include "llcharacter.h" #include "llcoordframe.h" // for mFrameAgent -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include #include @@ -901,7 +901,7 @@ private: S32 mNumPendingQueries; S32 mWearablesCacheQueryID; U32 mUpdateSerialNum; - S32 mActiveCacheQueries[LLVOAvatarDefines::BAKED_NUM_INDICES]; + S32 mActiveCacheQueries[LLAvatarAppearanceDefines::BAKED_NUM_INDICES]; }; extern LLAgentQueryManager gAgentQueryManager; diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index a544909e66..e1ef0d5399 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -49,7 +49,7 @@ #include "llwindow.h" #include "llworld.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; extern LLMenuBarGL* gMenuBarView; diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e4f02b9f0b..2202d65380 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -56,7 +56,7 @@ LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; /////////////////////////////////////////////////////////////////////////////// @@ -903,7 +903,7 @@ U32 LLAgentWearables::getWearableCount(const LLWearableType::EType type) const U32 LLAgentWearables::getWearableCount(const U32 tex_index) const { - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); return getWearableCount(wearable_type); } @@ -1093,7 +1093,7 @@ void LLAgentWearables::recoverMissingWearableDone() } } -void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index) +void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index) { LLViewerWearable* wearable = getWearable((LLWearableType::EType)wearable_type, wearable_index); if (!wearable) @@ -1626,7 +1626,7 @@ void LLAgentWearables::queryWearableCache() num_queries++; // *NOTE: make sure at least one request gets packed - ETextureIndex te_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); + ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index); //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl; gMessageSystem->nextBlockFast(_PREHASH_WearableData); @@ -1652,13 +1652,13 @@ void LLAgentWearables::queryWearableCache() } } -LLUUID LLAgentWearables::computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index, +LLUUID LLAgentWearables::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache { LLUUID hash_id; bool hash_computed = false; LLMD5 hash; - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); for (U8 i=0; i < baked_dict->mWearables.size(); i++) { diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 3df552544b..423e23018e 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -36,7 +36,7 @@ // newview #include "llinventorymodel.h" #include "llviewerinventory.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLInventoryItem; class LLVOAvatarSelf; @@ -122,7 +122,7 @@ public: void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false); void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); - void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index); + void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index); U32 getWearableIndex(const LLViewerWearable *wearable) const; protected: @@ -171,7 +171,7 @@ protected: public: // Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant) static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data); - LLUUID computeBakedTextureHash(LLVOAvatarDefines::EBakedTextureIndex baked_index, + LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, BOOL generate_valid_hash = TRUE); protected: diff --git a/indra/newview/llappearance.h b/indra/newview/llappearance.h index a28b77b1fc..05dfac4e42 100644 --- a/indra/newview/llappearance.h +++ b/indra/newview/llappearance.h @@ -38,14 +38,14 @@ public: void addParam( S32 id, F32 value ) { mParamMap[id] = value; } F32 getParam( S32 id, F32 defval ) { return get_if_there(mParamMap, id, defval ); } - void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLVOAvatarDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; } - const LLUUID& getTexture( S32 te ) { return ( te < LLVOAvatarDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; } + void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLAvatarAppearanceDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; } + const LLUUID& getTexture( S32 te ) { return ( te < LLAvatarAppearanceDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; } - void clear() { mParamMap.clear(); for( S32 i=0; i param_map_t; param_map_t mParamMap; - LLUUID mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; + LLUUID mTextures[LLAvatarAppearanceDefines::TEX_NUM_INDICES]; }; #endif // LL_LLAPPEARANCE_H diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index d2acd32713..76f10e2d56 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -38,7 +38,7 @@ #include "llagentdata.h" #include "llimfloater.h" #include "llviewertexture.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" // library includes #include "llavatarnamecache.h" diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index b26b302ea6..68bdf9a8d6 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -38,7 +38,7 @@ #include "llviewerobjectlist.h" #include "llvoavatarself.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLSD& id) : LLFloater(id), @@ -54,7 +54,7 @@ BOOL LLFloaterAvatarTextures::postBuild() { for (U32 i=0; i < TEX_NUM_INDICES; i++) { - const std::string tex_name = LLVOAvatarDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; + const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; mTextures[i] = getChild(tex_name); } mTitle = getTitle(); @@ -76,7 +76,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, ETextureIndex te) { LLUUID id = IMG_DEFAULT_AVATAR; - const LLVOAvatarDictionary::TextureEntry* tex_entry = LLVOAvatarDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); if (tex_entry->mIsLocalTexture) { if (avatarp->isSelf()) @@ -164,14 +164,14 @@ void LLFloaterAvatarTextures::onClickDump(void* data) const LLTextureEntry* te = avatarp->getTE(i); if (!te) continue; - const LLVOAvatarDictionary::TextureEntry* tex_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)(i)); + const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)(i)); if (!tex_entry) continue; if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) { LLUUID id = IMG_DEFAULT_AVATAR; - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType((ETextureIndex)i); if (avatarp->isSelf()) { LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); diff --git a/indra/newview/llfloateravatartextures.h b/indra/newview/llfloateravatartextures.h index 85ff545855..02474a10e1 100644 --- a/indra/newview/llfloateravatartextures.h +++ b/indra/newview/llfloateravatartextures.h @@ -30,7 +30,7 @@ #include "llfloater.h" #include "lluuid.h" #include "llstring.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLTextureCtrl; @@ -51,7 +51,7 @@ private: private: LLUUID mID; std::string mTitle; - LLTextureCtrl* mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; + LLTextureCtrl* mTextures[LLAvatarAppearanceDefines::TEX_NUM_INDICES]; }; #endif diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 097c751386..fce4c29870 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -495,11 +495,11 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp if (lto && lto->getID() == old_id) { U32 local_texlayer_index = 0; /* can't keep that as static const, gives errors, so i'm leaving this var here */ - LLVOAvatarDefines::EBakedTextureIndex baked_texind = + LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind = lto->getTexLayer(local_texlayer_index)->getTexLayerSet()->getBakedTexIndex(); - LLVOAvatarDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind); - if (reg_texind != LLVOAvatarDefines::TEX_NUM_INDICES) + LLAvatarAppearanceDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind); + if (reg_texind != LLAvatarAppearanceDefines::TEX_NUM_INDICES) { U32 index = gAgentWearables.getWearableIndex(wearable); gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index); @@ -515,10 +515,10 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp } } -LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( - LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind) +LLAvatarAppearanceDefines::ETextureIndex LLLocalBitmap::getTexIndex( + LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind) { - LLVOAvatarDefines::ETextureIndex result = LLVOAvatarDefines::TEX_NUM_INDICES; // using as a default/fail return. + LLAvatarAppearanceDefines::ETextureIndex result = LLAvatarAppearanceDefines::TEX_NUM_INDICES; // using as a default/fail return. switch(type) { @@ -526,32 +526,32 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_EYES: + case LLAvatarAppearanceDefines::BAKED_EYES: { - result = LLVOAvatarDefines::TEX_EYES_ALPHA; + result = LLAvatarAppearanceDefines::TEX_EYES_ALPHA; break; } - case LLVOAvatarDefines::BAKED_HAIR: + case LLAvatarAppearanceDefines::BAKED_HAIR: { - result = LLVOAvatarDefines::TEX_HAIR_ALPHA; + result = LLAvatarAppearanceDefines::TEX_HAIR_ALPHA; break; } - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_ALPHA; + result = LLAvatarAppearanceDefines::TEX_HEAD_ALPHA; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_ALPHA; + result = LLAvatarAppearanceDefines::TEX_LOWER_ALPHA; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_ALPHA; + result = LLAvatarAppearanceDefines::TEX_UPPER_ALPHA; break; } @@ -567,9 +567,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_EYES: { - if (baked_texind == LLVOAvatarDefines::BAKED_EYES) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_EYES) { - result = LLVOAvatarDefines::TEX_EYES_IRIS; + result = LLAvatarAppearanceDefines::TEX_EYES_IRIS; } break; @@ -577,9 +577,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_GLOVES: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_GLOVES; + result = LLAvatarAppearanceDefines::TEX_UPPER_GLOVES; } break; @@ -587,13 +587,13 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_JACKET: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_JACKET; + result = LLAvatarAppearanceDefines::TEX_LOWER_JACKET; } - else if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + else if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_JACKET; + result = LLAvatarAppearanceDefines::TEX_UPPER_JACKET; } break; @@ -601,9 +601,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_PANTS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_PANTS; + result = LLAvatarAppearanceDefines::TEX_LOWER_PANTS; } break; @@ -611,9 +611,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SHIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_SHIRT; + result = LLAvatarAppearanceDefines::TEX_UPPER_SHIRT; } break; @@ -621,9 +621,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SHOES: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_SHOES; + result = LLAvatarAppearanceDefines::TEX_LOWER_SHOES; } break; @@ -633,20 +633,20 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_HEAD_BODYPAINT; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_LOWER_BODYPAINT; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_BODYPAINT; + result = LLAvatarAppearanceDefines::TEX_UPPER_BODYPAINT; break; } @@ -661,9 +661,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SKIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_SKIRT) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_SKIRT) { - result = LLVOAvatarDefines::TEX_SKIRT; + result = LLAvatarAppearanceDefines::TEX_SKIRT; } break; @@ -671,9 +671,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_SOCKS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_SOCKS; + result = LLAvatarAppearanceDefines::TEX_LOWER_SOCKS; } break; @@ -683,20 +683,20 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( { switch(baked_texind) { - case LLVOAvatarDefines::BAKED_HEAD: + case LLAvatarAppearanceDefines::BAKED_HEAD: { - result = LLVOAvatarDefines::TEX_HEAD_TATTOO; + result = LLAvatarAppearanceDefines::TEX_HEAD_TATTOO; break; } - case LLVOAvatarDefines::BAKED_LOWER: + case LLAvatarAppearanceDefines::BAKED_LOWER: { - result = LLVOAvatarDefines::TEX_LOWER_TATTOO; + result = LLAvatarAppearanceDefines::TEX_LOWER_TATTOO; break; } - case LLVOAvatarDefines::BAKED_UPPER: + case LLAvatarAppearanceDefines::BAKED_UPPER: { - result = LLVOAvatarDefines::TEX_UPPER_TATTOO; + result = LLAvatarAppearanceDefines::TEX_UPPER_TATTOO; break; } @@ -711,9 +711,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_UNDERPANTS: { - if (baked_texind == LLVOAvatarDefines::BAKED_LOWER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_LOWER) { - result = LLVOAvatarDefines::TEX_LOWER_UNDERPANTS; + result = LLAvatarAppearanceDefines::TEX_LOWER_UNDERPANTS; } break; @@ -721,9 +721,9 @@ LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex( case LLWearableType::WT_UNDERSHIRT: { - if (baked_texind == LLVOAvatarDefines::BAKED_UPPER) + if (baked_texind == LLAvatarAppearanceDefines::BAKED_UPPER) { - result = LLVOAvatarDefines::TEX_UPPER_UNDERSHIRT; + result = LLAvatarAppearanceDefines::TEX_UPPER_UNDERSHIRT; } break; diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index df031de3cb..ca12fe2045 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -30,7 +30,7 @@ #include "lleventtimer.h" #include "llwearabletype.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLScrollListCtrl; class LLViewerObject; @@ -64,7 +64,7 @@ class LLLocalBitmap void updateUserPrims(LLUUID old_id, LLUUID new_id); void updateUserSculpts(LLUUID old_id, LLUUID new_id); void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type); - LLVOAvatarDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind); + LLAvatarAppearanceDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind); private: /* private enums */ enum ELinkStatus diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 44b56afb1a..225996b5ce 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -104,7 +104,7 @@ enum ESubpart { SUBPART_PHYSICS_ADVANCED, }; -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; typedef std::vector subpart_vec_t; @@ -762,11 +762,11 @@ BOOL LLPanelEditWearable::postBuild() mWearablePtr = NULL; - configureAlphaCheckbox(LLVOAvatarDefines::TEX_LOWER_ALPHA, "lower alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_UPPER_ALPHA, "upper alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_HEAD_ALPHA, "head alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_EYES_ALPHA, "eye alpha texture invisible"); - configureAlphaCheckbox(LLVOAvatarDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_LOWER_ALPHA, "lower alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_UPPER_ALPHA, "upper alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_HEAD_ALPHA, "head alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_EYES_ALPHA, "eye alpha texture invisible"); + configureAlphaCheckbox(LLAvatarAppearanceDefines::TEX_HAIR_ALPHA, "hair alpha texture invisible"); // configure tab expanded callbacks for (U32 type_index = 0; type_index < (U32)LLWearableType::WT_COUNT; ++type_index) @@ -1505,7 +1505,7 @@ void LLPanelEditWearable::updateVerbs() } } -void LLPanelEditWearable::configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name) +void LLPanelEditWearable::configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name) { LLCheckBoxCtrl* checkbox = mPanelAlpha->getChild(name); checkbox->setCommitCallback(boost::bind(&LLPanelEditWearable::onInvisibilityCommit, this, checkbox, te)); @@ -1513,7 +1513,7 @@ void LLPanelEditWearable::configureAlphaCheckbox(LLVOAvatarDefines::ETextureInde mAlphaCheckbox2Index[name] = te; } -void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te) +void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te) { if (!checkbox_ctrl) return; if (!getWearable()) return; @@ -1557,7 +1557,7 @@ void LLPanelEditWearable::updateAlphaCheckboxes() for(string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin(); iter != mAlphaCheckbox2Index.end(); ++iter ) { - LLVOAvatarDefines::ETextureIndex te = (LLVOAvatarDefines::ETextureIndex)iter->second; + LLAvatarAppearanceDefines::ETextureIndex te = (LLAvatarAppearanceDefines::ETextureIndex)iter->second; LLCheckBoxCtrl* ctrl = mPanelAlpha->getChild(iter->first); if (ctrl) { @@ -1575,7 +1575,7 @@ void LLPanelEditWearable::initPreviousAlphaTextures() initPreviousAlphaTextureEntry(TEX_LOWER_ALPHA); } -void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te) +void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefines::ETextureIndex te) { LLLocalTextureObject *lto = getWearable()->getLocalTextureObject(te); if (lto) diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 85e43c8ebd..309d512e23 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -30,7 +30,7 @@ #include "llpanel.h" #include "llscrollingpanellist.h" #include "llmodaldialog.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "llwearabletype.h" class LLAccordionCtrl; @@ -95,11 +95,11 @@ private: void updateTypeSpecificControls(LLWearableType::EType type); //alpha mask checkboxes - void configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name); - void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te); + void configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name); + void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te); void updateAlphaCheckboxes(); void initPreviousAlphaTextures(); - void initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te); + void initPreviousAlphaTextureEntry(LLAvatarAppearanceDefines::ETextureIndex te); // callback for HeightUnits parameter. bool changeHeightUnits(const LLSD& new_value); @@ -165,10 +165,10 @@ private: LLPanel *mPanelTattoo; LLPanel *mPanelPhysics; - typedef std::map string_texture_index_map_t; + typedef std::map string_texture_index_map_t; string_texture_index_map_t mAlphaCheckbox2Index; - typedef std::map s32_uuid_map_t; + typedef std::map s32_uuid_map_t; s32_uuid_map_t mPreviousAlphaTexture; }; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 4611107bc2..070009fe9c 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -418,11 +418,11 @@ void LLAvatarTexBar::draw() LLColor4 color; U32 line_num = 1; - for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; const LLViewerTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 01a54509ef..2fc6de9d4d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -122,7 +122,7 @@ #include "llpathfindingmanager.h" #include "boost/unordered_map.hpp" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; typedef LLPointer LLViewerObjectPtr; @@ -7387,7 +7387,7 @@ void handle_grab_baked_texture(void* data) if(folder_id.notNull()) { std::string name; - name = "Baked " + LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; + name = "Baked " + LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; LLUUID item_id; item_id.generate(); diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 3a3cae4047..051aa41ed1 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -212,7 +212,7 @@ BOOL LLTexLayerSetBuffer::needsRender() } // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. - if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && + if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) { cancelUpload(); @@ -627,7 +627,7 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, if (result >= 0) { layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later - LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); + LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); // Update baked texture info with the new UUID U64 now = LLFrameTimer::getTotalTime(); // Record starting time llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 2b6649a7ec..0cd3ded371 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -35,11 +35,11 @@ #include "lltextureentry.h" #include "llviewertexlayer.h" #include "llvoavatarself.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "llviewerwearable.h" #include "llviewercontrol.h" -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; // support class - remove for 2.1 (hackity hack hack) class LLOverrideBakedTextureUpdate @@ -47,7 +47,7 @@ class LLOverrideBakedTextureUpdate public: LLOverrideBakedTextureUpdate(bool temp_state) { - U32 num_bakes = (U32) LLVOAvatarDefines::BAKED_NUM_INDICES; + U32 num_bakes = (U32) LLAvatarAppearanceDefines::BAKED_NUM_INDICES; for( U32 index = 0; index < num_bakes; ++index ) { composite_enabled[index] = gAgentAvatarp->isCompositeUpdateEnabled(index); @@ -57,14 +57,14 @@ public: ~LLOverrideBakedTextureUpdate() { - U32 num_bakes = (U32)LLVOAvatarDefines::BAKED_NUM_INDICES; + U32 num_bakes = (U32)LLAvatarAppearanceDefines::BAKED_NUM_INDICES; for( U32 index = 0; index < num_bakes; ++index ) { gAgentAvatarp->setCompositeUpdatesEnabled(index, composite_enabled[index]); } } private: - bool composite_enabled[LLVOAvatarDefines::BAKED_NUM_INDICES]; + bool composite_enabled[LLAvatarAppearanceDefines::BAKED_NUM_INDICES]; }; // Private local functions @@ -175,7 +175,7 @@ LLWearable::EImportResult LLViewerWearable::importFile( LLFILE* file ) LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( textureid ); if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) { - image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLVOAvatarDefines::ETextureIndex)te), NULL); + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLAvatarAppearanceDefines::ETextureIndex)te), NULL); } mTEMap[te] = new LLLocalTextureObject(image, textureid); mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); @@ -230,7 +230,7 @@ BOOL LLViewerWearable::isOldVersion() const S32 te_count = 0; for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { te_count++; if( !is_in_map(mTEMap, te ) ) @@ -282,7 +282,7 @@ BOOL LLViewerWearable::isDirty() const for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { te_map_t::const_iterator current_iter = mTEMap.find(te); if(current_iter != mTEMap.end()) @@ -328,7 +328,7 @@ void LLViewerWearable::setTexturesToDefaults() { for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { LLUUID id = getDefaultTextureImageID((ETextureIndex) te); LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id ); @@ -352,7 +352,7 @@ void LLViewerWearable::setTexturesToDefaults() //static const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); const std::string &default_image_name = texture_dict->mDefaultImageName; if (default_image_name == "") { @@ -389,7 +389,7 @@ void LLViewerWearable::writeToAvatar() // Pull texture entries for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { te_map_t::const_iterator iter = mTEMap.find(te); LLUUID image_id; @@ -492,7 +492,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) for (S32 te = 0; te < TEX_NUM_INDICES; te++) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { te_map_t::const_iterator iter = src->mTEMap.find(te); LLUUID image_id; @@ -678,7 +678,7 @@ void LLViewerWearable::syncImages(te_map_t &src, te_map_t &dst) // Deep copy of src (copies only those tes that are current, filling in defaults where needed) for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType) { te_map_t::const_iterator iter = src.find(te); LLUUID image_id; diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index a921f82e7d..ccc26000f2 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -28,7 +28,7 @@ #define LL_VIEWER_WEARABLE_H #include "llwearable.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" class LLViewerWearable : public LLWearable { @@ -68,7 +68,7 @@ public: void setParamsToDefaults(); void setTexturesToDefaults(); - static const LLUUID getDefaultTextureImageID(LLVOAvatarDefines::ETextureIndex index); + static const LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index); void saveNewAsset() const; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e3d8f9135e..56ded53b5d 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -118,7 +118,7 @@ extern F32 ANIM_SPEED_MIN; // #define OUTPUT_BREAST_DATA -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; //----------------------------------------------------------------------------- // Global constants @@ -597,7 +597,7 @@ LLXmlTree LLVOAvatar::sXMLTree; LLXmlTree LLVOAvatar::sSkeletonXMLTree; LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; -LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; +LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; U32 LLVOAvatar::sMaxVisible = 12; F32 LLVOAvatar::sRenderDistance = 256.f; @@ -711,7 +711,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureDatas[i].mIsLoaded = false; mBakedTextureDatas[i].mIsUsed = false; mBakedTextureDatas[i].mMaskTexName = 0; - mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); + mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); } mDirtyMesh = 2; // Dirty geometry, need to regenerate. @@ -1073,15 +1073,15 @@ void LLVOAvatar::dumpBakedStatus() { llcont << " Unbaked ("; - for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++iter) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; if (!inst->isTextureDefined(index)) { - llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName; + llcont << " " << LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName; } } llcont << " ) " << inst->getUnbakedPixelAreaRank(); @@ -1282,12 +1282,12 @@ void LLVOAvatar::initInstance(void) //------------------------------------------------------------------------- mRoot.setName( "mRoot" ); - for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); ++iter) { const EMeshIndex mesh_index = iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; LLViewerJoint* joint = new LLViewerJoint(); joint->setName(mesh_dict->mName); joint->setMeshID(mesh_index); @@ -1328,12 +1328,12 @@ void LLVOAvatar::initInstance(void) //------------------------------------------------------------------------- // associate baked textures with meshes //------------------------------------------------------------------------- - for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); ++iter) { const EMeshIndex mesh_index = iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; // Skip it if there's no associated baked texture. if (baked_texture_index == BAKED_NUM_INDICES) continue; @@ -4565,7 +4565,7 @@ void LLVOAvatar::updateTextures() mHasGrey = FALSE; // debug for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); const LLTextureEntry *te = getTE(texture_index); const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); @@ -4575,7 +4575,7 @@ void LLVOAvatar::updateTextures() imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; if (texture_dict->mIsLocalTexture) { @@ -4736,7 +4736,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) std::string url = ""; if (mUseServerBakes && !gSavedSettings.getString("AgentAppearanceServiceURL").empty()) { - const LLVOAvatarDictionary::TextureEntry* texture_entry = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)te); + const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); if (texture_entry != NULL) { url = gSavedSettings.getString("AgentAppearanceServiceURL") + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); @@ -5515,7 +5515,7 @@ BOOL LLVOAvatar::loadAvatar() { LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter; - EBakedTextureIndex baked = LLVOAvatarDictionary::findBakedByRegionName(info->mRegion); + EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); if (baked != BAKED_NUM_INDICES) { LLPolyMorphTarget *morph_param; @@ -5723,12 +5723,12 @@ BOOL LLVOAvatar::loadMeshNodes() switch(lod) case 0: mesh = &mHairMesh0; */ - for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); - mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); + mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); ++mesh_iter) { const EMeshIndex mesh_index = mesh_iter->first; - const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second; if (type.compare(mesh_dict->mName) == 0) { mesh_id = mesh_index; @@ -6815,12 +6815,12 @@ void LLVOAvatar::updateMeshTextures() } - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); @@ -6848,7 +6848,7 @@ void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, B } //virtual -void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatar::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { // invalid for anyone but self llassert(0); @@ -6894,7 +6894,7 @@ void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* mor } // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise -BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index) +BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index) { if (index >= BAKED_NUM_INDICES) { @@ -6920,7 +6920,7 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde return FALSE; } -void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index) +void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index) { if (index >= BAKED_NUM_INDICES) { @@ -6959,7 +6959,7 @@ void LLVOAvatar::releaseComponentTextures() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLVOAvatarDictionary::BakedEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID if (!isTextureDefined(bakedDicEntry->mTextureIndex) && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) @@ -6978,11 +6978,11 @@ void LLVOAvatar::releaseComponentTextures() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; // TODO: MULTI-WEARABLE: handle multiple textures for self const LLViewerTexture* te_image = getImage(iter->first,0); if( !te_image ) @@ -7027,11 +7027,11 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const /* switch(type) case LLWearableType::WT_SHIRT: indicator_te = TEX_UPPER_SHIRT; */ - for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++tex_iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; if (texture_dict->mWearableType == type) { // If you're checking another avatar's clothing, you don't have component textures. @@ -7042,7 +7042,7 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const if (texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); + return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); } return FALSE; } @@ -7495,12 +7495,12 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; */ BOOL found_texture_id = false; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsUsedByBakedTexture) { const ETextureIndex texture_index = iter->first; @@ -7622,7 +7622,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) { //mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); } - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) @@ -7684,7 +7684,7 @@ void LLVOAvatar::dumpArchetypeXML( void* ) for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type) + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0); @@ -8491,7 +8491,7 @@ void LLVOAvatar::idleUpdateRenderCost() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); ETextureIndex tex_index = baked_dict->mTextureIndex; if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) { @@ -8571,11 +8571,11 @@ void LLVOAvatar::idleUpdateRenderCost() } // print any avatar textures we didn't already know about - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; // TODO: MULTI-WEARABLE: handle multiple textures for self const LLViewerTexture* te_image = getImage(iter->first,0); if (!te_image) @@ -8604,26 +8604,26 @@ void LLVOAvatar::idleUpdateRenderCost() BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; } // static BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { if (index < 0 || index >= TEX_NUM_INDICES) return false; - return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + return LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const { std::string line; - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsBakedTexture) { line += texture_dict->mName; @@ -8655,7 +8655,7 @@ F32 calc_bouncy_animation(F32 x) } //virtual -BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index ) const +BOOL LLVOAvatar::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index ) const { if (isIndexLocalTexture(te)) { @@ -8667,7 +8667,7 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index } //virtual -BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (isIndexLocalTexture(type)) { @@ -8683,7 +8683,7 @@ BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 ind } //virtual -BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const +BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { // non-self avatars don't have wearables return FALSE; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 512522803a..644ea22b53 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -45,7 +45,7 @@ #include "llviewerjointmesh.h" #include "llviewerjointattachment.h" #include "llrendertarget.h" -#include "llvoavatardefines.h" +#include "llavatarappearancedefines.h" #include "lltexglobalcolor.h" #include "lldriverparam.h" #include "material_codes.h" // LL_MCODE_END @@ -472,9 +472,9 @@ private: // Morph masks //-------------------------------------------------------------------- public: - BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); - void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); + BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); + virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); //-------------------------------------------------------------------- @@ -582,9 +582,9 @@ public: // Loading status //-------------------------------------------------------------------- public: - virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const; + virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + virtual BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const; BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); @@ -610,7 +610,7 @@ protected: LLViewerTexLayerSet* mTexLayerSet; // Only exists for self bool mIsLoaded; bool mIsUsed; - LLVOAvatarDefines::ETextureIndex mTextureIndex; + LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts @@ -624,10 +624,10 @@ protected: // Local Textures //-------------------------------------------------------------------- protected: - virtual void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); - virtual void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); + virtual void setLocalTexture(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); + virtual void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); // MULTI-WEARABLE: make self-only? - virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); + virtual void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); //-------------------------------------------------------------------- // Texture accessors @@ -662,11 +662,11 @@ public: // Static texture/mesh/baked dictionary //-------------------------------------------------------------------- public: - static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); - static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); + static BOOL isIndexLocalTexture(LLAvatarAppearanceDefines::ETextureIndex i); + static BOOL isIndexBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i); private: - static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } - static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary; + static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } + static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; static LLVOAvatarXmlInfo* sAvatarXmlInfo; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0fcf43a501..b300cfc71c 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -112,7 +112,7 @@ void selfStopAllPhases() } } -using namespace LLVOAvatarDefines; +using namespace LLAvatarAppearanceDefines; /********************************************************************************* ** ** @@ -190,7 +190,7 @@ void LLVOAvatarSelf::initInstance() llinfos << "Self avatar object created. Starting timer." << llendl; mDebugSelfLoadTimer.reset(); // clear all times to -1 for debugging - for (U32 i =0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + for (U32 i =0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) { for (U32 j = 0; j <= MAX_DISCARD_LEVEL; ++j) { @@ -198,7 +198,7 @@ void LLVOAvatarSelf::initInstance() } } - for (U32 i =0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + for (U32 i =0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) { mDebugBakedTextureTimes[i][0] = -1.0f; mDebugBakedTextureTimes[i][1] = -1.0f; @@ -609,11 +609,11 @@ BOOL LLVOAvatarSelf::loadLayersets() // scan baked textures and associate the layerset with the appropriate one EBakedTextureIndex baked_index = BAKED_NUM_INDICES; - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; if (layer_set->isBodyRegion(baked_dict->mName)) { baked_index = baked_iter->first; @@ -819,7 +819,7 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, // need to trigger a few operations to get the avatar to use the new bakes for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; + const LLAvatarAppearanceDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex; LLUUID texture_id = getTEImage(te)->getID(); setNewBakedTexture(te, texture_id); mInitialBakeIDs[i] = texture_id; @@ -1074,16 +1074,16 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) //----------------------------------------------------------------------------- void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_result ) { - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; - const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDefines::EBakedTextureIndex index = baked_iter->first; if (baked_dict) { - for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); + for (LLAvatarAppearanceDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); type_iter != baked_dict->mWearables.end(); ++type_iter) { @@ -1306,9 +1306,9 @@ BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) return FALSE; } -U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const +U32 LLVOAvatarSelf::getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const { - LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); return gAgentWearables.getWearableCount(type); } @@ -1381,7 +1381,7 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex return TRUE; } -LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const +LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (!isIndexLocalTexture(type)) { @@ -1422,21 +1422,21 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* laye { /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) { BOOL ret = true; - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -1465,13 +1465,13 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset { if (layerset == mBakedTextureDatas[i].mTexLayerSet) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -1495,13 +1495,13 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -1515,7 +1515,7 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const return TRUE; } -BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const +BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const { const LLViewerTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; if (!layerset) return FALSE; @@ -1524,13 +1524,13 @@ BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureI return !layerset_buffer->uploadNeeded(); } -BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { LLUUID id; BOOL isDefined = TRUE; if (isIndexLocalTexture(type)) { - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(type); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(type); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (index >= wearable_count) { @@ -1557,7 +1557,7 @@ BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 } //virtual -BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const +BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { if (isIndexBakedTexture(type)) { @@ -1570,7 +1570,7 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 } //virtual -BOOL LLVOAvatarSelf::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const +BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { if (isIndexBakedTexture(type)) { @@ -1593,7 +1593,7 @@ void LLVOAvatarSelf::requestLayerSetUploads() } } -void LLVOAvatarSelf::requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i) +void LLVOAvatarSelf::requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i) { ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); @@ -1779,7 +1779,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te llerrs << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << llendl; return; } - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(type); if (!gAgentWearables.getWearable(wearable_type,index)) { // no wearable is loaded, cannot set the texture. @@ -1839,7 +1839,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te setBakedReady(type,baked_version_ready,index); } //virtual -void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) +void LLVOAvatarSelf::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { if (!isIndexLocalTexture(type)) return; LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); @@ -1858,16 +1858,16 @@ void LLVOAvatarSelf::dumpLocalTextures() const /* ETextureIndex baked_equiv[] = { TEX_UPPER_BAKED, if (isTextureDefined(baked_equiv[i])) */ - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) continue; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; + const ETextureIndex baked_equiv = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; const std::string &name = texture_dict->mName; const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); @@ -2071,21 +2071,21 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str()); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { @@ -2112,14 +2112,14 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); BOOL is_texture_final = TRUE; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index); + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { @@ -2243,7 +2243,7 @@ const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) c { if (canGrabBakedTexture(baked_index)) { - ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return LLUUID::null; @@ -2255,7 +2255,7 @@ const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) c BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const { - ETextureIndex tex_index = LLVOAvatarDictionary::bakedToLocalTextureIndex(baked_index); + ETextureIndex tex_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(baked_index); if (tex_index == TEX_NUM_INDICES) { return FALSE; @@ -2274,13 +2274,13 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const // baked texture. We don't want people copying people's // work via baked textures. - const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); iter != baked_dict->mLocalTextures.end(); ++iter) { const ETextureIndex t_index = (*iter); - LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType(t_index); + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(t_index); U32 count = gAgentWearables.getWearableCount(wearable_type); lldebugs << "Checking index " << (U32) t_index << " count: " << count << llendl; @@ -2358,9 +2358,9 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe } } -LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const +LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const { - LLWearableType::EType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i); + LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); LLViewerWearable* wearable = gAgentWearables.getWearable(type, wearable_index); if (wearable) { @@ -2388,9 +2388,9 @@ ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset ) } -void LLVOAvatarSelf::setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid) +void LLVOAvatarSelf::setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid) { - ETextureIndex index = LLVOAvatarDictionary::bakedToLocalTextureIndex(i); + ETextureIndex index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(i); setNewBakedTexture(index, uuid); } @@ -2412,7 +2412,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) /* switch(te) case TEX_HEAD_BAKED: llinfos << "New baked texture: HEAD" << llendl; */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(te); if (texture_dict->mIsBakedTexture) { debugBakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish. @@ -2477,7 +2477,7 @@ void LLVOAvatarSelf::outputRezDiagnostics() const LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl; - for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + for (U32 i = 0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) { std::stringstream out; out << "\t\t (" << i << ") "; @@ -2505,16 +2505,16 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } } LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl; - for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + for (U32 i = 0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) { LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; } - for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { - const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); @@ -2583,12 +2583,12 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = TEX_HEAD_BAKED, TEX_UPPER_BAKED, */ - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (texture_dict->mIsBakedTexture) { if (texture_id == gAgentAvatarp->getTEImage(index)->getID()) @@ -2657,7 +2657,7 @@ void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) case LOCTEX_UPPER_SHIRT: if( mUpperBodyLayerSet ) mUpperBodyLayerSet->requestUpdate(); */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) return; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -2673,7 +2673,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const case TEX_HEAD_BAKED: case TEX_HEAD_BODYPAINT: return mHeadLayerSet; */ - const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); if (texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; @@ -2747,12 +2747,12 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { LLUUID texture_id[TEX_NUM_INDICES]; // pack away current TEs to make sure we don't send them out - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsBakedTexture) { LLTextureEntry* entry = getTE((U8) index); @@ -2764,12 +2764,12 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const bool success = packTEMessage(mesgsys); // unpack TEs to make sure we don't re-trigger a bake - for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); - iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; - const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; if (!texture_dict->mIsBakedTexture) { LLTextureEntry* entry = getTE((U8) index); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 26662e8a25..d4bde1f61f 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -195,32 +195,32 @@ public: //-------------------------------------------------------------------- public: /*virtual*/ bool hasPendingBakedUploads() const; - S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + S32 getLocalDiscardLevel(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; bool areTexturesCurrent() const; BOOL isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const; BOOL isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const; - BOOL isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureIndex index) const; + BOOL isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const; // If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index - /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const; - /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - /*virtual*/ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLViewerWearable *wearable) const; + /*virtual*/ BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; + /*virtual*/ BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index = 0) const; + /*virtual*/ BOOL isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- public: - BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; - LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const; - const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const; + BOOL getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; + LLViewerFetchedTexture* getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; + const LLUUID& getLocalTextureID(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const; void setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index); - /*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); + /*virtual*/ void setLocalTexture(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); protected: - /*virtual*/ void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); + /*virtual*/ void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void getLocalTextureByteCount(S32* gl_byte_count) const; - /*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index); - LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index) const; + /*virtual*/ void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index); + LLLocalTextureObject* getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 index) const; private: static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); @@ -233,10 +233,10 @@ private: // Baked textures //-------------------------------------------------------------------- public: - LLVOAvatarDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const; - void setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid); - void setNewBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); - void setCachedBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid); + LLAvatarAppearanceDefines::ETextureIndex getBakedTE(const LLViewerTexLayerSet* layerset ) const; + void setNewBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex i, const LLUUID &uuid); + void setNewBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid); + void setCachedBakedTexture(LLAvatarAppearanceDefines::ETextureIndex i, const LLUUID& uuid); void forceBakeAllTextures(bool slam_for_debug = false); static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); protected: @@ -247,10 +247,10 @@ protected: //-------------------------------------------------------------------- public: void requestLayerSetUploads(); - void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i); - void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); - LLViewerTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; - LLViewerTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + void requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedTextureIndex i); + void requestLayerSetUpdate(LLAvatarAppearanceDefines::ETextureIndex i); + LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::ETextureIndex index) const; + LLViewerTexLayerSet* getLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- // Composites @@ -264,8 +264,8 @@ public: void setupComposites(); void updateComposites(); - const LLUUID& grabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; - BOOL canGrabBakedTexture(LLVOAvatarDefines::EBakedTextureIndex baked_index) const; + const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; //-------------------------------------------------------------------- @@ -302,7 +302,7 @@ public: /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type) const; void wearableUpdated(LLWearableType::EType type, BOOL upload_result); protected: - U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; + U32 getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const; //-------------------------------------------------------------------- // Attachments @@ -371,24 +371,24 @@ public: public: struct LLAvatarTexData { - LLAvatarTexData(const LLUUID& id, LLVOAvatarDefines::ETextureIndex index) : + LLAvatarTexData(const LLUUID& id, LLAvatarAppearanceDefines::ETextureIndex index) : mAvatarID(id), mIndex(index) {} LLUUID mAvatarID; - LLVOAvatarDefines::ETextureIndex mIndex; + LLAvatarAppearanceDefines::ETextureIndex mIndex; }; void debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); } void debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); } void outputRezDiagnostics() const; void outputRezTiming(const std::string& msg) const; void reportAvatarRezTime() const; - void debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished); + void debugBakedTextureUpload(LLAvatarAppearanceDefines::EBakedTextureIndex index, BOOL finished); static void debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); BOOL isAllLocalTextureDataFinal() const; - const LLViewerTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } + const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD LLSD metricsData(); @@ -397,8 +397,8 @@ private: LLFrameTimer mDebugSelfLoadTimer; F32 mDebugTimeWearablesLoaded; F32 mDebugTimeAvatarVisible; - F32 mDebugTextureLoadTimes[LLVOAvatarDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // load time for each texture at each discard level - F32 mDebugBakedTextureTimes[LLVOAvatarDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture + F32 mDebugTextureLoadTimes[LLAvatarAppearanceDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // load time for each texture at each discard level + F32 mDebugBakedTextureTimes[LLAvatarAppearanceDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture void debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); /** Diagnostics -- cgit v1.2.3 From eb13b2b4680ab80e8a20d341a481b8c1d62ca156 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Mon, 3 Sep 2012 17:42:20 +0300 Subject: CHUI-307 FIXED (LLInitParam::Parser::parserWarnings in log when adding conversations or deleting entries from conversation log ) - removed redundant incorrect attributes --- indra/newview/skins/default/xui/en/panel_blocked_list_item.xml | 1 - .../newview/skins/default/xui/en/panel_conversation_log_list_item.xml | 3 --- 2 files changed, 4 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml index 84e7e467b1..752321b949 100644 --- a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -60,7 +60,6 @@ Date: Mon, 3 Sep 2012 17:52:54 +0300 Subject: CHUI-314 FIXED (Update Save IM logs on my computer setting to also control populatoin of conversation log) - Now LLConversationLog is optionally listener of IMSession, dependently on "LogInstantMessages" per account setting, saving of call log to file also depends on this setting. Which means that with the Save IM logs on my computer disabled: IM logs for the user will not be saved to their computer and conversations will not be logged to the conversation log. --- indra/newview/llappviewer.cpp | 5 ++++- indra/newview/llconversationlog.cpp | 27 +++++++++++++++++++++++++-- indra/newview/llconversationlog.h | 2 ++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 08a1a237f5..4dacde4792 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1834,7 +1834,10 @@ bool LLAppViewer::cleanup() LLMuteList::getInstance()->cache(gAgent.getID()); //save call log list - LLConversationLog::instance().cache(); + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + LLConversationLog::instance().cache(); + } if (mPurgeOnExit) { diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 23ccc78a0f..7db6a93709 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -185,11 +185,34 @@ LLConversationLog::LLConversationLog() { loadFromFile(getFileName()); - LLIMMgr::instance().addSessionObserver(this); - + LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLConversationLog::observeIMSession, this)); + + if (ctrl->getValue().asBoolean()) + { + LLIMMgr::instance().addSessionObserver(this); + } + } + mFriendObserver = new LLConversationLogFriendObserver; LLAvatarTracker::instance().addObserver(mFriendObserver); + } + +void LLConversationLog::observeIMSession() +{ + if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + { + LLIMMgr::instance().addSessionObserver(this); + } + else + { + LLIMMgr::instance().removeSessionObserver(this); + } +} + void LLConversationLog::logConversation(const LLConversation& conversation) { mConversations.push_back(conversation); diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index f2b6a67c92..9fd54c61c9 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -145,6 +145,8 @@ private: LLConversationLog(); + void observeIMSession(); + /** * constructs file name in which conversations log will be saved * file name is conversation.log -- cgit v1.2.3 From 7b4385420edf3f431ddc4a7042bbc9623ffedd34 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 4 Sep 2012 04:24:47 +0000 Subject: More clean-up to closer match original file order. For llavatarappearance diffs --- indra/llappearance/llavatarappearance.h | 95 +++++++++++++++++++++--------- indra/llappearance/llinventoryicon.cpp | 1 - indra/llappearance/lltexglobalcolor.cpp | 2 - indra/llappearance/llviewervisualparam.cpp | 1 - indra/llappearance/llwearabletype.cpp | 1 - indra/newview/lltexturefetch.cpp | 3 +- indra/newview/llvoavatar.h | 1 - indra/newview/llwearablelist.cpp | 4 +- 8 files changed, 71 insertions(+), 37 deletions(-) diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 0ab3960e64..e882868e91 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -31,8 +31,8 @@ #include "llframetimer.h" #include "llavatarappearancedefines.h" -class LLTexGlobalColor; class LLTexLayerSet; +class LLTexGlobalColor; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLAvatarAppearance @@ -43,27 +43,36 @@ class LLAvatarAppearance : public LLCharacter { LOG_CLASS(LLAvatarAppearance); +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ + public: LLAvatarAppearance(); - //-------------------------------------------------------------------- - // Clothing colors (convenience functions to access visual parameters) - //-------------------------------------------------------------------- -public: - void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); - LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); - static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); +/** Initialization + ** ** + *******************************************************************************/ - //-------------------------------------------------------------------- - // Global colors - //-------------------------------------------------------------------- +/******************************************************************************** + ** ** + ** STATE + **/ public: - LLColor4 getGlobalColor(const std::string& color_name ) const; - virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0; -protected: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; + virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + virtual BOOL isUsingBakedTextures() const = 0; + +/** State + ** ** + *******************************************************************************/ + + +/******************************************************************************** + ** ** + ** RENDERING + **/ + BOOL mIsDummy; // for special views //-------------------------------------------------------------------- // Morph masks @@ -71,6 +80,10 @@ protected: public: virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; +/** Rendering + ** ** + *******************************************************************************/ + //-------------------------------------------------------------------- // Composites //-------------------------------------------------------------------- @@ -81,39 +94,65 @@ public: ** ** ** MESHES **/ + +public: + virtual void updateMeshTextures() = 0; virtual void dirtyMesh() = 0; // Dirty the avatar mesh +protected: virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority -/******************************************************************************** +/** Meshes ** ** - ** RENDERING - **/ - BOOL mIsDummy; // for special views + *******************************************************************************/ /******************************************************************************** ** ** - ** STATE + ** APPEARANCE **/ + + //-------------------------------------------------------------------- + // Clothing colors (convenience functions to access visual parameters) + //-------------------------------------------------------------------- public: - virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent - virtual BOOL isUsingBakedTextures() const = 0; + void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); + LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); + static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + LLColor4 getGlobalColor(const std::string& color_name ) const; + virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0; +protected: + LLTexGlobalColor* mTexSkinColor; + LLTexGlobalColor* mTexHairColor; + LLTexGlobalColor* mTexEyeColor; + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + static LLColor4 getDummyColor(); +/** Appearance + ** ** + *******************************************************************************/ /******************************************************************************** ** ** ** WEARABLES **/ + public: + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const = 0; + virtual U32 getWearableCount(const LLWearableType::EType type) const = 0; virtual U32 getWearableCount(const U32 tex_index) const = 0; virtual LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) = 0; virtual const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const = 0; - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const = 0; -public: - static LLColor4 getDummyColor(); - virtual void updateMeshTextures() = 0; }; #endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/llappearance/llinventoryicon.cpp b/indra/llappearance/llinventoryicon.cpp index 62261058ef..371f60353b 100644 --- a/indra/llappearance/llinventoryicon.cpp +++ b/indra/llappearance/llinventoryicon.cpp @@ -24,7 +24,6 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" #include "llinventoryicon.h" diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index d9c6150fc6..f38b982104 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -25,10 +25,8 @@ */ #include "linden_common.h" - #include "llavatarappearance.h" #include "lltexlayer.h" -//#include "llwearable.h" #include "lltexglobalcolor.h" class LLWearable; diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index e1ddeeeff0..a6792d0974 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -27,7 +27,6 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" #include "llviewervisualparam.h" diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 009a3b631a..c72a0965fe 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -25,7 +25,6 @@ */ #include "linden_common.h" - #include "llwearabletype.h" #include "llinventoryicon.h" #include "lltrans.h" diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 7adf5212c2..16baefac4f 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -973,7 +973,8 @@ bool LLTextureFetchWorker::doWork(S32 param) } else if(!mUrl.empty() && mCanUseHTTP) { - if (!(mUrl.compare(0, 7, "http://") == 0)) + if (!(mUrl.compare(0, 7, "http://") == 0) && + !(mUrl.compare(0, 8, "https://") == 0)) { // *TODO:?remove this warning llwarns << "Unknown URL Type: " << mUrl << llendl; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 644ea22b53..d54d06a6a7 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -454,7 +454,6 @@ public: static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); - BOOL mIsDummy; // for special views S32 mSpecialRenderMode; // special lighting U32 mAttachmentGeometryBytes; //number of bytes in attached geometry F32 mAttachmentSurfaceArea; //estimated surface area of attachments diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 9f04fbecf0..6c4790ad77 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -112,8 +112,8 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID else { wearable = new LLViewerWearable(uuid); - bool res = wearable->importFile( fp ); - if (!res) + LLWearable::EImportResult result = wearable->importFile( fp ); + if (LLWearable::SUCCESS != result) { if (wearable->getType() == LLWearableType::WT_COUNT) { -- cgit v1.2.3 From 204be2ba5261d794f8264e004b65725450bf1be9 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 4 Sep 2012 15:18:15 +0000 Subject: Split LLTexLayerSetBuffer into llappearance portion, and viewer-specific LLViewerTexLayerSetBuffer --- indra/llappearance/lltexlayer.cpp | 109 +++++++++++++ indra/llappearance/lltexlayer.h | 37 +++++ indra/llrender/lltexture.h | 2 +- indra/newview/llassetuploadresponders.cpp | 8 +- indra/newview/lldynamictexture.h | 4 +- indra/newview/lltextureview.cpp | 2 +- indra/newview/llviewerjointmesh.cpp | 2 +- indra/newview/llviewerstats.cpp | 2 +- indra/newview/llviewertexlayer.cpp | 260 ++++++++++++------------------ indra/newview/llviewertexlayer.h | 58 ++++--- indra/newview/llvoavatar.cpp | 2 +- indra/newview/llvoavatarself.cpp | 6 +- 12 files changed, 295 insertions(+), 197 deletions(-) diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index bf2fd1e30d..0d3219c4e0 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -40,6 +40,7 @@ #include "lltexturemanagerbridge.h" #include "llui.h" #include "llwearable.h" +#include "llvertexbuffer.h" #include "llviewervisualparam.h" //#include "../tools/imdebug/imdebug.h" @@ -89,6 +90,92 @@ private: param_alpha_info_list_t mParamAlphaInfoList; }; +//----------------------------------------------------------------------------- +// LLTexLayerSetBuffer +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. +//----------------------------------------------------------------------------- + +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) : + mTexLayerSet(owner) +{ +} + +LLTexLayerSetBuffer::~LLTexLayerSetBuffer() +{ +} + +void LLTexLayerSetBuffer::pushProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); +} + +void LLTexLayerSetBuffer::popProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); +} + +// virtual +void LLTexLayerSetBuffer::preRenderTexLayerSet() +{ + // Set up an ortho projection + pushProjection(); +} + +// virtual +void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) +{ + popProjection(); +} + +BOOL LLTexLayerSetBuffer::renderTexLayerSet() +{ + // Default color mask for tex layer render + gGL.setColorMask(true, true); + + BOOL success = TRUE; + + bool use_shaders = LLGLSLShader::sNoFixedFunction; + + if (use_shaders) + { + gAlphaMaskProgram.bind(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + LLVertexBuffer::unbind(); + + // Composite the color data + LLGLSUIDefault gls_ui; + success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), + getCompositeWidth(), getCompositeHeight() ); + gGL.flush(); + + midRenderTexLayerSet(success); + + if (use_shaders) + { + gAlphaMaskProgram.unbind(); + } + + LLVertexBuffer::unbind(); + + // reset GL state + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + return success; +} //----------------------------------------------------------------------------- // LLTexLayerSetInfo @@ -381,6 +468,28 @@ const std::string LLTexLayerSet::getBodyRegionName() const } +void LLTexLayerSet::destroyComposite() +{ + if( mComposite ) + { + mComposite = NULL; + } +} + +LLTexLayerSetBuffer* LLTexLayerSet::getComposite() +{ + if (!mComposite) + { + createComposite(); + } + return mComposite; +} + +const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const +{ + return mComposite; +} + void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { const LLTexLayerSetInfo *info = getInfo(); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 5a413e929f..4f2ee5b045 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -40,6 +40,7 @@ class LLXmlTreeNode; class LLTexLayerSet; class LLTexLayerSetInfo; class LLTexLayerInfo; +class LLTexLayerSetBuffer; class LLWearable; class LLViewerVisualParam; @@ -178,10 +179,16 @@ private: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLTexLayerSet { + friend class LLTexLayerSetBuffer; public: LLTexLayerSet(LLAvatarAppearance* const appearance); virtual ~LLTexLayerSet(); + LLTexLayerSetBuffer* getComposite(); + const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. + virtual void createComposite() = 0; + void destroyComposite(); + const LLTexLayerSetInfo* getInfo() const { return mInfo; } BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions @@ -199,6 +206,7 @@ public: LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } const std::string getBodyRegionName() const; + BOOL hasComposite() const { return (mComposite.notNull()); } LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } BOOL isVisible() const { return mIsVisible; } @@ -209,6 +217,7 @@ protected: typedef std::vector layer_list_t; layer_list_t mLayerList; layer_list_t mMaskLayerList; + LLPointer mComposite; LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. BOOL mIsVisible; @@ -241,6 +250,34 @@ protected: layer_info_list_t mLayerInfoList; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSetBuffer +// +// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSetBuffer : public virtual LLRefCount +{ + LOG_CLASS(LLTexLayerSetBuffer); + +public: + LLTexLayerSetBuffer(LLTexLayerSet* const owner); + virtual ~LLTexLayerSetBuffer(); + +protected: + void pushProjection() const; + void popProjection() const; + virtual void preRenderTexLayerSet(); + virtual void midRenderTexLayerSet(BOOL success) {} + virtual void postRenderTexLayerSet(BOOL success); + virtual S32 getCompositeOriginX() const = 0; + virtual S32 getCompositeOriginY() const = 0; + virtual S32 getCompositeWidth() const = 0; + virtual S32 getCompositeHeight() const = 0; + BOOL renderTexLayerSet(); + + LLTexLayerSet* const mTexLayerSet; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLTexLayerStaticImageList // diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index a23aa72520..40245968d1 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -43,7 +43,7 @@ class LLImageRaw ; //this is an abstract class as the parent for the class LLViewerTexture //through the following virtual functions, the class LLViewerTexture can be reached from /llrender. // -class LLTexture : public LLRefCount +class LLTexture : public virtual LLRefCount { friend class LLTexUnit ; friend class LLFontGL ; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 35e44d73d4..7c423af3c8 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -456,7 +456,7 @@ LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, LLSendTexLayerResponder::~LLSendTexLayerResponder() { - // mBakedUploadData is normally deleted by calls to LLTexLayerSetBuffer::onTextureUploadComplete() below + // mBakedUploadData is normally deleted by calls to LLViewerTexLayerSetBuffer::onTextureUploadComplete() below if (mBakedUploadData) { // ...but delete it in the case where uploadComplete() is never called delete mBakedUploadData; @@ -477,12 +477,12 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) if (result == "complete" && mBakedUploadData != NULL) { // Invoke - LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } else { // Invoke the original callback with an error result - LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } } @@ -492,7 +492,7 @@ void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason) llinfos << "status: " << statusNum << " reason: " << reason << llendl; // Invoke the original callback with an error result - LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); mBakedUploadData = NULL; // deleted in onTextureUploadComplete() } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index c51e7d1e1a..d287ae6eeb 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -72,8 +72,8 @@ public: /*virtual*/ S8 getType() const ; - S32 getOriginX() { return mOrigin.mX; } - S32 getOriginY() { return mOrigin.mY; } + S32 getOriginX() const { return mOrigin.mX; } + S32 getOriginY() const { return mOrigin.mY; } S32 getSize() { return mFullWidth * mFullHeight * mComponents; } diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 070009fe9c..03529b9246 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -425,7 +425,7 @@ void LLAvatarTexBar::draw() const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; const LLViewerTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index); if (!layerset) continue; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) continue; LLColor4 text_color = LLColor4::white; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 79800c1df3..3532fac1bc 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -562,7 +562,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); + gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getViewerComposite()); } else { diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index f049130f3a..961c7082cf 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -519,7 +519,7 @@ void output_statistics(void*) llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl; LLTexLayerStaticImageList::getInstance()->dumpByteCount(); LLVOAvatarSelf::dumpScratchTextureByteCount(); - LLTexLayerSetBuffer::dumpTotalByteCount(); + LLViewerTexLayerSetBuffer::dumpTotalByteCount(); LLVOAvatarSelf::dumpTotalLocalTextureByteCount(); LLTexLayerParamAlpha::dumpCacheByteCount(); LLVOAvatar::dumpBakedStatus(); diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 051aa41ed1..69457ab1db 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -63,33 +63,33 @@ LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar, } //----------------------------------------------------------------------------- -// LLTexLayerSetBuffer +// LLViewerTexLayerSetBuffer // The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. //----------------------------------------------------------------------------- // static -S32 LLTexLayerSetBuffer::sGLByteCount = 0; +S32 LLViewerTexLayerSetBuffer::sGLByteCount = 0; -LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLViewerTexLayerSet* const owner, +LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height) : // ORDER_LAST => must render these after the hints are created. + LLTexLayerSetBuffer(owner), LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ), mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates mNeedsUpload(FALSE), mNumLowresUploads(0), mUploadFailCount(0), mNeedsUpdate(TRUE), - mNumLowresUpdates(0), - mTexLayerSet(owner) + mNumLowresUpdates(0) { - LLTexLayerSetBuffer::sGLByteCount += getSize(); + LLViewerTexLayerSetBuffer::sGLByteCount += getSize(); mNeedsUploadTimer.start(); mNeedsUpdateTimer.start(); } -LLTexLayerSetBuffer::~LLTexLayerSetBuffer() +LLViewerTexLayerSetBuffer::~LLViewerTexLayerSetBuffer() { - LLTexLayerSetBuffer::sGLByteCount -= getSize(); + LLViewerTexLayerSetBuffer::sGLByteCount -= getSize(); destroyGLTexture(); for( S32 order = 0; order < ORDER_COUNT; order++ ) { @@ -98,30 +98,30 @@ LLTexLayerSetBuffer::~LLTexLayerSetBuffer() } //virtual -S8 LLTexLayerSetBuffer::getType() const +S8 LLViewerTexLayerSetBuffer::getType() const { return LLViewerDynamicTexture::LL_TEX_LAYER_SET_BUFFER ; } //virtual -void LLTexLayerSetBuffer::restoreGLTexture() +void LLViewerTexLayerSetBuffer::restoreGLTexture() { LLViewerDynamicTexture::restoreGLTexture() ; } //virtual -void LLTexLayerSetBuffer::destroyGLTexture() +void LLViewerTexLayerSetBuffer::destroyGLTexture() { LLViewerDynamicTexture::destroyGLTexture() ; } // static -void LLTexLayerSetBuffer::dumpTotalByteCount() +void LLViewerTexLayerSetBuffer::dumpTotalByteCount() { - llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; + llinfos << "Composite System GL Buffers: " << (LLViewerTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; } -void LLTexLayerSetBuffer::requestUpdate() +void LLViewerTexLayerSetBuffer::requestUpdate() { restartUpdateTimer(); mNeedsUpdate = TRUE; @@ -131,7 +131,7 @@ void LLTexLayerSetBuffer::requestUpdate() mUploadID.setNull(); } -void LLTexLayerSetBuffer::requestUpload() +void LLViewerTexLayerSetBuffer::requestUpload() { conditionalRestartUploadTimer(); mNeedsUpload = TRUE; @@ -139,7 +139,7 @@ void LLTexLayerSetBuffer::requestUpload() mUploadPending = TRUE; } -void LLTexLayerSetBuffer::conditionalRestartUploadTimer() +void LLViewerTexLayerSetBuffer::conditionalRestartUploadTimer() { // If we requested a new upload but haven't even uploaded // a low res version of our last upload request, then @@ -155,13 +155,13 @@ void LLTexLayerSetBuffer::conditionalRestartUploadTimer() } } -void LLTexLayerSetBuffer::restartUpdateTimer() +void LLViewerTexLayerSetBuffer::restartUpdateTimer() { mNeedsUpdateTimer.reset(); mNeedsUpdateTimer.start(); } -void LLTexLayerSetBuffer::cancelUpload() +void LLViewerTexLayerSetBuffer::cancelUpload() { mNeedsUpload = FALSE; mUploadPending = FALSE; @@ -169,29 +169,8 @@ void LLTexLayerSetBuffer::cancelUpload() mUploadRetryTimer.reset(); } -void LLTexLayerSetBuffer::pushProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); -} - -void LLTexLayerSetBuffer::popProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); -} - // virtual -BOOL LLTexLayerSetBuffer::needsRender() +BOOL LLViewerTexLayerSetBuffer::needsRender() { llassert(mTexLayerSet->getAvatarAppearance() == gAgentAvatarp); if (!isAgentAvatarValid()) return FALSE; @@ -212,7 +191,7 @@ BOOL LLTexLayerSetBuffer::needsRender() } // Don't render if we are trying to create a shirt texture but aren't wearing a skirt. - if (gAgentAvatarp->getBakedTE(mTexLayerSet) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && + if (gAgentAvatarp->getBakedTE(getViewerTexLayerSet()) == LLAvatarAppearanceDefines::TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT)) { cancelUpload(); @@ -220,51 +199,36 @@ BOOL LLTexLayerSetBuffer::needsRender() } // Render if we have at least minimal level of detail for each local texture. - return mTexLayerSet->isLocalTextureDataAvailable(); + return getViewerTexLayerSet()->isLocalTextureDataAvailable(); } -void LLTexLayerSetBuffer::preRender(BOOL clear_depth) +// virtual +void LLViewerTexLayerSetBuffer::preRenderTexLayerSet() { - // Set up an ortho projection - pushProjection(); + LLTexLayerSetBuffer::preRenderTexLayerSet(); // keep depth buffer, we don't need to clear it LLViewerDynamicTexture::preRender(FALSE); } -void LLTexLayerSetBuffer::postRender(BOOL success) +// virtual +void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) { - popProjection(); + // *TODO: Old logic does not check success before setGLTextureCreated + // we have valid texture data now + mGLTexturep->setGLTextureCreated(true); + LLTexLayerSetBuffer::postRenderTexLayerSet(success); LLViewerDynamicTexture::postRender(success); } -BOOL LLTexLayerSetBuffer::render() +// virtual +void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success) { - // Default color mask for tex layer render - gGL.setColorMask(true, true); - // do we need to upload, and do we have sufficient data to create an uploadable composite? // TODO: When do we upload the texture if gAgent.mNumPendingQueries is non-zero? const BOOL upload_now = mNeedsUpload && isReadyToUpload(); const BOOL update_now = mNeedsUpdate && isReadyToUpdate(); - - BOOL success = TRUE; - - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if (use_shaders) - { - gAlphaMaskProgram.bind(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - LLVertexBuffer::unbind(); - - // Composite the color data - LLGLSUIDefault gls_ui; - success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); - gGL.flush(); if(upload_now) { @@ -275,9 +239,10 @@ BOOL LLTexLayerSetBuffer::render() } else { - if (mTexLayerSet->isVisible()) + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + if (layer_set->isVisible()) { - mTexLayerSet->getAvatar()->debugBakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. + layer_set->getAvatar()->debugBakedTextureUpload(layer_set->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. doUpload(); } else @@ -285,7 +250,7 @@ BOOL LLTexLayerSetBuffer::render() mUploadPending = FALSE; mNeedsUpload = FALSE; mNeedsUploadTimer.pause(); - mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE); + layer_set->getAvatar()->setNewBakedTexture(layer_set->getBakedTexIndex(),IMG_INVISIBLE); } } } @@ -294,51 +259,35 @@ BOOL LLTexLayerSetBuffer::render() { doUpdate(); } - - if (use_shaders) - { - gAlphaMaskProgram.unbind(); - } - - LLVertexBuffer::unbind(); - - // reset GL state - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - // we have valid texture data now - mGLTexturep->setGLTextureCreated(true); - - return success; } -BOOL LLTexLayerSetBuffer::isInitialized(void) const +BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const { return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated(); } -BOOL LLTexLayerSetBuffer::uploadPending() const +BOOL LLViewerTexLayerSetBuffer::uploadPending() const { return mUploadPending; } -BOOL LLTexLayerSetBuffer::uploadNeeded() const +BOOL LLViewerTexLayerSetBuffer::uploadNeeded() const { return mNeedsUpload; } -BOOL LLTexLayerSetBuffer::uploadInProgress() const +BOOL LLViewerTexLayerSetBuffer::uploadInProgress() const { return !mUploadID.isNull(); } -BOOL LLTexLayerSetBuffer::isReadyToUpload() const +BOOL LLViewerTexLayerSetBuffer::isReadyToUpload() const { if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries. if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites. BOOL ready = FALSE; - if (mTexLayerSet->isLocalTextureDataFinal()) + if (getViewerTexLayerSet()->isLocalTextureDataFinal()) { // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry) if (mUploadFailCount == 0) @@ -363,7 +312,7 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const // If we hit our timeout and have textures available at even lower resolution, then upload. const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); + const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable(); ready = has_lower_lod && is_upload_textures_timeout; } } @@ -371,10 +320,10 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const return ready; } -BOOL LLTexLayerSetBuffer::isReadyToUpdate() const +BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const { // If we requested an update and have the final LOD ready, then update. - if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE; + if (getViewerTexLayerSet()->isLocalTextureDataFinal()) return TRUE; // If we haven't done an update yet, then just do one now regardless of state of textures. if (mNumLowresUpdates == 0) return TRUE; @@ -386,14 +335,14 @@ BOOL LLTexLayerSetBuffer::isReadyToUpdate() const { // If we hit our timeout and have textures available at even lower resolution, then update. const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; - const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable(); + const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable(); if (has_lower_lod && is_update_textures_timeout) return TRUE; } return FALSE; } -BOOL LLTexLayerSetBuffer::requestUpdateImmediate() +BOOL LLViewerTexLayerSetBuffer::requestUpdateImmediate() { mNeedsUpdate = TRUE; BOOL result = FALSE; @@ -410,14 +359,15 @@ BOOL LLTexLayerSetBuffer::requestUpdateImmediate() // Create the baked texture, send it out to the server, then wait for it to come // back so we can switch to using it. -void LLTexLayerSetBuffer::doUpload() +void LLViewerTexLayerSetBuffer::doUpload() { - llinfos << "Uploading baked " << mTexLayerSet->getBodyRegionName() << llendl; + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + llinfos << "Uploading baked " << layer_set->getBodyRegionName() << llendl; LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); // Don't need caches since we're baked now. (note: we won't *really* be baked // until this image is sent to the server and the Avatar Appearance message is received.) - mTexLayerSet->deleteCaches(); + layer_set->deleteCaches(); // Get the COLOR information from our texture U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; @@ -428,7 +378,7 @@ void LLTexLayerSetBuffer::doUpload() LLGLSUIDefault gls_ui; LLPointer baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); U8* baked_mask_data = baked_mask_image->getData(); - mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); + layer_set->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight); // Create the baked image from our color and mask information @@ -475,10 +425,10 @@ void LLTexLayerSetBuffer::doUpload() if (valid) { - const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + const bool highest_lod = layer_set->isLocalTextureDataFinal(); // Baked_upload_data is owned by the responder and deleted after the request completes. LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, - this->mTexLayerSet, + layer_set, asset_id, highest_lod); // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. @@ -491,7 +441,7 @@ void LLTexLayerSetBuffer::doUpload() && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. { LLSD body = LLSD::emptyMap(); - // The responder will call LLTexLayerSetBuffer::onTextureUploadComplete() + // The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete() LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; } @@ -499,7 +449,7 @@ void LLTexLayerSetBuffer::doUpload() { gAssetStorage->storeAssetData(tid, LLAssetType::AT_TEXTURE, - LLTexLayerSetBuffer::onTextureUploadComplete, + LLViewerTexLayerSetBuffer::onTextureUploadComplete, baked_upload_data, TRUE, // temp_file TRUE, // is_priority @@ -527,12 +477,12 @@ void LLTexLayerSetBuffer::doUpload() { const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32()); args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); + args["BODYREGION"] = layer_set->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } else @@ -557,9 +507,10 @@ void LLTexLayerSetBuffer::doUpload() // Mostly bookkeeping; don't need to actually "do" anything since // render() will actually do the update. -void LLTexLayerSetBuffer::doUpdate() +void LLViewerTexLayerSetBuffer::doUpdate() { - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); + const BOOL highest_lod = layer_set->isLocalTextureDataFinal(); if (highest_lod) { mNeedsUpdate = FALSE; @@ -573,25 +524,25 @@ void LLTexLayerSetBuffer::doUpdate() // need to switch to using this layerset if this is the first update // after getting the lowest LOD - mTexLayerSet->getAvatar()->updateMeshTextures(); + layer_set->getAvatar()->updateMeshTextures(); // Print out notification that we updated this texture. if (gSavedSettings.getBOOL("DebugAvatarRezTime")) { - const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal(); + const BOOL highest_lod = layer_set->isLocalTextureDataFinal(); const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mTexLayerSet->getAvatar()->debugGetExistenceTimeElapsedF32()); + args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32()); args["TIME"] = llformat("%d",(U32)mNeedsUpdateTimer.getElapsedTimeF32()); - args["BODYREGION"] = mTexLayerSet->getBodyRegionName(); + args["BODYREGION"] = layer_set->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args); - LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; + LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } // static -void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, +void LLViewerTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status) // StoreAssetData callback (not fixed) @@ -603,7 +554,7 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, (baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures. (baked_upload_data->mTexLayerSet->hasComposite())) { - LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite(); + LLViewerTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getViewerComposite(); S32 failures = layerset_buffer->mUploadFailCount; layerset_buffer->mUploadFailCount = 0; @@ -627,7 +578,7 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, if (result >= 0) { layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later - LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet); + LLAvatarAppearanceDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->getViewerTexLayerSet()); // Update baked texture info with the new UUID U64 now = LLFrameTimer::getTotalTime(); // Record starting time llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; @@ -673,7 +624,6 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, LLViewerTexLayerSet::LLViewerTexLayerSet(LLAvatarAppearance* const appearance) : LLTexLayerSet(appearance), - mComposite( NULL ), mUpdatesEnabled( FALSE ) { } @@ -704,24 +654,31 @@ void LLViewerTexLayerSet::requestUpdate() if( mUpdatesEnabled ) { createComposite(); - mComposite->requestUpdate(); + getViewerComposite()->requestUpdate(); } } void LLViewerTexLayerSet::requestUpload() { createComposite(); - mComposite->requestUpload(); + getViewerComposite()->requestUpload(); } void LLViewerTexLayerSet::cancelUpload() { if(mComposite) { - mComposite->cancelUpload(); + getViewerComposite()->cancelUpload(); } } +void LLViewerTexLayerSet::updateComposite() +{ + createComposite(); + getViewerComposite()->requestUpdateImmediate(); +} + +// virtual void LLViewerTexLayerSet::createComposite() { if(!mComposite) @@ -733,15 +690,7 @@ void LLViewerTexLayerSet::createComposite() { llerrs << "composites should not be created for non-self avatars!" << llendl; } - mComposite = new LLTexLayerSetBuffer( this, width, height ); - } -} - -void LLViewerTexLayerSet::destroyComposite() -{ - if( mComposite ) - { - mComposite = NULL; + mComposite = new LLViewerTexLayerSetBuffer( this, width, height ); } } @@ -751,26 +700,6 @@ void LLViewerTexLayerSet::setUpdatesEnabled( BOOL b ) } -void LLViewerTexLayerSet::updateComposite() -{ - createComposite(); - mComposite->requestUpdateImmediate(); -} - -LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() -{ - if (!mComposite) - { - createComposite(); - } - return mComposite; -} - -const LLTexLayerSetBuffer* LLViewerTexLayerSet::getComposite() const -{ - return mComposite; -} - void LLViewerTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) { memset(data, 255, width * height); @@ -778,29 +707,44 @@ void LLViewerTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); + layer->gatherAlphaMasks(data, getViewerComposite()->getOriginX(), + getViewerComposite()->getOriginY(), width, height); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true); + renderAlphaMaskTextures(getViewerComposite()->getOriginX(), + getViewerComposite()->getOriginY(), width, height, true); } - -LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const +LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() { return dynamic_cast (mAvatarAppearance); } +const LLVOAvatarSelf* LLViewerTexLayerSet::getAvatar() const +{ + return dynamic_cast (mAvatarAppearance); +} + +LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() +{ + return dynamic_cast (getComposite()); +} + +const LLViewerTexLayerSetBuffer* LLViewerTexLayerSet::getViewerComposite() const +{ + return dynamic_cast (getComposite()); +} -const std::string LLTexLayerSetBuffer::dumpTextureInfo() const +const std::string LLViewerTexLayerSetBuffer::dumpTextureInfo() const { if (!isAgentAvatarValid()) return ""; const BOOL is_high_res = !mNeedsUpload; const U32 num_low_res = mNumLowresUploads; const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32(); - const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet); + const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(getViewerTexLayerSet()); std::string status = "CREATING "; if (!uploadNeeded()) status = "DONE "; diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index 125bf82adf..6788214f3a 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -31,7 +31,7 @@ #include "lltexlayer.h" class LLVOAvatarSelf; -class LLTexLayerSetBuffer; +class LLViewerTexLayerSetBuffer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLViewerTexLayerSet @@ -41,46 +41,43 @@ class LLTexLayerSetBuffer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLViewerTexLayerSet : public LLTexLayerSet { - friend class LLTexLayerSetBuffer; public: LLViewerTexLayerSet(LLAvatarAppearance* const appearance); virtual ~LLViewerTexLayerSet(); - LLTexLayerSetBuffer* getComposite(); - const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. virtual void requestUpdate(); void requestUpload(); void cancelUpload(); - void updateComposite(); BOOL isLocalTextureDataAvailable() const; BOOL isLocalTextureDataFinal() const; - void createComposite(); - void destroyComposite(); + void updateComposite(); + /*virtual*/void createComposite(); void setUpdatesEnabled(BOOL b); BOOL getUpdatesEnabled() const { return mUpdatesEnabled; } void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); - LLVOAvatarSelf* getAvatar() const; - BOOL hasComposite() const { return (mComposite.notNull()); } + LLVOAvatarSelf* getAvatar(); + const LLVOAvatarSelf* getAvatar() const; + LLViewerTexLayerSetBuffer* getViewerComposite(); + const LLViewerTexLayerSetBuffer* getViewerComposite() const; private: - LLPointer mComposite; BOOL mUpdatesEnabled; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSetBuffer +// LLViewerTexLayerSetBuffer // -// The composite image that a LLViewerTexLayerSet writes to. Each LLTexLayerSet has one. +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetBuffer : public LLViewerDynamicTexture +class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDynamicTexture { - LOG_CLASS(LLTexLayerSetBuffer); + LOG_CLASS(LLViewerTexLayerSetBuffer); public: - LLTexLayerSetBuffer(LLViewerTexLayerSet* const owner, S32 width, S32 height); - virtual ~LLTexLayerSetBuffer(); + LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height); + virtual ~LLViewerTexLayerSetBuffer(); public: /*virtual*/ S8 getType() const; @@ -89,23 +86,34 @@ public: const std::string dumpTextureInfo() const; virtual void restoreGLTexture(); virtual void destroyGLTexture(); -protected: - void pushProjection() const; - void popProjection() const; private: - LLViewerTexLayerSet* const mTexLayerSet; + LLViewerTexLayerSet* getViewerTexLayerSet() + { return dynamic_cast (mTexLayerSet); } + const LLViewerTexLayerSet* getViewerTexLayerSet() const + { return dynamic_cast (mTexLayerSet); } static S32 sGLByteCount; //-------------------------------------------------------------------- - // Render + // Tex Layer Render + //-------------------------------------------------------------------- + virtual void preRenderTexLayerSet(); + virtual void midRenderTexLayerSet(BOOL success); + virtual void postRenderTexLayerSet(BOOL success); + virtual S32 getCompositeOriginX() const { return getOriginX(); } + virtual S32 getCompositeOriginY() const { return getOriginY(); } + virtual S32 getCompositeWidth() const { return getFullWidth(); } + virtual S32 getCompositeHeight() const { return getFullHeight(); } + + //-------------------------------------------------------------------- + // Dynamic Texture Interface //-------------------------------------------------------------------- public: /*virtual*/ BOOL needsRender(); protected: - BOOL render(S32 x, S32 y, S32 width, S32 height); - virtual void preRender(BOOL clear_depth); - virtual void postRender(BOOL success); - virtual BOOL render(); + // Pass these along for tex layer rendering. + virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); } + virtual void postRender(BOOL success) { postRenderTexLayerSet(success); } + virtual BOOL render() { return renderTexLayerSet(); } //-------------------------------------------------------------------- // Uploads diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 56ded53b5d..4e17884e0e 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6722,7 +6722,7 @@ void LLVOAvatar::updateMeshTextures() // use the last-known good baked texture until it finish the first // render of the new layerset. const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet - && ( !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized() + && ( !mBakedTextureDatas[i].mTexLayerSet->getViewerComposite()->isInitialized() || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() ); use_lkg_baked_layer[i] = (!is_layer_baked[i] && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index ec37e6f301..e836a5e4a8 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1519,7 +1519,7 @@ BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBaked { const LLViewerTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; if (!layerset) return FALSE; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) return FALSE; return !layerset_buffer->uploadNeeded(); } @@ -1614,7 +1614,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; - if (layerset && layerset->getComposite() && layerset->getComposite()->uploadPending()) + if (layerset && layerset->getViewerComposite() && layerset->getViewerComposite()->uploadPending()) { return true; } @@ -2517,7 +2517,7 @@ void LLVOAvatarSelf::outputRezDiagnostics() const const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); if (!layerset) continue; - const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) continue; LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } -- cgit v1.2.3 From 681406427fab95167cb87b54e8315600176bf218 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Tue, 4 Sep 2012 20:39:49 +0300 Subject: CHUI-311 FIXED (Make conversation list panel size persist between sessions): save current width in the setting_per_account.xml --- indra/newview/llimfloatercontainer.cpp | 23 ++++++++++++++++++++++- indra/newview/llimfloatercontainer.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 56648d09b5..480f964939 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -52,7 +52,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), - mConversationsRoot(NULL) + mConversationsRoot(NULL), + mInitialized(false) { mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); @@ -139,6 +140,16 @@ BOOL LLIMFloaterContainer::postBuild() LLAvatarNameCache::addUseDisplayNamesCallback( boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + if (! mMessagesPane->isCollapsed()) + { + S32 list_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"); + LLRect list_size = mConversationsPane->getRect(); + S32 left_pad = mConversationsListPanel->getRect().mLeft; + list_size.mRight = list_size.mLeft + list_width - left_pad; + + mConversationsPane->handleReshape(list_size, TRUE); + } + mInitialized = true; return TRUE; } @@ -514,6 +525,16 @@ void LLIMFloaterContainer::onCustomAction(const LLSD& userdata) void LLIMFloaterContainer::repositioningWidgets() { + if (!mInitialized) + { + return; + } + + if (!mConversationsPane->isCollapsed()) + { + S32 list_width = (mConversationsPane->getRect()).getWidth(); + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", list_width); + } LLRect panel_rect = mConversationsListPanel->getRect(); S32 item_height = 16; int index = 0; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a72a3e2221..53e3849600 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -110,6 +110,8 @@ private: LLLayoutPanel* mConversationsPane; LLLayoutStack* mConversationsStack; + bool mInitialized; + // Conversation list implementation public: void removeConversationListItem(const LLUUID& uuid, bool change_focus = true); -- cgit v1.2.3 From 1f6e20c5bbfd4495e6493facd2363fd133fe7fcd Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 4 Sep 2012 17:43:08 +0000 Subject: Split gl-specific LLViewerTexture implementation into llrender/LLGLViewerTexture --- indra/llappearance/lllocaltextureobject.cpp | 8 +- indra/llappearance/lllocaltextureobject.h | 10 +- indra/llappearance/lltexlayer.cpp | 24 +- indra/llappearance/lltexlayer.h | 6 +- indra/llappearance/lltexlayerparams.cpp | 2 +- indra/llappearance/lltexlayerparams.h | 4 +- indra/llappearance/lltexturemanagerbridge.h | 8 +- indra/llrender/CMakeLists.txt | 2 + indra/llrender/llgltexture.cpp | 396 ++++++++++++++++++++++++++++ indra/llrender/llgltexture.h | 196 ++++++++++++++ indra/llrender/lltexture.h | 53 +--- indra/newview/llcolorswatch.cpp | 2 +- indra/newview/lldrawpoolbump.cpp | 4 +- indra/newview/lldrawpoolterrain.cpp | 8 +- indra/newview/lldrawpoolwater.cpp | 4 +- indra/newview/lldynamictexture.cpp | 2 +- indra/newview/llface.cpp | 4 +- indra/newview/llfloatermodelpreview.cpp | 2 +- indra/newview/llfloaterreporter.cpp | 4 +- indra/newview/llfloaterscriptdebug.cpp | 2 +- indra/newview/lllocalbitmaps.cpp | 2 +- indra/newview/llpreviewtexture.cpp | 6 +- indra/newview/llselectmgr.cpp | 6 +- indra/newview/llspatialpartition.cpp | 4 +- indra/newview/lltexturectrl.cpp | 6 +- indra/newview/lltextureview.cpp | 2 +- indra/newview/llviewerobject.cpp | 10 +- indra/newview/llviewerstats.cpp | 2 +- indra/newview/llviewertexture.cpp | 390 ++------------------------- indra/newview/llviewertexture.h | 103 +------- indra/newview/llviewertexturelist.cpp | 20 +- indra/newview/llviewertexturelist.h | 14 +- indra/newview/llviewerwearable.cpp | 2 +- indra/newview/llviewerwindow.cpp | 4 +- indra/newview/llvlcomposition.cpp | 6 +- indra/newview/llvoavatar.cpp | 6 +- indra/newview/llvoavatar.h | 4 +- indra/newview/llvoavatarself.h | 4 +- indra/newview/llvograss.cpp | 2 +- indra/newview/llvoicevisualizer.cpp | 2 +- indra/newview/llvosky.cpp | 10 +- indra/newview/llvotree.cpp | 2 +- indra/newview/llvovolume.cpp | 10 +- indra/newview/llworldmap.cpp | 6 +- indra/newview/llworldmipmap.cpp | 16 +- indra/newview/tests/llworldmap_test.cpp | 6 +- indra/newview/tests/llworldmipmap_test.cpp | 4 +- 47 files changed, 759 insertions(+), 631 deletions(-) create mode 100644 indra/llrender/llgltexture.cpp create mode 100644 indra/llrender/llgltexture.h diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index 0e77444f49..7e36a06797 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -30,7 +30,7 @@ #include "llimage.h" #include "llrender.h" #include "lltexlayer.h" -#include "lltexture.h" +#include "llgltexture.h" #include "lluuid.h" #include "llwearable.h" @@ -42,7 +42,7 @@ LLLocalTextureObject::LLLocalTextureObject() : mImage = NULL; } -LLLocalTextureObject::LLLocalTextureObject(LLTexture* image, const LLUUID& id) : +LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) : mIsBakedReady(FALSE), mDiscard(MAX_DISCARD_LEVEL+1) { @@ -78,7 +78,7 @@ LLLocalTextureObject::~LLLocalTextureObject() { } -LLTexture* LLLocalTextureObject::getImage() const +LLGLTexture* LLLocalTextureObject::getImage() const { return mImage; } @@ -127,7 +127,7 @@ BOOL LLLocalTextureObject::getBakedReady() const return mIsBakedReady; } -void LLLocalTextureObject::setImage(LLTexture* new_image) +void LLLocalTextureObject::setImage(LLGLTexture* new_image) { mImage = new_image; } diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index 8f868eb412..6f14448cca 100644 --- a/indra/llappearance/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -30,7 +30,7 @@ #include #include "llpointer.h" -#include "lltexture.h" +#include "llgltexture.h" class LLUUID; class LLTexLayer; @@ -44,11 +44,11 @@ class LLLocalTextureObject { public: LLLocalTextureObject(); - LLLocalTextureObject(LLTexture* image, const LLUUID& id); + LLLocalTextureObject(LLGLTexture* image, const LLUUID& id); LLLocalTextureObject(const LLLocalTextureObject& lto); ~LLLocalTextureObject(); - LLTexture* getImage() const; + LLGLTexture* getImage() const; LLTexLayer* getTexLayer(U32 index) const; LLTexLayer* getTexLayer(const std::string &name); U32 getNumTexLayers() const; @@ -56,7 +56,7 @@ public: S32 getDiscard() const; BOOL getBakedReady() const; - void setImage(LLTexture* new_image); + void setImage(LLGLTexture* new_image); BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index); BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); @@ -70,7 +70,7 @@ protected: private: - LLPointer mImage; + LLPointer mImage; // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer // using shared pointers here only for smart assignment & cleanup // do NOT create new shared pointers to these objects, or keep pointers to them around diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 0d3219c4e0..a741a83af7 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -504,7 +504,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gGL.flush(); { - LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); if( tex ) { LLGLSUIDefault gls_ui; @@ -1087,7 +1087,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) { { - LLTexture* tex = NULL; + LLGLTexture* tex = NULL; if (mLocalTextureObject && mLocalTextureObject->getImage()) { tex = mLocalTextureObject->getImage(); @@ -1137,7 +1137,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) if( !getInfo()->mStaticImageFileName.empty() ) { { - LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { gGL.getTexUnit(0)->bind(tex, TRUE); @@ -1259,7 +1259,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) if( !getInfo()->mStaticImageFileName.empty() ) { - LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); if( tex ) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1284,7 +1284,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) { - LLTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if (tex) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1358,7 +1358,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - LLTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if( tex && (tex->getComponents() == 4) ) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1376,7 +1376,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC if( !getInfo()->mStaticImageFileName.empty() ) { - LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { if( (tex->getComponents() == 4) || @@ -1493,7 +1493,7 @@ LLUUID LLTexLayer::getUUID() const LLUUID uuid; if( getInfo()->mLocalTexture != -1 ) { - LLTexture* tex = mLocalTextureObject->getImage(); + LLGLTexture* tex = mLocalTextureObject->getImage(); if (tex) { uuid = mLocalTextureObject->getID(); @@ -1501,7 +1501,7 @@ LLUUID LLTexLayer::getUUID() const } if( !getInfo()->mStaticImageFileName.empty() ) { - LLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { uuid = tex->getID(); @@ -1821,9 +1821,9 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -LLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) +LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) { - LLPointer tex; + LLPointer tex; const char *namekey = mImageNames.addString(file_name); texture_map_t::const_iterator iter = mStaticImageList.find(namekey); @@ -1844,7 +1844,7 @@ LLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, B // that once an image is a mask it's always a mask. tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } - tex->createGLTexture(0, image_raw, 0, TRUE, LLTexture::LOCAL); + tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL); gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 4f2ee5b045..e9e1764763 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -28,7 +28,7 @@ #define LL_LLTEXLAYER_H #include -#include "lltexture.h" +#include "llgltexture.h" #include "llframetimer.h" #include "llavatarappearancedefines.h" #include "lltexlayerparams.h" @@ -287,7 +287,7 @@ class LLTexLayerStaticImageList : public LLSingleton public: LLTexLayerStaticImageList(); ~LLTexLayerStaticImageList(); - LLTexture* getTexture(const std::string& file_name, BOOL is_mask); + LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask); LLImageTGA* getImageTGA(const std::string& file_name); void deleteCachedImages(); void dumpByteCount() const; @@ -295,7 +295,7 @@ protected: BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); private: LLStringTable mImageNames; - typedef std::map > texture_map_t; + typedef std::map > texture_map_t; texture_map_t mStaticImageList; typedef std::map > image_tga_map_t; image_tga_map_t mStaticImageListTGA; diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 4f0456f315..06001c6b15 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -97,7 +97,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) iter != sInstances.end(); iter++) { LLTexLayerParamAlpha* instance = *iter; - LLTexture* tex = instance->mCachedProcessedTexture; + LLGLTexture* tex = instance->mCachedProcessedTexture; if (tex) { S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index dbffd15751..1974a4f7ac 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -36,7 +36,7 @@ class LLImageRaw; class LLImageTGA; class LLTexLayer; class LLTexLayerInterface; -class LLTexture; +class LLGLTexture; class LLWearable; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -91,7 +91,7 @@ public: BOOL getMultiplyBlend() const; private: - LLPointer mCachedProcessedTexture; + LLPointer mCachedProcessedTexture; LLPointer mStaticImageTGA; LLPointer mStaticImageRaw; BOOL mNeedsCreateTexture; diff --git a/indra/llappearance/lltexturemanagerbridge.h b/indra/llappearance/lltexturemanagerbridge.h index 20f5d0fd3c..99c01755d4 100644 --- a/indra/llappearance/lltexturemanagerbridge.h +++ b/indra/llappearance/lltexturemanagerbridge.h @@ -28,15 +28,15 @@ #define LL_TEXTUREMANAGERBRIDGE_H #include "llpointer.h" -#include "lltexture.h" +#include "llgltexture.h" // Abstract bridge interface class LLTextureManagerBridge { public: - virtual LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0; - virtual LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0; - virtual LLTexture* getFetchedTexture(const LLUUID &image_id) = 0; + virtual LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0; + virtual LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0; + virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0; }; extern LLTextureManagerBridge* gTextureManagerBridgep; diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 516af93316..4609401ccf 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -34,6 +34,7 @@ set(llrender_SOURCE_FILES llfontregistry.cpp llgldbg.cpp llglslshader.cpp + llgltexture.cpp llimagegl.cpp llpostprocess.cpp llrendernavprim.cpp @@ -56,6 +57,7 @@ set(llrender_HEADER_FILES llglheaders.h llglslshader.h llglstates.h + llgltexture.h llgltypes.h llimagegl.h llpostprocess.h diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp new file mode 100644 index 0000000000..d06ed5e57b --- /dev/null +++ b/indra/llrender/llgltexture.cpp @@ -0,0 +1,396 @@ +/** + * @file llgltexture.cpp + * @brief Opengl texture implementation + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" +#include "llgltexture.h" + + +// static +S32 LLGLTexture::getTotalNumOfCategories() +{ + return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; +} + +// static +//index starts from zero. +S32 LLGLTexture::getIndexFromCategory(S32 category) +{ + return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; +} + +//static +S32 LLGLTexture::getCategoryFromIndex(S32 index) +{ + return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; +} + +LLGLTexture::LLGLTexture(BOOL usemipmaps) +{ + init(); + mUseMipMaps = usemipmaps; +} + +LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) +{ + init(); + mFullWidth = width ; + mFullHeight = height ; + mUseMipMaps = usemipmaps; + mComponents = components ; + setTexelsPerImage(); +} + +LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) +{ + init(); + mUseMipMaps = usemipmaps ; + // Create an empty image of the specified size and width + mGLTexturep = new LLImageGL(raw, usemipmaps) ; +} + +LLGLTexture::~LLGLTexture() +{ + cleanup(); +} + +void LLGLTexture::init() +{ + mBoostLevel = LLGLTexture::BOOST_NONE; + + mFullWidth = 0; + mFullHeight = 0; + mTexelsPerImage = 0 ; + mUseMipMaps = FALSE ; + mComponents = 0 ; + + mTextureState = NO_DELETE ; + mDontDiscard = FALSE; + mNeedsGLTexture = FALSE ; +} + +void LLGLTexture::cleanup() +{ + if(mGLTexturep) + { + mGLTexturep->cleanup(); + } +} + +// virtual +void LLGLTexture::dump() +{ + if(mGLTexturep) + { + mGLTexturep->dump(); + } +} + +void LLGLTexture::setBoostLevel(S32 level) +{ + if(mBoostLevel != level) + { + mBoostLevel = level ; + if(mBoostLevel != LLGLTexture::BOOST_NONE) + { + setNoDelete() ; + } + } +} + +void LLGLTexture::forceActive() +{ + mTextureState = ACTIVE ; +} + +void LLGLTexture::setActive() +{ + if(mTextureState != NO_DELETE) + { + mTextureState = ACTIVE ; + } +} + +//set the texture to stay in memory +void LLGLTexture::setNoDelete() +{ + mTextureState = NO_DELETE ; +} + +void LLGLTexture::generateGLTexture() +{ + if(mGLTexturep.isNull()) + { + mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; + } +} + +LLImageGL* LLGLTexture::getGLTexture() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep ; +} + +BOOL LLGLTexture::createGLTexture() +{ + if(mGLTexturep.isNull()) + { + generateGLTexture() ; + } + + return mGLTexturep->createGLTexture() ; +} + +BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) +{ + llassert(mGLTexturep.notNull()) ; + + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; + + if(ret) + { + mFullWidth = mGLTexturep->getCurrentWidth() ; + mFullHeight = mGLTexturep->getCurrentHeight() ; + mComponents = mGLTexturep->getComponents() ; + setTexelsPerImage(); + } + + return ret ; +} + +void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; +} +void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) +{ + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setAddressMode(mode) ; +} +void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) +{ + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setFilteringOption(option) ; +} + +//virtual +S32 LLGLTexture::getWidth(S32 discard_level) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getWidth(discard_level) ; +} + +//virtual +S32 LLGLTexture::getHeight(S32 discard_level) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getHeight(discard_level) ; +} + +S32 LLGLTexture::getMaxDiscardLevel() const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getMaxDiscardLevel() ; +} +S32 LLGLTexture::getDiscardLevel() const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getDiscardLevel() ; +} +S8 LLGLTexture::getComponents() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getComponents() ; +} + +LLGLuint LLGLTexture::getTexName() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexName() ; +} + +BOOL LLGLTexture::hasGLTexture() const +{ + if(mGLTexturep.notNull()) + { + return mGLTexturep->getHasGLTexture() ; + } + return FALSE ; +} + +BOOL LLGLTexture::getBoundRecently() const +{ + if(mGLTexturep.notNull()) + { + return mGLTexturep->getBoundRecently() ; + } + return FALSE ; +} + +LLTexUnit::eTextureType LLGLTexture::getTarget(void) const +{ + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getTarget() ; +} + +BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; +} + +BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; +} + +void LLGLTexture::setGLTextureCreated (bool initialized) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setGLTextureCreated (initialized) ; +} + +void LLGLTexture::setCategory(S32 category) +{ + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setCategory(category) ; +} + +LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getAddressMode() ; +} + +S32 LLGLTexture::getTextureMemory() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->mTextureMemory ; +} + +LLGLenum LLGLTexture::getPrimaryFormat() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getPrimaryFormat() ; +} + +BOOL LLGLTexture::getIsAlphaMask() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getIsAlphaMask() ; +} + +BOOL LLGLTexture::getMask(const LLVector2 &tc) +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getMask(tc) ; +} + +F32 LLGLTexture::getTimePassedSinceLastBound() +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTimePassedSinceLastBound() ; +} +BOOL LLGLTexture::getMissed() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getMissed() ; +} + +BOOL LLGLTexture::isJustBound() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->isJustBound() ; +} + +void LLGLTexture::forceUpdateBindStats(void) const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->forceUpdateBindStats() ; +} + +U32 LLGLTexture::getTexelsInAtlas() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexelsInAtlas() ; +} + +U32 LLGLTexture::getTexelsInGLTexture() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getTexelsInGLTexture() ; +} + +BOOL LLGLTexture::isGLTextureCreated() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->isGLTextureCreated() ; +} + +S32 LLGLTexture::getDiscardLevelInAtlas() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getDiscardLevelInAtlas() ; +} + +void LLGLTexture::destroyGLTexture() +{ + if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) + { + mGLTexturep->destroyGLTexture() ; + mTextureState = DELETED ; + } +} + +void LLGLTexture::setTexelsPerImage() +{ + S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); + S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); + mTexelsPerImage = (F32)fullwidth * fullheight; +} + + diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h new file mode 100644 index 0000000000..a02946d37f --- /dev/null +++ b/indra/llrender/llgltexture.h @@ -0,0 +1,196 @@ +/** + * @file llglviewertexture.h + * @brief Object for managing opengl textures + * + * $LicenseInfo:firstyear=2012&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_GL_TEXTURE_H +#define LL_GL_TEXTURE_H + +#include "lltexture.h" +#include "llgl.h" + +class LLImageRaw; + +// +//this the parent for the class LLViewerTexture +//through the following virtual functions, the class LLViewerTexture can be reached from /llrender. +// +class LLGLTexture : public LLTexture +{ +public: + enum + { + MAX_IMAGE_SIZE_DEFAULT = 1024, + INVALID_DISCARD_LEVEL = 0x7fff + }; + + enum EBoostLevel + { + BOOST_NONE = 0, + BOOST_AVATAR_BAKED , + BOOST_AVATAR , + BOOST_CLOUDS , + BOOST_SCULPTED , + + BOOST_HIGH = 10, + BOOST_BUMP , + BOOST_TERRAIN , // has to be high priority for minimap / low detail + BOOST_SELECTED , + BOOST_AVATAR_BAKED_SELF , + BOOST_AVATAR_SELF , // needed for baking avatar + BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. + BOOST_HUD , + BOOST_ICON , + BOOST_UI , + BOOST_PREVIEW , + BOOST_MAP , + BOOST_MAP_VISIBLE , + BOOST_MAX_LEVEL, + + //other texture Categories + LOCAL = BOOST_MAX_LEVEL, + AVATAR_SCRATCH_TEX, + DYNAMIC_TEX, + MEDIA, + ATLAS, + OTHER, + MAX_GL_IMAGE_CATEGORY + }; + + static S32 getTotalNumOfCategories() ; + static S32 getIndexFromCategory(S32 category) ; + static S32 getCategoryFromIndex(S32 index) ; + +protected: + virtual ~LLGLTexture(); + LOG_CLASS(LLGLTexture); + +public: + LLGLTexture(BOOL usemipmaps = TRUE); + LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + + virtual void dump(); // debug info to llinfos + + void setBoostLevel(S32 level); + S32 getBoostLevel() { return mBoostLevel; } + + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } + + void generateGLTexture() ; + void destroyGLTexture() ; + + virtual const LLUUID& getID() const = 0; + + //--------------------------------------------------------------------------------------------- + //functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + /*virtual*/S32 getWidth(S32 discard_level = -1) const; + /*virtual*/S32 getHeight(S32 discard_level = -1) const; + + BOOL hasGLTexture() const ; + LLGLuint getTexName() const ; + BOOL createGLTexture() ; + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER); + + void setFilteringOption(LLTexUnit::eTextureFilterOptions option); + void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); + void setAddressMode(LLTexUnit::eTextureAddressMode mode); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); + void setGLTextureCreated (bool initialized); + void setCategory(S32 category) ; + + LLTexUnit::eTextureAddressMode getAddressMode(void) const ; + S32 getMaxDiscardLevel() const; + S32 getDiscardLevel() const; + S8 getComponents() const; + BOOL getBoundRecently() const; + S32 getTextureMemory() const ; + LLGLenum getPrimaryFormat() const; + BOOL getIsAlphaMask() const ; + LLTexUnit::eTextureType getTarget(void) const ; + BOOL getMask(const LLVector2 &tc); + F32 getTimePassedSinceLastBound(); + BOOL getMissed() const ; + BOOL isJustBound()const ; + void forceUpdateBindStats(void) const; + + U32 getTexelsInAtlas() const ; + U32 getTexelsInGLTexture() const ; + BOOL isGLTextureCreated() const ; + S32 getDiscardLevelInAtlas() const ; + //--------------------------------------------------------------------------------------------- + //end of functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + + //----------------- + /*virtual*/ void setActive() ; + void forceActive() ; + void setNoDelete() ; + void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } + BOOL getDontDiscard() const { return mDontDiscard; } + //----------------- + +private: + void cleanup(); + void init(); + +protected: + void setTexelsPerImage(); + + //note: do not make this function public. + /*virtual*/ LLImageGL* getGLTexture() const ; + +protected: + S32 mBoostLevel; // enum describing priority level + S32 mFullWidth; + S32 mFullHeight; + BOOL mUseMipMaps; + S8 mComponents; + F32 mTexelsPerImage; // Texels per image. + mutable S8 mNeedsGLTexture; + + //GL texture + LLPointer mGLTexturep ; + S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + +protected: + typedef enum + { + DELETED = 0, //removed from memory + DELETION_CANDIDATE, //ready to be removed from memory + INACTIVE, //not be used for the last certain period (i.e., 30 seconds). + ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). + NO_DELETE = 99 //stay in memory, can not be removed. + } LLGLTextureState; + LLGLTextureState mTextureState ; + + +}; + +#endif // LL_GL_TEXTURE_H + diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 40245968d1..2f9eb9b642 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -32,18 +32,15 @@ #ifndef LL_TEXTURE_H #define LL_TEXTURE_H -#include "llgltypes.h" #include "llrefcount.h" -#include "llrender.h" - +class LLImageGL ; +class LLTexUnit ; class LLFontGL ; -class LLImageRaw ; // -//this is an abstract class as the parent for the class LLViewerTexture -//through the following virtual functions, the class LLViewerTexture can be reached from /llrender. +//this is an abstract class as the parent for the class LLGLTexture // -class LLTexture : public virtual LLRefCount +class LLTexture : public LLRefCount { friend class LLTexUnit ; friend class LLFontGL ; @@ -54,41 +51,8 @@ protected: public: LLTexture(){} - enum EBoostLevel - { - BOOST_NONE = 0, - BOOST_AVATAR_BAKED , - BOOST_AVATAR , - BOOST_CLOUDS , - BOOST_SCULPTED , - - BOOST_HIGH = 10, - BOOST_BUMP , - BOOST_TERRAIN , // has to be high priority for minimap / low detail - BOOST_SELECTED , - BOOST_AVATAR_BAKED_SELF , - BOOST_AVATAR_SELF , // needed for baking avatar - BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. - BOOST_HUD , - BOOST_ICON , - BOOST_UI , - BOOST_PREVIEW , - BOOST_MAP , - BOOST_MAP_VISIBLE , - BOOST_MAX_LEVEL, - - //other texture Categories - LOCAL = BOOST_MAX_LEVEL, - AVATAR_SCRATCH_TEX, - DYNAMIC_TEX, - MEDIA, - ATLAS, - OTHER, - MAX_GL_IMAGE_CATEGORY - }; - // - //interfaces to access LLViewerTexture + //interfaces to access LLGLTexture // virtual S8 getType() const = 0 ; virtual void setKnownDrawSize(S32 width, S32 height) = 0 ; @@ -97,13 +61,6 @@ public: virtual void setActive() = 0 ; virtual S32 getWidth(S32 discard_level = -1) const = 0 ; virtual S32 getHeight(S32 discard_level = -1) const = 0 ; - virtual BOOL hasGLTexture() const = 0; - virtual BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLTexture::OTHER) = 0; - virtual void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE) = 0; - virtual void setAddressMode(LLTexUnit::eTextureAddressMode mode) = 0; - virtual LLTexUnit::eTextureAddressMode getAddressMode(void) const = 0; - virtual S8 getComponents() const = 0; - virtual const LLUUID& getID() const = 0; private: //note: do not make this function public. diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 5b942f283a..87fd47cb2c 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -242,7 +242,7 @@ void LLColorSwatchCtrl::draw() if (!mFallbackImageName.empty()) { LLPointer fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, - LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if( fallback_image->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior ); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index a264eae302..74633e4e42 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -153,7 +153,7 @@ void LLStandardBumpmap::addstandard() gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLGLTexture::BOOST_BUMP) ; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ; LLStandardBumpmap::sStandardBumpmapCount++; @@ -1075,7 +1075,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText src_image->getHeight() != bump->getHeight())// || //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) { - src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; + src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ; src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); src_image->forceToSaveRawImage(0) ; } diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 9bc32fddbd..809f34bdff 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -69,7 +69,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", - TRUE, LLViewerTexture::BOOST_UI, + TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, format, int_format, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); @@ -78,7 +78,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", - TRUE, LLViewerTexture::BOOST_UI, + TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, format, int_format, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); @@ -86,7 +86,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - mTexturep->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); + mTexturep->setBoostLevel(LLGLTexture::BOOST_TERRAIN); //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -170,7 +170,7 @@ void LLDrawPoolTerrain::render(S32 pass) LLVLComposition *compp = regionp->getComposition(); for (S32 i = 0; i < 4; i++) { - compp->mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); + compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 4f6eaa5a5b..26890bd75f 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -66,11 +66,11 @@ LLVector3 LLDrawPoolWater::sLightDir; LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) { - mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[0]) ; mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[1]); mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index fa42b157a7..29ad4f34d2 100755 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -107,7 +107,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum { setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); } - createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX); + createGLTexture(0, raw_image, 0, TRUE, LLGLTexture::DYNAMIC_TEX); setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mGLTexturep->setGLTextureCreated(false); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4a0c94df33..947ab84eec 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -560,8 +560,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) /* removed in lieu of raycast uv detection void LLFace::renderSelectedUV() { - LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLViewerTexture::BOOST_UI); - LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLViewerTexture::BOOST_UI); + LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLGLTexture::BOOST_UI); + LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLGLTexture::BOOST_UI); LLGLSUVSelect object_select; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index a071f338ba..dbab15dc9e 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -2488,7 +2488,7 @@ void LLModelLoader::loadTextures() if(!material.mDiffuseMapFilename.empty()) { material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW); + LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLGLTexture::BOOST_PREVIEW); material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); mNumOfFetchingTextures++ ; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 479bdd5ff7..da773e90ec 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -765,8 +765,8 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer image_in_list = - LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); - image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER); + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); + image_in_list->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER); // the texture picker then uses that texture LLTexturePicker* texture = getChild("screenshot"); diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index b691db1049..c987dbb4fb 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -105,7 +105,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: if (objectp) { - objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI)); + objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLGLTexture::BOOST_UI)); floater_label = llformat("%s(%.0f, %.0f, %.0f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index fce4c29870..3a199135b6 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -440,7 +440,7 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id) if (face && face->getTexture() && face->getTexture()->getID() == old_id) { object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture - (new_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + (new_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); update_obj = true; } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 3ff5a05d81..3784208e37 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -70,7 +70,7 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mAspectRatio(0.f), mPreviewToSave(FALSE), mImage(NULL), - mImageOldBoostLevel(LLViewerTexture::BOOST_NONE) + mImageOldBoostLevel(LLGLTexture::BOOST_NONE) { updateImageID(); if (key.has("save_as")) @@ -468,9 +468,9 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) void LLPreviewTexture::loadAsset() { - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mImageOldBoostLevel = mImage->getBoostLevel(); - mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); mImage->forceToSaveRawImage(0) ; mAssetStatus = PREVIEW_ASSET_LOADING; mUpdateDimensions = TRUE; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index c3c37141ed..24e272c740 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1608,7 +1608,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) // Texture picker defaults aren't inventory items // * Don't need to worry about permissions for them // * Can just apply the texture and be done with it. - objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } return true; } @@ -1774,7 +1774,7 @@ BOOL LLSelectMgr::selectionRevertTextures() } else { - object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } } @@ -5198,7 +5198,7 @@ void LLSelectMgr::updateSilhouettes() if (!mSilhouetteImagep) { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI); + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLGLTexture::BOOST_UI); } mHighlightedObjects->cleanupNodes(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 06c87e57fc..c804898cc3 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3574,9 +3574,9 @@ void renderTexturePriority(LLDrawable* drawable) drawBox(center, size); /*S32 boost = imagep->getBoostLevel(); - if (boost>LLViewerTexture::BOOST_NONE) + if (boost>LLGLTexture::BOOST_NONE) { - F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1); + F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); LLVector4 col = lerp(boost_cold, boost_hot, t); LLGLEnable blend_on(GL_BLEND); gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ec36cf48c2..3dc506d265 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -571,7 +571,7 @@ void LLFloaterTexturePicker::draw() if(mImageAssetID.notNull()) { mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); - mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); } if (mTentativeLabel) @@ -1456,9 +1456,9 @@ void LLTextureCtrl::draw() } else if (!mImageAssetID.isNull()) { - LLPointer texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPointer texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); texture->forceToSaveRawImage(0) ; mTexturep = texture; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 03529b9246..e9615e2613 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -170,7 +170,7 @@ void LLTextureBar::draw() { color = LLColor4::green4; } - else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE) + else if (mImagep->getBoostLevel() > LLGLTexture::BOOST_NONE) { color = LLColor4::magenta; } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 0bf039224c..3bb7de74e1 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3290,14 +3290,14 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) S32 tex_count = getNumTEs(); for (i = 0; i < tex_count; i++) { - getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (isSculpted() && !isMesh()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (boost_children) @@ -4044,7 +4044,7 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) // if (mDrawable.notNull() && mDrawable->isVisible()) // { const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); // } } @@ -4070,7 +4070,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, const std: uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTextureFromUrl (url, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + mTEImages[te] = LLViewerTextureManager::getFetchedTextureFromUrl (url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); setChanged(TEXTURE); if (mDrawable.notNull()) { @@ -4087,7 +4087,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); setChanged(TEXTURE); if (mDrawable.notNull()) { diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 961c7082cf..635cda4e27 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -564,7 +564,7 @@ F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; U32 gObjectBits = 0; F32 gAvgSimPing = 0.f; -U32 gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c362269b81..a73ce1d115 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -233,7 +233,7 @@ LLPointer LLViewerTextureManager::getLocalTexture(BOOL usemipma if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } @@ -243,14 +243,14 @@ LLPointer LLViewerTextureManager::getLocalTexture(const LLUUID& if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } LLPointer LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { LLPointer tex = new LLViewerTexture(raw, usemipmaps) ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; return tex ; } LLPointer LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) @@ -259,7 +259,7 @@ LLPointer LLViewerTextureManager::getLocalTexture(const U32 wid if(generate_gl_tex) { tex->generateGLTexture() ; - tex->setCategory(LLViewerTexture::LOCAL) ; + tex->setCategory(LLGLTexture::LOCAL) ; } return tex ; } @@ -309,17 +309,17 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const // Create a bridge to the viewer texture manager. class LLViewerTextureManagerBridge : public LLTextureManagerBridge { - /*virtual*/ LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) + /*virtual*/ LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) { return LLViewerTextureManager::getLocalTexture(usemipmaps, generate_gl_tex); } - /*virtual*/ LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) + /*virtual*/ LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) { return LLViewerTextureManager::getLocalTexture(width, height, components, usemipmaps, generate_gl_tex); } - /*virtual*/ LLTexture* getFetchedTexture(const LLUUID &image_id) + /*virtual*/ LLGLTexture* getFetchedTexture(const LLUUID &image_id) { return LLViewerTextureManager::getFetchedTexture(image_id); } @@ -371,12 +371,12 @@ void LLViewerTextureManager::init() imagep->setCachedRawImage(0, image_raw) ; image_raw = NULL; #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); #endif LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); - LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ; + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER) ; - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLGLTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; image_raw = new LLImageRaw(32,32,3); @@ -442,25 +442,6 @@ void LLViewerTexture::initClass() } } -// static -S32 LLViewerTexture::getTotalNumOfCategories() -{ - return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; -} - -// static -//index starts from zero. -S32 LLViewerTexture::getIndexFromCategory(S32 category) -{ - return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; -} - -//static -S32 LLViewerTexture::getCategoryFromIndex(S32 index) -{ - return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; -} - // tuning params const F32 discard_bias_delta = .25f; const F32 discard_delta_time = 0.5f; @@ -597,45 +578,38 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity //------------------------------------------------------------------------------------------- const U32 LLViewerTexture::sCurrentFileVersion = 1; -LLViewerTexture::LLViewerTexture(BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(BOOL usemipmaps) : + LLGLTexture(usemipmaps) { init(true); - mUseMipMaps = usemipmaps ; mID.generate(); sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) - : mID(id) +LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) : + LLGLTexture(usemipmaps), + mID(id) { init(true); - mUseMipMaps = usemipmaps ; sImageCount++; } -LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) : + LLGLTexture(width, height, components, usemipmaps) { init(true); - mFullWidth = width ; - mFullHeight = height ; - mUseMipMaps = usemipmaps ; - mComponents = components ; - setTexelsPerImage(); - mID.generate(); sImageCount++; } -LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : + LLGLTexture(raw, usemipmaps) { init(true); - mUseMipMaps = usemipmaps ; - mGLTexturep = new LLImageGL(raw, usemipmaps) ; - // Create an empty image of the specified size and width mID.generate(); sImageCount++; } @@ -646,20 +620,10 @@ LLViewerTexture::~LLViewerTexture() sImageCount--; } +// virtual void LLViewerTexture::init(bool firstinit) { - mBoostLevel = LLViewerTexture::BOOST_NONE; - - mFullWidth = 0; - mFullHeight = 0; - mTexelsPerImage = 0 ; - mUseMipMaps = FALSE ; - mComponents = 0 ; - - mTextureState = NO_DELETE ; - mDontDiscard = FALSE; mMaxVirtualSize = 0.f; - mNeedsGLTexture = FALSE ; mMaxVirtualSizeResetInterval = 1; mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ; mAdditionalDecodePriority = 0.f ; @@ -680,38 +644,18 @@ void LLViewerTexture::cleanup() { mFaceList.clear() ; mVolumeList.clear(); - if(mGLTexturep) - { - mGLTexturep->cleanup(); - } } // virtual void LLViewerTexture::dump() { - if(mGLTexturep) - { - mGLTexturep->dump(); - } + LLGLTexture::dump(); llinfos << "LLViewerTexture" << " mID " << mID << llendl; } -void LLViewerTexture::setBoostLevel(S32 level) -{ - if(mBoostLevel != level) - { - mBoostLevel = level ; - if(mBoostLevel != LLViewerTexture::BOOST_NONE) - { - setNoDelete() ; - } - } -} - - bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -904,294 +848,18 @@ void LLViewerTexture::reorganizeVolumeList() mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end()); } - - //virtual void LLViewerTexture::switchToCachedImage() { //nothing here. } -void LLViewerTexture::forceActive() -{ - mTextureState = ACTIVE ; -} - -void LLViewerTexture::setActive() -{ - if(mTextureState != NO_DELETE) - { - mTextureState = ACTIVE ; - } -} - -//set the texture to stay in memory -void LLViewerTexture::setNoDelete() -{ - mTextureState = NO_DELETE ; -} - -void LLViewerTexture::generateGLTexture() -{ - if(mGLTexturep.isNull()) - { - mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; - } -} - -LLImageGL* LLViewerTexture::getGLTexture() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep ; -} - -BOOL LLViewerTexture::createGLTexture() -{ - if(mGLTexturep.isNull()) - { - generateGLTexture() ; - } - - return mGLTexturep->createGLTexture() ; -} - -BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) -{ - llassert(mGLTexturep.notNull()) ; - - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; - - if(ret) - { - mFullWidth = mGLTexturep->getCurrentWidth() ; - mFullHeight = mGLTexturep->getCurrentHeight() ; - mComponents = mGLTexturep->getComponents() ; - setTexelsPerImage(); - } - - return ret ; -} - //virtual void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { //nothing here. } -void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; -} -void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) -{ - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setAddressMode(mode) ; -} -void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) -{ - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setFilteringOption(option) ; -} - -//virtual -S32 LLViewerTexture::getWidth(S32 discard_level) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getWidth(discard_level) ; -} - -//virtual -S32 LLViewerTexture::getHeight(S32 discard_level) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getHeight(discard_level) ; -} - -S32 LLViewerTexture::getMaxDiscardLevel() const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMaxDiscardLevel() ; -} -S32 LLViewerTexture::getDiscardLevel() const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getDiscardLevel() ; -} -S8 LLViewerTexture::getComponents() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getComponents() ; -} - -LLGLuint LLViewerTexture::getTexName() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexName() ; -} - -BOOL LLViewerTexture::hasGLTexture() const -{ - if(mGLTexturep.notNull()) - { - return mGLTexturep->getHasGLTexture() ; - } - return FALSE ; -} - -BOOL LLViewerTexture::getBoundRecently() const -{ - if(mGLTexturep.notNull()) - { - return mGLTexturep->getBoundRecently() ; - } - return FALSE ; -} - -LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const -{ - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTarget() ; -} - -BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; -} - -BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; -} - -void LLViewerTexture::setGLTextureCreated (bool initialized) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setGLTextureCreated (initialized) ; -} - -void LLViewerTexture::setCategory(S32 category) -{ - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setCategory(category) ; -} - -LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getAddressMode() ; -} - -S32 LLViewerTexture::getTextureMemory() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->mTextureMemory ; -} - -LLGLenum LLViewerTexture::getPrimaryFormat() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getPrimaryFormat() ; -} - -BOOL LLViewerTexture::getIsAlphaMask() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getIsAlphaMask() ; -} - -BOOL LLViewerTexture::getMask(const LLVector2 &tc) -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getMask(tc) ; -} - -F32 LLViewerTexture::getTimePassedSinceLastBound() -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTimePassedSinceLastBound() ; -} -BOOL LLViewerTexture::getMissed() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getMissed() ; -} - -BOOL LLViewerTexture::isJustBound() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->isJustBound() ; -} - -void LLViewerTexture::forceUpdateBindStats(void) const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->forceUpdateBindStats() ; -} - -U32 LLViewerTexture::getTexelsInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInAtlas() ; -} - -U32 LLViewerTexture::getTexelsInGLTexture() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getTexelsInGLTexture() ; -} - -BOOL LLViewerTexture::isGLTextureCreated() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->isGLTextureCreated() ; -} - -S32 LLViewerTexture::getDiscardLevelInAtlas() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getDiscardLevelInAtlas() ; -} - -void LLViewerTexture::destroyGLTexture() -{ - if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) - { - mGLTexturep->destroyGLTexture() ; - mTextureState = DELETED ; - } -} - -void LLViewerTexture::setTexelsPerImage() -{ - S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); - S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); - mTexelsPerImage = (F32)fullwidth * fullheight; -} - BOOL LLViewerTexture::isLargeImage() { return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ; @@ -1775,7 +1443,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Don't decode anything we don't need priority = -4.0f; } - else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data) + else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data) { priority = 1.f; } @@ -2161,7 +1829,7 @@ bool LLViewerFetchedTexture::updateFetch() // Load the texture progressively: we try not to rush to the desired discard too fast. // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around - S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; + S32 delta_level = (mBoostLevel > LLGLTexture::BOOST_NONE) ? 2 : 1 ; if (current_discard < 0) { desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); @@ -2412,7 +2080,7 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so destroySavedRawImage() ; } } - else if(needsToSaveRawImage() && mBoostLevel != LLViewerTexture::BOOST_PREVIEW) + else if(needsToSaveRawImage() && mBoostLevel != LLGLTexture::BOOST_PREVIEW) { if(desired_raw_discard != INVALID_DISCARD_LEVEL) { @@ -2870,7 +2538,7 @@ void LLViewerFetchedTexture::setCachedRawImage() S32 h = mRawImage->getHeight() ; S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; - if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel) + if(LLGLTexture::BOOST_TERRAIN == mBoostLevel) { max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; } @@ -3243,7 +2911,7 @@ void LLViewerLODTexture::processTextureStats() if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } - else if (mBoostLevel < LLViewerTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) + else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) { // If the image has not been significantly visible in a while, we don't want it mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); @@ -3293,7 +2961,7 @@ void LLViewerLODTexture::processTextureStats() mCalculatedDiscardLevel = discard_level; } } - if (mBoostLevel < LLViewerTexture::BOOST_SCULPTED) + if (mBoostLevel < LLGLTexture::BOOST_SCULPTED) { discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale @@ -3319,7 +2987,7 @@ void LLViewerLODTexture::processTextureStats() // S32 current_discard = getDiscardLevel(); - if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0) + if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLGLTexture::BOOST_SCULPTED && current_discard >= 0) { if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage) { @@ -3462,7 +3130,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL setMediaImpl() ; - setCategory(LLViewerTexture::MEDIA) ; + setCategory(LLGLTexture::MEDIA) ; LLViewerTexture* tex = gTextureList.findImage(mID) ; if(tex) //this media is a parcel media for tex. diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 4b92a2bf8a..d180d7fa99 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -27,7 +27,7 @@ #ifndef LL_LLVIEWERTEXTURE_H #define LL_LLVIEWERTEXTURE_H -#include "lltexture.h" +#include "llgltexture.h" #include "lltimer.h" #include "llframetimer.h" #include "llhost.h" @@ -88,14 +88,9 @@ public: class LLTextureBar; -class LLViewerTexture : public LLTexture +class LLViewerTexture : public LLGLTexture { public: - enum - { - MAX_IMAGE_SIZE_DEFAULT = 1024, - INVALID_DISCARD_LEVEL = 0x7fff - }; enum { LOCAL_TEXTURE, @@ -107,10 +102,6 @@ public: INVALID_TEXTURE_TYPE }; - static S32 getTotalNumOfCategories() ; - static S32 getIndexFromCategory(S32 category) ; - static S32 getCategoryFromIndex(S32 index) ; - typedef std::vector ll_face_list_t; typedef std::vector ll_volume_list_t; @@ -137,9 +128,6 @@ public: /*virtual*/ const LLUUID& getID() const { return mID; } - void setBoostLevel(S32 level); - S32 getBoostLevel() { return mBoostLevel; } - void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; void resetTextureStats(); void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} @@ -149,8 +137,6 @@ public: LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} - S32 getFullWidth() const { return mFullWidth; } - S32 getFullHeight() const { return mFullHeight; } /*virtual*/ void setKnownDrawSize(S32 width, S32 height); virtual void addFace(LLFace* facep) ; @@ -163,60 +149,8 @@ public: S32 getNumVolumes() const; const ll_volume_list_t* getVolumeList() const { return &mVolumeList; } - void generateGLTexture() ; - void destroyGLTexture() ; - - //--------------------------------------------------------------------------------------------- - //functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - /*virtual*/S32 getWidth(S32 discard_level = -1) const; - /*virtual*/S32 getHeight(S32 discard_level = -1) const; - /*virtual*/BOOL hasGLTexture() const ; - LLGLuint getTexName() const ; - BOOL createGLTexture() ; - /*virtual*/ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLTexture::OTHER); virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; - - void setFilteringOption(LLTexUnit::eTextureFilterOptions option); - /*virtual*/ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); - /*virtual*/ void setAddressMode(LLTexUnit::eTextureAddressMode mode); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); - void setGLTextureCreated (bool initialized); - void setCategory(S32 category) ; - - /*virtual*/ LLTexUnit::eTextureAddressMode getAddressMode(void) const ; - S32 getMaxDiscardLevel() const; - S32 getDiscardLevel() const; - /*virtual*/ S8 getComponents() const; - BOOL getBoundRecently() const; - S32 getTextureMemory() const ; - LLGLenum getPrimaryFormat() const; - BOOL getIsAlphaMask() const ; - LLTexUnit::eTextureType getTarget(void) const ; - BOOL getMask(const LLVector2 &tc); - F32 getTimePassedSinceLastBound(); - BOOL getMissed() const ; - BOOL isJustBound()const ; - void forceUpdateBindStats(void) const; - - U32 getTexelsInAtlas() const ; - U32 getTexelsInGLTexture() const ; - BOOL isGLTextureCreated() const ; - S32 getDiscardLevelInAtlas() const ; - //--------------------------------------------------------------------------------------------- - //end of functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - - //----------------- - /*virtual*/ void setActive() ; - void forceActive() ; - void setNoDelete() ; - void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } - BOOL getDontDiscard() const { return mDontDiscard; } - //----------------- - BOOL isLargeImage() ; void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} @@ -229,35 +163,21 @@ protected: void init(bool firstinit) ; void reorganizeFaceList() ; void reorganizeVolumeList() ; - void setTexelsPerImage(); private: friend class LLBumpImageList; friend class LLUIImageList; - //note: do not make this function public. - /*virtual*/ LLImageGL* getGLTexture() const ; virtual void switchToCachedImage(); static bool isMemoryForTextureLow() ; protected: LLUUID mID; - S32 mBoostLevel; // enum describing priority level - S32 mFullWidth; - S32 mFullHeight; - BOOL mUseMipMaps ; - S8 mComponents; - F32 mTexelsPerImage; // Texels per image. - mutable S8 mNeedsGLTexture; mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter ; mutable S32 mMaxVirtualSizeResetInterval; mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. LLFrameTimer mLastReferencedTimer; - //GL texture - LLPointer mGLTexturep ; - S8 mDontDiscard; // Keep full res version of this image (for UI, etc) - ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture U32 mNumFaces ; LLFrameTimer mLastFaceListUpdateTimer ; @@ -269,17 +189,6 @@ protected: //do not use LLPointer here. LLViewerMediaTexture* mParcelMedia ; -protected: - typedef enum - { - DELETED = 0, //removed from memory - DELETION_CANDIDATE, //ready to be removed from memory - INACTIVE, //not be used for the last certain period (i.e., 30 seconds). - ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). - NO_DELETE = 99 //stay in memory, can not be removed. - } LLGLTextureState; - LLGLTextureState mTextureState ; - static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; @@ -475,7 +384,7 @@ protected: S32 getCurrentDiscardLevelForFetching() ; private: - void init(bool firstinit) ; + void init(bool firstinit) ; void cleanup() ; void saveRawImage() ; @@ -698,7 +607,7 @@ public: static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -707,7 +616,7 @@ public: static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -716,7 +625,7 @@ public: static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index e4669cde34..b89247ec6f 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -198,7 +198,7 @@ void LLViewerTextureList::doPrefetchImages() if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) { - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, texture_type); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) { image->addTextureStats((F32)pixel_area); @@ -339,7 +339,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& if (full_path.empty()) { llwarns << "Failed to find local image file: " << filename << llendl; - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); } std::string url = "file://" + full_path; @@ -430,7 +430,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if ((&image_id == NULL) || image_id.isNull()) { - return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI)); + return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); } LLPointer imagep = findImage(image_id); @@ -1361,7 +1361,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1434,7 +1434,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1534,9 +1534,9 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priori LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority ) { - if (boost_priority == LLViewerTexture::BOOST_NONE) + if (boost_priority == LLGLTexture::BOOST_NONE) { - boost_priority = LLViewerTexture::BOOST_UI; + boost_priority = LLGLTexture::BOOST_UI; } LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority); return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect); @@ -1545,9 +1545,9 @@ LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority) { - if (boost_priority == LLViewerTexture::BOOST_NONE) + if (boost_priority == LLGLTexture::BOOST_NONE) { - boost_priority = LLViewerTexture::BOOST_UI; + boost_priority = LLGLTexture::BOOST_UI; } LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority); return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect); @@ -1572,7 +1572,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st //Note: //Some other textures such as ICON also through this flow to be fetched. //But only UI textures need to set this callback. - if(imagep->getBoostLevel() == LLViewerTexture::BOOST_UI) + if(imagep->getBoostLevel() == LLGLTexture::BOOST_UI) { LLUIImageLoadData* datap = new LLUIImageLoadData; datap->mImageName = name; diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 3dda973d3f..05c7c35f7c 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -131,7 +131,7 @@ private: LLViewerFetchedTexture * getImage(const LLUUID &image_id, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -140,7 +140,7 @@ private: LLViewerFetchedTexture * getImageFromFile(const std::string& filename, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -149,7 +149,7 @@ private: LLViewerFetchedTexture* getImageFromUrl(const std::string& url, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -158,7 +158,7 @@ private: LLViewerFetchedTexture* createImage(const LLUUID &image_id, BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -168,7 +168,7 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + { return getImage(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set > image_list_t; @@ -233,11 +233,11 @@ private: LLPointer loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); LLPointer loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); LLPointer loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 0cd3ded371..34f24ef330 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -401,7 +401,7 @@ void LLViewerWearable::writeToAvatar() { image_id = getDefaultTextureImageID((ETextureIndex) te); } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. gAgentAvatarp->setLocalTextureTE(te, image, 0); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4aabbd6bb6..d5ca01931f 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -729,7 +729,7 @@ public: if(log_texture_traffic) { U32 old_y = ypos ; - for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++) + for(S32 i = LLGLTexture::BOOST_NONE; i < LLGLTexture::MAX_GL_IMAGE_CATEGORY; i++) { if(gTotalTextureBytesPerBoostLevel[i] > 0) { @@ -1678,7 +1678,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. - LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; + LLImageGL::initClass(LLGLTexture::MAX_GL_IMAGE_CATEGORY) ; gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index ec932501e5..e90a2470d4 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -223,7 +223,7 @@ BOOL LLVLComposition::generateComposition() { if (mDetailTextures[i]->getDiscardLevel() < 0) { - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); return FALSE; } @@ -240,7 +240,7 @@ BOOL LLVLComposition::generateComposition() ddiscard++; min_dim /= 2; } - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail mDetailTextures[i]->setMinDiscardLevel(ddiscard); return FALSE; } @@ -463,7 +463,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, for (S32 i = 0; i < 4; i++) { // Un-boost detatil textures (will get re-boosted if rendering in high detail) - mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE); + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE); mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4e17884e0e..b86c5d5e8f 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4698,7 +4698,7 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel imagep->addTextureStats(pixel_area / texel_area_ratio); imagep->setBoostLevel(boost_level); - if(boost_level != LLViewerTexture::BOOST_AVATAR_BAKED_SELF) + if(boost_level != LLGLTexture::BOOST_AVATAR_BAKED_SELF) { imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ; } @@ -6748,7 +6748,7 @@ void LLVOAvatar::updateMeshTextures() const std::string url = getImageURL(i, mBakedTextureDatas[i].mLastTextureIndex); if (!url.empty()) { - baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureIndex); + baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureIndex); } else { @@ -7289,7 +7289,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) && baked_index != BAKED_SKIRT) { setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index d54d06a6a7..b8999728b3 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -563,8 +563,8 @@ private: // Constants //-------------------------------------------------------------------- public: - virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; } - virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; } + virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLGLTexture::BOOST_AVATAR; } + virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED; } virtual S32 getTexImageSize() const; virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index d4bde1f61f..12886d2d36 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -177,8 +177,8 @@ private: // LLVOAvatar Constants //-------------------------------------------------------------------- public: - /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_SELF; } - /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED_SELF; } + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLGLTexture::BOOST_AVATAR_SELF; } + /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED_SELF; } /*virtual*/ S32 getTexImageSize() const { return LLVOAvatar::getTexImageSize()*4; } /** Rendering diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 566c33c0af..479e871e94 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -102,7 +102,7 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 47060720e7..315e618132 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -136,7 +136,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; icreateGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL); + mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -384,9 +384,9 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mSun.setIntensity(SUN_INTENSITY); mMoon.setIntensity(0.1f * SUN_INTENSITY); - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -478,9 +478,9 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 6687ce432f..68bb40d727 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -316,7 +316,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b43bdb69f8..7fab1cf9b7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -747,7 +747,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) { F32 area = (F32) camera->getScreenPixelArea(); vsize = area; - imagep->setBoostLevel(LLViewerTexture::BOOST_HUD); + imagep->setBoostLevel(LLGLTexture::BOOST_HUD); face->setPixelArea(area); // treat as full screen face->setVirtualSize(vsize); } @@ -803,7 +803,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (mSculptTexture.notNull()) { mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLViewerTexture::BOOST_SCULPTED)); + (S32)LLGLTexture::BOOST_SCULPTED)); mSculptTexture->setForSculpt() ; if(!mSculptTexture->isCachedRawImageReady()) @@ -1006,7 +1006,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (is404) { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLGLTexture::BOOST_UI)); //render prim proxy when mesh loading attempts give up volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); @@ -1090,7 +1090,7 @@ void LLVOVolume::updateSculptTexture() LLUUID id = sculpt_params->getSculptTexture(); if (id.notNull()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } } else @@ -2698,7 +2698,7 @@ void LLVOVolume::updateSpotLightPriority() if (mLightTexture.notNull()) { mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS); + mLightTexture->setBoostLevel(LLGLTexture::BOOST_CLOUDS); } } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index cb24e96d5b..4d52f23ddb 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -78,7 +78,7 @@ void LLSimInfo::setLandForSaleImage (LLUUID image_id) // Fetch the image if (mMapImageID.notNull()) { - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); } else @@ -92,13 +92,13 @@ LLPointer LLSimInfo::getLandForSaleImage () if (mOverlayImage.isNull() && mMapImageID.notNull()) { // Fetch the image if it hasn't been done yet (unlikely but...) - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); } if (!mOverlayImage.isNull()) { // Boost the fetch level when we try to access that image - mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP); + mOverlayImage->setBoostLevel(LLGLTexture::BOOST_MAP); } return mOverlayImage; } diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 74ed844376..c9d2a24a4e 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -74,21 +74,21 @@ void LLWorldMipmap::equalizeBoostLevels() { LLPointer img = iter->second; S32 current_boost_level = img->getBoostLevel(); - if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high - img->setBoostLevel(LLViewerTexture::BOOST_MAP); + img->setBoostLevel(LLGLTexture::BOOST_MAP); } else { // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw // so we drop its boost level to BOOST_NONE. - img->setBoostLevel(LLViewerTexture::BOOST_NONE); + img->setBoostLevel(LLGLTexture::BOOST_NONE); } #if DEBUG_TILES_STAT // Increment some stats if compile option on nb_tiles++; - if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + if (current_boost_level == LLGLTexture::BOOST_MAP_VISIBLE) { nb_visible++; } @@ -115,7 +115,7 @@ void LLWorldMipmap::dropBoostLevels() for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { LLPointer img = iter->second; - img->setBoostLevel(LLViewerTexture::BOOST_NONE); + img->setBoostLevel(LLGLTexture::BOOST_NONE); } } } @@ -172,7 +172,7 @@ LLPointer LLWorldMipmap::getObjectsTile(U32 grid_x, U32 // Boost the tile level so to mark it's in use *if* load on if (load) { - img->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); + img->setBoostLevel(LLGLTexture::BOOST_MAP_VISIBLE); } return img; } @@ -189,8 +189,8 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - img->setBoostLevel(LLViewerTexture::BOOST_MAP); + LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + img->setBoostLevel(LLGLTexture::BOOST_MAP); // Return the smart pointer return img; diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp index acc6e814bc..3c68890c36 100644 --- a/indra/newview/tests/llworldmap_test.cpp +++ b/indra/newview/tests/llworldmap_test.cpp @@ -47,9 +47,9 @@ // * A simulator for a class can be implemented here. Please comment and document thoroughly. // Stub image calls -void LLViewerTexture::setBoostLevel(S32 ) { } -void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, BOOL, LLViewerTexture::EBoostLevel, S8, +void LLGLTexture::setBoostLevel(S32 ) { } +void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { } +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, BOOL, LLGLTexture::EBoostLevel, S8, LLGLint, LLGLenum, LLHost ) { return NULL; } // Stub related map calls diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index e7ef017760..22ebf28f55 100644 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -42,8 +42,8 @@ // * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) // * A simulator for a class can be implemented here. Please comment and document thoroughly. -void LLViewerTexture::setBoostLevel(S32 ) { } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, BOOL, LLViewerTexture::EBoostLevel, S8, +void LLGLTexture::setBoostLevel(S32 ) { } +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, BOOL, LLGLTexture::EBoostLevel, S8, LLGLint, LLGLenum, const LLUUID& ) { return NULL; } LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker(name) { } -- cgit v1.2.3 From 0f519ca167071e06e326dfc0494768f978e2328e Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 4 Sep 2012 17:47:16 +0000 Subject: Set virtual inheritance on LLTexture -> LLRefCount --- indra/llrender/lltexture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 2f9eb9b642..093bac20d1 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -40,7 +40,7 @@ class LLFontGL ; // //this is an abstract class as the parent for the class LLGLTexture // -class LLTexture : public LLRefCount +class LLTexture : public virtual LLRefCount { friend class LLTexUnit ; friend class LLFontGL ; -- cgit v1.2.3 From 5fbb161ba0a28e64474efc295b12bccffdcdb0e0 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 4 Sep 2012 13:34:33 -0700 Subject: CHUI-305: Now searching in the resident picker works. Problem: The resident picker search results were being sent to the old global resident picker. Now resident pickers are non-global and coupled to their parent floater. --- indra/newview/llfloateravatarpicker.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 2152de1035..6ada809cdb 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -460,8 +460,9 @@ class LLAvatarPickerResponder : public LLHTTPClient::Responder { public: LLUUID mQueryID; + std::string mName; - LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } + LLAvatarPickerResponder(const LLUUID& id, const std::string& name) : mQueryID(id), mName(name) { } /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content) { @@ -474,7 +475,7 @@ public: if (isGoodStatus(status) || status == 400) { LLFloaterAvatarPicker* floater = - LLFloaterReg::findTypedInstance("avatar_picker"); + LLFloaterReg::findTypedInstance("avatar_picker", mName); if (floater) { floater->processResponse(mQueryID, content); @@ -517,7 +518,7 @@ void LLFloaterAvatarPicker::find() url += "?page_size=100&names="; url += LLURI::escape(text); llinfos << "avatar picker " << url << llendl; - LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID)); + LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString())); } else { -- cgit v1.2.3 From d41202336b7c797bc3fe4feffa8be2164518e845 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 4 Sep 2012 14:21:25 -0700 Subject: CHUI-303: Problem was that the prior solution only updated (using dirtyFilter()) the inventory window that the paste occurred in. Resolution: Now each inventory window calls dirtyFilter(), which then determines visibility of the pasted item. --- indra/newview/llinventorybridge.cpp | 12 ++---------- indra/newview/llinventorymodel.cpp | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 745375fe3d..72c54e5ce2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3193,16 +3193,8 @@ void LLFolderBridge::pasteFromClipboard() LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); llassert(vicat); if (vicat) - { - //Set the pasted folder to dirty, could do this in changeCategoryParent() but only need to set dirty - //when pasting from the clipboard. Setting dirty allows updating the filter state, which determines - //visibility in the new pasted location. - LLFolderViewFolder * folderViewItem = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(item_id) : NULL; - if(folderViewItem && folderViewItem->getViewModelItem()) - { - folderViewItem->getViewModelItem()->dirtyFilter(); - } - + { + //changeCategoryParent() implicity calls dirtyFilter changeCategoryParent(model, vicat, parent_id, FALSE); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0673970d89..e7d59d92d9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -986,6 +986,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat) cat_array->put(old_cat); } mask |= LLInventoryObserver::STRUCTURE; + mask |= LLInventoryObserver::INTERNAL; } if(old_cat->getName() != cat->getName()) { -- cgit v1.2.3 From 41301004e13bec1c74f444f42372a3a6609cb305 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 4 Sep 2012 22:49:26 +0000 Subject: Cleanup actions from code review of llappearance with nyx --- indra/cmake/CMakeLists.txt | 1 - indra/cmake/Viewer.cmake | 7 ------- indra/llappearance/CMakeLists.txt | 1 - indra/llappearance/llavatarappearance.cpp | 9 +++++++++ indra/llappearance/llavatarappearance.h | 3 ++- indra/llappearance/lltexlayer.h | 2 +- indra/llcharacter/CMakeLists.txt | 1 - indra/llrender/llgltexture.h | 4 ++-- indra/newview/lldriverparam.cpp | 4 ++-- indra/newview/lltexturefetch.cpp | 6 ------ indra/newview/llviewertexlayer.cpp | 7 ++++--- indra/newview/llviewertexlayer.h | 2 +- indra/newview/llviewertexture.h | 1 - indra/newview/llvoavatar.h | 5 ++--- 14 files changed, 23 insertions(+), 30 deletions(-) delete mode 100644 indra/cmake/Viewer.cmake diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 875b5be152..5935eeb192 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -78,7 +78,6 @@ set(cmake_SOURCE_FILES Tut.cmake UI.cmake UnixInstall.cmake - Viewer.cmake Variables.cmake XmlRpcEpi.cmake ZLIB.cmake diff --git a/indra/cmake/Viewer.cmake b/indra/cmake/Viewer.cmake deleted file mode 100644 index 771bb0ed7a..0000000000 --- a/indra/cmake/Viewer.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# -*- cmake -*- - -set(VIEWER_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/newview - ) - -set(VIEWER_LIBRARIES viewer) diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index f77c7e6440..0206f76546 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -4,7 +4,6 @@ project(llappearance) include(00-Common) include(LLCommon) -include(Viewer) include(LLAudio) include(LLCharacter) include(LLCommon) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2cc38ae2ab..75b9c1ffa5 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -27,6 +27,7 @@ #include "linden_common.h" #include "llavatarappearance.h" +#include "lldeleteutils.h" #include "lltexglobalcolor.h" const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -40,6 +41,14 @@ LLAvatarAppearance::LLAvatarAppearance() : { } +// virtual +LLAvatarAppearance::~LLAvatarAppearance() +{ + deleteAndClear(mTexSkinColor); + deleteAndClear(mTexHairColor); + deleteAndClear(mTexEyeColor); +} + using namespace LLAvatarAppearanceDefines; //static diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index e882868e91..0e746b3b9d 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -28,7 +28,7 @@ #define LL_AVATAR_APPEARANCE_H #include "llcharacter.h" -#include "llframetimer.h" +//#include "llframetimer.h" #include "llavatarappearancedefines.h" class LLTexLayerSet; @@ -50,6 +50,7 @@ class LLAvatarAppearance : public LLCharacter public: LLAvatarAppearance(); + virtual ~LLAvatarAppearance(); /** Initialization ** ** diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index e9e1764763..e6c2ece64a 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -29,7 +29,7 @@ #include #include "llgltexture.h" -#include "llframetimer.h" +//#include "llframetimer.h" #include "llavatarappearancedefines.h" #include "lltexlayerparams.h" diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index e9704d5635..a1712699eb 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -15,7 +15,6 @@ include_directories( ${LLMESSAGE_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLAPPEARANCE_INCLUDE_DIRS} ) set(llcharacter_SOURCE_FILES diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index a02946d37f..b1efe77519 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -94,6 +94,8 @@ public: virtual void dump(); // debug info to llinfos + virtual const LLUUID& getID() const = 0; + void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } @@ -103,8 +105,6 @@ public: void generateGLTexture() ; void destroyGLTexture() ; - virtual const LLUUID& getID() const = 0; - //--------------------------------------------------------------------------------------------- //functions to access LLImageGL //--------------------------------------------------------------------------------------------- diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 0ae9acd1af..5abf72d51f 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -629,9 +629,9 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bo driven->mParam->getCrossWearable()) { LLViewerWearable* wearable = dynamic_cast (mWearablep); - if (!wearable->isOnTop()) + if (wearable->isOnTop()) { - use_self = false; + use_self = true; } } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 16baefac4f..db08c16f15 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -973,12 +973,6 @@ bool LLTextureFetchWorker::doWork(S32 param) } else if(!mUrl.empty() && mCanUseHTTP) { - if (!(mUrl.compare(0, 7, "http://") == 0) && - !(mUrl.compare(0, 8, "https://") == 0)) - { - // *TODO:?remove this warning - llwarns << "Unknown URL Type: " << mUrl << llendl; - } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); mState = SEND_HTTP_REQ; } diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 69457ab1db..f516562c2f 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -214,9 +214,6 @@ void LLViewerTexLayerSetBuffer::preRenderTexLayerSet() // virtual void LLViewerTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) { - // *TODO: Old logic does not check success before setGLTextureCreated - // we have valid texture data now - mGLTexturep->setGLTextureCreated(true); LLTexLayerSetBuffer::postRenderTexLayerSet(success); LLViewerDynamicTexture::postRender(success); @@ -259,6 +256,10 @@ void LLViewerTexLayerSetBuffer::midRenderTexLayerSet(BOOL success) { doUpdate(); } + + // *TODO: Old logic does not check success before setGLTextureCreated + // we have valid texture data now + mGLTexturep->setGLTextureCreated(true); } BOOL LLViewerTexLayerSetBuffer::isInitialized(void) const diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index 6788214f3a..95c339a5b0 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -45,7 +45,7 @@ public: LLViewerTexLayerSet(LLAvatarAppearance* const appearance); virtual ~LLViewerTexLayerSet(); - virtual void requestUpdate(); + /*virtual*/void requestUpdate(); void requestUpload(); void cancelUpload(); BOOL isLocalTextureDataAvailable() const; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index d180d7fa99..254a0cf92f 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -637,7 +637,6 @@ public: static void init() ; static void cleanup() ; }; - // //this class is used for test/debug only //it tracks the activities of the texture pipeline diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index b8999728b3..5f780da145 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -473,14 +473,14 @@ private: public: BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + /*virtual*/void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); //-------------------------------------------------------------------- // Global colors //-------------------------------------------------------------------- public: - virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); + /*virtual*/void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); //-------------------------------------------------------------------- // Visibility @@ -1039,7 +1039,6 @@ public: void debugAvatarRezTime(std::string notification_name, std::string comment = ""); F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } - protected: LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. -- cgit v1.2.3 From 8cd5d361600f34a0a7fa504a721bea3301191644 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 4 Sep 2012 22:11:28 -0700 Subject: CHUI-285 : Create participant widgets in the conversation list --- indra/newview/llconversationmodel.cpp | 12 ++++-- indra/newview/llconversationmodel.h | 14 ++++--- indra/newview/llconversationview.cpp | 38 ++++++++++++++++- indra/newview/llconversationview.h | 20 ++++++++- indra/newview/llimfloatercontainer.cpp | 75 +++++++++++++++++++++++++--------- 5 files changed, 128 insertions(+), 31 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d7f9093a4a..aa21b08ec8 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -36,21 +36,24 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(display_name), - mUUID(uuid) + mUUID(uuid), + mNeedsRefresh(true) { } LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUUID(uuid) + mUUID(uuid), + mNeedsRefresh(true) { } LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_model) : LLFolderViewModelItemCommon(root_view_model), mName(""), - mUUID() + mUUID(), + mNeedsRefresh(true) { } @@ -102,11 +105,13 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa { addChild(participant); mIsLoaded = true; + mNeedsRefresh = true; } void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) { removeChild(participant); + mNeedsRefresh = true; } void LLConversationItemSession::removeParticipant(const LLUUID& participant_id) @@ -122,6 +127,7 @@ void LLConversationItemSession::clearParticipants() { clearChildren(); mIsLoaded = false; + mNeedsRefresh = true; } LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 1a2e09dfab..5947055e0f 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -60,7 +60,7 @@ public: virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual BOOL isItemRenameable() const { return TRUE; } - virtual BOOL renameItem(const std::string& new_name) { mName = new_name; return TRUE; } + virtual BOOL renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return TRUE; } virtual BOOL isItemMovable( void ) const { return FALSE; } virtual BOOL isItemRemovable( void ) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } @@ -102,10 +102,14 @@ public: // bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } - + + void resetRefresh() { mNeedsRefresh = false; } + bool needsRefresh() { return mNeedsRefresh; } + protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant + bool mNeedsRefresh; // Flag signaling to the view that something changed for this item }; class LLConversationItemSession : public LLConversationItem @@ -115,7 +119,7 @@ public: LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} - void setSessionID(const LLUUID& session_id) { mUUID = session_id; } + void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); void removeParticipant(const LLUUID& participant_id); @@ -142,8 +146,8 @@ public: bool isMuted() { return mIsMuted; } bool isModerator() {return mIsModerator; } - void setIsMuted(bool is_muted) { mIsMuted = is_muted; } - void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; } + void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } + void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void dumpDebugData(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index fefb7e9cac..2f71e92a7d 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -79,12 +79,46 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) } } +LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id) +{ + // This is *not* a general tree parsing algorithm. We search only in the mItems list + // assuming there is no mFolders which makes sense for sessions (sessions don't contain + // sessions). + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast(*iter); + if (participant->hasSameValue(participant_id)) + { + break; + } + } + return (iter == getItemsEnd() ? NULL : participant); +} + +void LLConversationViewSession::refresh() +{ + // Refresh the session view from its model data + // LLConversationItemSession* vmi = dynamic_cast(getViewModelItem()); + + // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + + // Do the regular upstream refresh + LLFolderViewFolder::refresh(); +} + // // Implementation of conversations list participant (avatar) widgets // -LLConversationViewParticipant::LLConversationViewParticipant( const LLFolderViewItem::Params& p ): - LLFolderViewItem(p) +LLConversationViewParticipant::Params::Params() : + participant_id() +{} + +LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): + LLFolderViewItem(p), + mUUID(p.participant_id) { } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 5695925f43..27ceb2af3b 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -30,6 +30,8 @@ #include "llfolderviewitem.h" class LLIMFloaterContainer; +class LLConversationViewSession; +class LLConversationViewParticipant; // Implementation of conversations list session widgets @@ -53,18 +55,34 @@ public: virtual ~LLConversationViewSession( void ) { } virtual void selectItem(); void setVisibleIfDetached(BOOL visible); + LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); + + virtual void refresh(); }; // Implementation of conversations list participant (avatar) widgets class LLConversationViewParticipant : public LLFolderViewItem { +public: + struct Params : public LLInitParam::Block + { + Optional participant_id; + + Params(); + }; + protected: friend class LLUICtrlFactory; - LLConversationViewParticipant( const LLFolderViewItem::Params& p ); + LLConversationViewParticipant( const Params& p ); public: virtual ~LLConversationViewParticipant( void ) { } + + bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } + +private: + LLUUID mUUID; // UUID of the participant }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index aa85e5023d..dfe9e6491d 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -289,6 +289,59 @@ void LLIMFloaterContainer::setMinimized(BOOL b) void LLIMFloaterContainer::draw() { + // CHUI Notes + // Currently, the model is not responsible for creating the view which is a good thing. This means that + // the model could change substantially and the view could decide to echo only a portion of this model. + // Consequently, the participant views need to be created either by the session view or by the container panel. + // For the moment, we create them here (which makes for complicated code...) to conform to the pattern + // implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). + // The best however would be to have an observer on the model so that we would not pool on each draw to know + // if the view needs refresh. The current implementation (testing for change on draw) is less + // efficient perf wise than a listener/observer scheme. We will implement that shortly. + + // On each session in mConversationsItems + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + // Get the current session descriptors + LLConversationItem* session_model = it_session->second; + LLUUID session_id = it_session->first; + LLConversationViewSession* session_view = dynamic_cast(mConversationsWidgets[session_id]); + // If the session model has been changed, refresh the corresponding view + if (session_model->needsRefresh()) + { + session_view->refresh(); + } + // Iterate through each model participant child + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItem* participant_model = dynamic_cast(*current_participant_model); + LLUUID participant_id = participant_model->getUUID(); + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + // Is there a corresponding view? If not create it + if (!participant_view) + { + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + mConversationsListPanel->addChild(participant_view); + participant_view->setVisible(TRUE); + } + else + // Else, see if it needs refresh + { + if (participant_model->needsRefresh()) + { + participant_view->refresh(); + } + } + // Reset the need for refresh + session_model->resetRefresh(); + // Next participant + current_participant_model++; + } + } + if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -536,24 +589,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) participant_view->setVisible(TRUE); current_participant_model++; } - // Debugging hack : uncomment to force the creation of a dummy participant - // This hack is to be eventually deleted - if (item->getChildrenCount() == 0) - { - llinfos << "Merov debug : create dummy participant" << llendl; - // Create a dummy participant : we let that leak but that's just for debugging... - std::string name("Debug Test : "); - name += display_name; - LLUUID test_id; - test_id.generate(name); - LLConversationItemParticipant* participant_model = new LLConversationItemParticipant(name, test_id, getRootViewModel()); - // Create the dummy widget - LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(widget); - mConversationsListPanel->addChild(participant_view); - participant_view->setVisible(TRUE); - } - // End debugging hack repositioningWidgets(); @@ -610,7 +645,7 @@ LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LL LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParticipant(LLConversationItem* item) { - LLConversationViewSession::Params params; + LLConversationViewParticipant::Params params; params.name = item->getDisplayName(); //params.icon = bridge->getIcon(); @@ -620,7 +655,7 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti params.listener = item; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; - params.container = this; + params.participant_id = item->getUUID(); return LLUICtrlFactory::create(params); } -- cgit v1.2.3 From 3cf624b371eace5ec382796d7bd811d181d5e877 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 5 Sep 2012 18:48:07 +0300 Subject: CHUI-268 (Transfer the common functionality from LLNearbyChat and LLIMFloater to LLIMConversation): moved focusLost(), focusReceived and enable/disable of the call button to base class --- indra/newview/llimconversation.cpp | 42 ++++++++++++++++++++++++++++++++++++++ indra/newview/llimconversation.h | 14 +++++++++---- indra/newview/llimfloater.cpp | 39 ----------------------------------- indra/newview/llimfloater.h | 9 -------- indra/newview/llnearbychat.cpp | 23 +-------------------- indra/newview/llnearbychat.h | 7 ------- 6 files changed, 53 insertions(+), 81 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index 5a5196fb7e..d8c81a7849 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -31,6 +31,8 @@ #include "llchatentry.h" #include "llchathistory.h" +#include "llchiclet.h" +#include "llchicletbar.h" #include "lldraghandle.h" #include "llfloaterreg.h" #include "llimfloater.h" @@ -53,6 +55,8 @@ LLIMConversation::LLIMConversation(const LLUUID& session_id) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) { + mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + mCommitCallbackRegistrar.add("IMSession.Menu.Action", boost::bind(&LLIMConversation::onIMSessionMenuItemClicked, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", @@ -182,6 +186,44 @@ void LLIMConversation::draw() } } +void LLIMConversation::enableDisableCallBtn() +{ + getChildView("voice_call_btn")->setEnabled( + mSessionID.notNull() + && mSession + && mSession->mSessionInitialized + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking() + && mSession->mCallBackEnabled); +} + + +void LLIMConversation::onFocusReceived() +{ + setBackgroundOpaque(true); + + if (mSessionID.notNull()) + { + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); + + if (getVisible()) + { + // suppress corresponding toast only if this floater is visible and have focus + LLIMModel::getInstance()->setActiveSessionID(mSessionID); + LLIMModel::instance().sendNoUnreadMessages(mSessionID); + } + } + + LLTransientDockableFloater::onFocusReceived(); +} + +void LLIMConversation::onFocusLost() +{ + setBackgroundOpaque(false); + LLTransientDockableFloater::onFocusLost(); +} + + void LLIMConversation::buildParticipantList() { if (mIsNearbyChat) diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 26151ad1be..50feb12aed 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -33,6 +33,7 @@ #include "lltransientdockablefloater.h" #include "llviewercontrol.h" #include "lleventtimer.h" +#include "llimview.h" #include "llconversationmodel.h" class LLPanelChatControlPanel; @@ -87,9 +88,6 @@ protected: // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn() = 0; - void buildParticipantList(); void onSortMenuItemClicked(const LLSD& userdata); @@ -99,9 +97,18 @@ protected: /// Update floater header and toolbar buttons when hosted/torn off state is toggled. void updateHeaderAndToolbar(); + // set the enable/disable state for the Call button + virtual void enableDisableCallBtn(); + + // process focus events to set a currently active session + /* virtual */ void onFocusLost(); + /* virtual */ void onFocusReceived(); + bool mIsNearbyChat; bool mIsP2PChat; + LLIMModel::LLIMSession* mSession; + LLLayoutPanel* mParticipantListPanel; LLParticipantList* mParticipantList; LLUUID mSessionID; @@ -119,7 +126,6 @@ private: /// Refreshes the floater at a constant rate. virtual void refresh() = 0; - /** * Adjusts chat history height to fit vertically with input chat field * and avoid overlapping, since input chat field can be vertically expanded. diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index a601561c62..7b475c1e0b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -92,24 +92,6 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) setDocked(true); } -void LLIMFloater::onFocusLost() -{ - LLIMModel::getInstance()->resetActiveSessionID(); - - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); -} - -void LLIMFloater::onFocusReceived() -{ - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); - - if (getVisible()) - { - // suppress corresponding toast only if this floater is visible and have focus - LLIMModel::getInstance()->setActiveSessionID(mSessionID); - LLIMModel::instance().sendNoUnreadMessages(mSessionID); - } -} // virtual void LLIMFloater::refresh() @@ -513,27 +495,6 @@ void LLIMFloater::boundVoiceChannel() } } -void LLIMFloater::enableDisableCallBtn() -{ - bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking(); - - if (mSession) - { - bool session_initialized = mSession->mSessionInitialized; - bool callback_enabled = mSession->mCallBackEnabled; - - BOOL enable_connect = - session_initialized && voice_enabled && callback_enabled; - getChildView("voice_call_btn")->setEnabled(enable_connect); - } - else - { - getChildView("voice_call_btn")->setEnabled(false); - } -} - - void LLIMFloater::onCallButtonClicked() { LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 24a8f17feb..7b2c9e7aef 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -134,10 +134,6 @@ public: private: - // process focus events to set a currently active session - /* virtual */ void onFocusLost(); - /* virtual */ void onFocusReceived(); - /*virtual*/ void refresh(); /*virtual*/ void onClickCloseBtn(); @@ -169,9 +165,6 @@ private: void onCallButtonClicked(); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - void boundVoiceChannel(); // Add the "User is typing..." indicator. @@ -184,8 +177,6 @@ private: static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); - - LLIMModel::LLIMSession* mSession; S32 mLastMessageIndex; EInstantMessage mDialog; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 25bbc82fee..c2ad8cfda3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -133,6 +133,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) setIsChrome(TRUE); mKey = LLSD(); mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + mSessionID = LLUUID(); setName("nearby_chat"); setIsSingleInstance(TRUE); } @@ -216,21 +217,6 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) return false; } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() -{ - setBackgroundOpaque(true); - LLIMConversation::onFocusReceived(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() -{ - setBackgroundOpaque(false); - LLIMConversation::onFocusLost(); -} BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) { @@ -326,13 +312,6 @@ void LLNearbyChat::setVisible(BOOL visible) } -void LLNearbyChat::enableDisableCallBtn() -{ - // bool btn_enabled = LLAgent::isActionAllowed("speak"); - - getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); -} - void LLNearbyChat::onTearOffClicked() { LLIMConversation::onTearOffClicked(); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 4fc5cb7f76..1db7afc01f 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -51,10 +51,6 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - // focus overrides - /*virtual*/ void onFocusLost(); - /*virtual*/ void onFocusReceived(); - /*virtual*/ void setVisible(BOOL visible); void loadHistory(); @@ -102,9 +98,6 @@ protected: void displaySpeakingIndicator(); - // set the enable/disable state for the Call button - virtual void enableDisableCallBtn(); - // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; -- cgit v1.2.3 From b146490e1b46799ccb35e156b4751eddea3a23ce Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 5 Sep 2012 17:46:11 -0400 Subject: SH-3264 Worked to move over mBakedTextureDatas from LLVOAvatar to LLAvatarAppearance. Appear to have been able to move over the parts that are common to both the backend and the viewer into LLAvatarAppearance. --- indra/llappearance/llavatarappearance.cpp | 38 ++++++++ indra/llappearance/llavatarappearance.h | 39 +++++++++ indra/newview/llvoavatar.cpp | 139 ++++++++++++++++-------------- indra/newview/llvoavatar.h | 38 +------- indra/newview/llvoavatarself.cpp | 57 ++++++------ indra/newview/llvoavatarself.h | 2 +- 6 files changed, 190 insertions(+), 123 deletions(-) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 75b9c1ffa5..81a1d3965c 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -26,7 +26,10 @@ #include "linden_common.h" + #include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "imageids.h" #include "lldeleteutils.h" #include "lltexglobalcolor.h" @@ -39,6 +42,16 @@ LLAvatarAppearance::LLAvatarAppearance() : mTexEyeColor( NULL ), mIsDummy(FALSE) { + mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) + { + mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; + mBakedTextureDatas[i].mTexLayerSet = NULL; + mBakedTextureDatas[i].mIsLoaded = false; + mBakedTextureDatas[i].mIsUsed = false; + mBakedTextureDatas[i].mMaskTexName = 0; + mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); + } } // virtual @@ -47,10 +60,35 @@ LLAvatarAppearance::~LLAvatarAppearance() deleteAndClear(mTexSkinColor); deleteAndClear(mTexHairColor); deleteAndClear(mTexEyeColor); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); + mBakedTextureDatas[i].mMeshes.clear(); + + for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); + iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) + { + LLMaskedMorph* masked_morph = (*iter2); + delete masked_morph; + } + } } using namespace LLAvatarAppearanceDefines; + +// adds a morph mask to the appropriate baked texture structure +void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer) +{ + if (index < BAKED_NUM_INDICES) + { + LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); + mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); + } +} + + //static BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) { diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 0e746b3b9d..9bff6b111e 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -30,6 +30,7 @@ #include "llcharacter.h" //#include "llframetimer.h" #include "llavatarappearancedefines.h" +#include "lljoint.h" class LLTexLayerSet; class LLTexGlobalColor; @@ -79,6 +80,7 @@ public: // Morph masks //-------------------------------------------------------------------- public: + void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer); virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; /** Rendering @@ -153,6 +155,43 @@ public: virtual LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) = 0; virtual const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const = 0; +/******************************************************************************** + ** ** + ** BAKED TEXTURES + **/ +protected: + struct LLMaskedMorph; + typedef std::deque morph_list_t; + struct BakedTextureData + { + LLUUID mLastTextureIndex; + LLTexLayerSet* mTexLayerSet; // Only exists for self + bool mIsLoaded; + bool mIsUsed; + LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; + U32 mMaskTexName; + // Stores pointers to the joint meshes that this baked texture deals with + std::vector< LLJoint* > mMeshes; // std::vector mJoints[i]->mMeshParts + morph_list_t mMaskedMorphs; + }; + typedef std::vector bakedtexturedata_vec_t; + bakedtexturedata_vec_t mBakedTextureDatas; + + +/******************************************************************************** + ** ** + ** SUPPORT CLASSES + **/ + + class LLMaskedMorph + { + public: + LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer); + + LLVisualParam *mMorphTarget; + BOOL mInvert; + std::string mLayer; + }; }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b86c5d5e8f..ce0b65ca89 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -703,17 +703,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mPelvisp = NULL; - mBakedTextureDatas.resize(BAKED_NUM_INDICES); - for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) - { - mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; - mBakedTextureDatas[i].mTexLayerSet = NULL; - mBakedTextureDatas[i].mIsLoaded = false; - mBakedTextureDatas[i].mIsUsed = false; - mBakedTextureDatas[i].mMaskTexName = 0; - mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); - } - mDirtyMesh = 2; // Dirty geometry, need to regenerate. mMeshTexturesDirty = FALSE; mHeadp = NULL; @@ -821,19 +810,6 @@ LLVOAvatar::~LLVOAvatar() mNumJoints = 0; - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); - mBakedTextureDatas[i].mMeshes.clear(); - - for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); - iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) - { - LLMaskedMorph* masked_morph = (*iter2); - delete masked_morph; - } - } - std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); mAttachmentPoints.clear(); @@ -1102,7 +1078,7 @@ void LLVOAvatar::restoreGL() gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++) { - gAgentAvatarp->invalidateComposite(gAgentAvatarp->mBakedTextureDatas[i].mTexLayerSet, FALSE); + gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i), FALSE); } gAgentAvatarp->updateMeshTextures(); } @@ -5518,9 +5494,9 @@ BOOL LLVOAvatar::loadAvatar() EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); if (baked != BAKED_NUM_INDICES) { - LLPolyMorphTarget *morph_param; + LLVisualParam* morph_param; const std::string *name = &info->mName; - morph_param = (LLPolyMorphTarget *)(getVisualParam(name->c_str())); + morph_param = getVisualParam(name->c_str()); if (morph_param) { BOOL invert = info->mInvert; @@ -6504,7 +6480,11 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL LLColor4 color = mTexHairColor->getColor(); for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + if (mesh) + { + mesh->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + } } } } @@ -6721,15 +6701,16 @@ void LLVOAvatar::updateMeshTextures() // When an avatar is changing clothes and not in Appearance mode, // use the last-known good baked texture until it finish the first // render of the new layerset. - const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet - && ( !mBakedTextureDatas[i].mTexLayerSet->getViewerComposite()->isInitialized() - || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() ); + LLViewerTexLayerSet* layerset = getTexLayerSet(i); + const BOOL layerset_invalid = layerset + && ( !layerset->getViewerComposite()->isInitialized() + || !layerset->isLocalTextureDataAvailable() ); use_lkg_baked_layer[i] = (!is_layer_baked[i] && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) && layerset_invalid); if (use_lkg_baked_layer[i]) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); + layerset->setUpdatesEnabled(TRUE); } } else @@ -6742,6 +6723,7 @@ void LLVOAvatar::updateMeshTextures() for (U32 i=0; i < mBakedTextureDatas.size(); i++) { + LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (use_lkg_baked_layer[i] && !mUseLocalAppearance ) { LLViewerFetchedTexture* baked_img; @@ -6765,7 +6747,11 @@ void LLVOAvatar::updateMeshTextures() mBakedTextureDatas[i].mIsUsed = TRUE; for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + if (mesh) + { + mesh->setTexture( baked_img ); + } } } else if (!mUseLocalAppearance && is_layer_baked[i]) @@ -6788,14 +6774,18 @@ void LLVOAvatar::updateMeshTextures() src_callback_list, paused ); } } - else if (mBakedTextureDatas[i].mTexLayerSet && mUseLocalAppearance) + else if (layerset && mUseLocalAppearance) { - mBakedTextureDatas[i].mTexLayerSet->createComposite(); - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE ); + layerset->createComposite(); + layerset->setUpdatesEnabled( TRUE ); mBakedTextureDatas[i].mIsUsed = FALSE; for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + if (mesh) + { + mesh->setLayerSet( layerset ); + } } } } @@ -6809,8 +6799,12 @@ void LLVOAvatar::updateMeshTextures() LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + if (mesh) + { + mesh->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mesh->setTexture( hair_img ); + } } } @@ -6883,16 +6877,28 @@ void LLVOAvatar::clearChat() mChats.clear(); } -// adds a morph mask to the appropriate baked texture structure -void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer) + +void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index) { - if (index < BAKED_NUM_INDICES) + if (index >= BAKED_NUM_INDICES) { - LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); - mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); + llwarns << "invalid baked texture index passed to applyMorphMask" << llendl; + return; + } + + for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); + iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) + { + const LLMaskedMorph* maskedMorph = (*iter); + LLPolyMorphTarget* morph_target = dynamic_cast(maskedMorph->mMorphTarget); + if (morph_target) + { + morph_target->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); + } } } + // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index) { @@ -6905,7 +6911,7 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIn { if (isSelf()) { - LLViewerTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet; + LLViewerTexLayerSet *layer_set = getTexLayerSet(index); if (layer_set) { return !layer_set->isMorphValid(); @@ -6920,23 +6926,6 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIn return FALSE; } -void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index) -{ - if (index >= BAKED_NUM_INDICES) - { - llwarns << "invalid baked texture index passed to applyMorphMask" << llendl; - return; - } - - for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); - iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) - { - const LLMaskedMorph* maskedMorph = (*iter); - maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); - } -} - - //----------------------------------------------------------------------------- // releaseComponentTextures() // release any component texture UUIDs for which we have a baked texture @@ -7616,7 +7605,11 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) mBakedTextureDatas[i].mIsUsed = true; for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + if (mesh) + { + mesh->setTexture( image_baked ); + } } if (mBakedTextureDatas[i].mTexLayerSet) { @@ -7637,7 +7630,11 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) { for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); + LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + if (mesh) + { + mesh->setColor( 1.f, 1.f, 1.f, 1.f ); + } } } } @@ -8689,3 +8686,17 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, return FALSE; } +//virtual +LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer) : + mMorphTarget(morph_target), + mInvert(invert), + mLayer(layer) +{ + LLPolyMorphTarget *target = dynamic_cast(morph_target); + if (target) + { + target->addPendingMorphMask(); + } +} + + diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5f780da145..91ea19fbd3 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -48,6 +48,7 @@ #include "llavatarappearancedefines.h" #include "lltexglobalcolor.h" #include "lldriverparam.h" +#include "llviewertexlayer.h" #include "material_codes.h" // LL_MCODE_END #include "llviewerstats.h" @@ -63,7 +64,6 @@ extern const LLUUID ANIM_AGENT_PELVIS_FIX; extern const LLUUID ANIM_AGENT_TARGET; extern const LLUUID ANIM_AGENT_WALK_ADJUST; -class LLViewerTexLayerSet; class LLViewerWearable; class LLVoiceVisualizer; class LLHUDNameTag; @@ -87,7 +87,6 @@ public: friend class LLVOAvatarSelf; protected: struct LLVOAvatarXmlInfo; - struct LLMaskedMorph; /******************************************************************************** ** ** @@ -471,9 +470,8 @@ private: // Morph masks //-------------------------------------------------------------------- public: + /*virtual*/ void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); - void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - /*virtual*/void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES); //-------------------------------------------------------------------- @@ -601,22 +599,9 @@ protected: static void onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); virtual void removeMissingBakedTextures(); void useBakedTexture(const LLUUID& id); + LLViewerTexLayerSet* getTexLayerSet(const U32 index) const { return dynamic_cast(mBakedTextureDatas[index].mTexLayerSet); } + - typedef std::deque morph_list_t; - struct BakedTextureData - { - LLUUID mLastTextureIndex; - LLViewerTexLayerSet* mTexLayerSet; // Only exists for self - bool mIsLoaded; - bool mIsUsed; - LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; - // Stores pointers to the joint meshes that this baked texture deals with - std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts - morph_list_t mMaskedMorphs; - }; - typedef std::vector bakedtexturedata_vec_t; - bakedtexturedata_vec_t mBakedTextureDatas; LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; BOOL mLoadedCallbacksPaused; //-------------------------------------------------------------------- @@ -1139,21 +1124,6 @@ protected: // Shared with LLVOAvatarSelf morph_info_list_t mMorphMaskInfoList; }; - struct LLMaskedMorph - { - LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert, std::string layer) : - mMorphTarget(morph_target), - mInvert(invert), - mLayer(layer) - { - morph_target->addPendingMorphMask(); - } - - LLPolyMorphTarget *mMorphTarget; - BOOL mInvert; - std::string mLayer; - }; - /** Support classes ** ** *******************************************************************************/ diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index e836a5e4a8..945e134d21 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -883,8 +883,9 @@ void LLVOAvatarSelf::removeMissingBakedTextures() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); - invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE); + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + layerset->setUpdatesEnabled(TRUE); + invalidateComposite(layerset, FALSE); } updateMeshTextures(); if (getRegion() && !getRegion()->getCentralBakeVersion()) @@ -1090,10 +1091,11 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re const LLWearableType::EType comp_type = *type_iter; if (comp_type == type) { - if (mBakedTextureDatas[index].mTexLayerSet) + LLViewerTexLayerSet *layerset = getLayerSet(index); + if (layerset) { - mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled(true); - invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result); + layerset->setUpdatesEnabled(true); + invalidateComposite(layerset, upload_result); } break; } @@ -1517,7 +1519,7 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLAvatarAppearanceDefines::EBakedTextureIndex index) const { - const LLViewerTexLayerSet *layerset = mBakedTextureDatas[index].mTexLayerSet; + const LLViewerTexLayerSet *layerset = getLayerSet(index); if (!layerset) return FALSE; const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); if (!layerset_buffer) return FALSE; @@ -1597,9 +1599,10 @@ void LLVOAvatarSelf::requestLayerSetUpload(LLAvatarAppearanceDefines::EBakedText { ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; const BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); - if (!layer_baked && mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getLayerSet(i); + if (!layer_baked && layerset) { - mBakedTextureDatas[i].mTexLayerSet->requestUpload(); + layerset->requestUpload(); } } @@ -1613,7 +1616,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - LLViewerTexLayerSet* layerset = mBakedTextureDatas[i].mTexLayerSet; + LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (layerset && layerset->getViewerComposite() && layerset->getViewerComposite()->uploadPending()) { return true; @@ -1648,7 +1651,8 @@ void LLVOAvatarSelf::invalidateAll() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE); + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + invalidateComposite(layerset, TRUE); } //mDebugSelfLoadTimer.reset(); } @@ -1666,17 +1670,19 @@ void LLVOAvatarSelf::setCompositeUpdatesEnabled( bool b ) void LLVOAvatarSelf::setCompositeUpdatesEnabled(U32 index, bool b) { - if (mBakedTextureDatas[index].mTexLayerSet ) + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset ) { - mBakedTextureDatas[index].mTexLayerSet->setUpdatesEnabled( b ); + layerset->setUpdatesEnabled( b ); } } bool LLVOAvatarSelf::isCompositeUpdateEnabled(U32 index) { - if (mBakedTextureDatas[index].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset) { - return mBakedTextureDatas[index].mTexLayerSet->getUpdatesEnabled(); + return layerset->getUpdatesEnabled(); } return false; } @@ -1687,9 +1693,10 @@ void LLVOAvatarSelf::setupComposites() { ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); - if (mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset) { - mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(!layer_baked); + layerset->setUpdatesEnabled(!layer_baked); } } } @@ -1698,10 +1705,11 @@ void LLVOAvatarSelf::updateComposites() { for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (mBakedTextureDatas[i].mTexLayerSet + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT))) { - mBakedTextureDatas[i].mTexLayerSet->updateComposite(); + layerset->updateComposite(); } } } @@ -1985,14 +1993,14 @@ BOOL LLVOAvatarSelf::getIsCloud() const if (!mPreviousFullyLoaded) { - if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) && + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_LOWER)) && (!isTextureDefined(TEX_LOWER_BAKED, 0))) { lldebugs << "Lower textures not baked" << llendl; return TRUE; } - if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) && + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_UPPER)) && (!isTextureDefined(TEX_UPPER_BAKED, 0))) { lldebugs << "Upper textures not baked" << llendl; @@ -2550,7 +2558,8 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid mHeadLayerSet->cancelUpload(); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if ( mBakedTextureDatas[i].mTextureIndex == te && layerset) { if (mInitialBakeIDs[i] != LLUUID::null) { @@ -2564,7 +2573,7 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid } mInitialBakeIDs[i] = LLUUID::null; } - mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); + layerset->cancelUpload(); } } } @@ -2677,7 +2686,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const if (texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return mBakedTextureDatas[baked_index].mTexLayerSet; + return getLayerSet(baked_index); } return NULL; } @@ -2690,7 +2699,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) return mHeadLayerSet; */ if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) { - return mBakedTextureDatas[baked_index].mTexLayerSet; + return getTexLayerSet(baked_index); } return NULL; } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 12886d2d36..7fcab020e6 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -388,7 +388,7 @@ public: BOOL isAllLocalTextureDataFinal() const; - const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; } + const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return (LLViewerTexLayerSet*)(mBakedTextureDatas[index].mTexLayerSet); } const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD LLSD metricsData(); -- cgit v1.2.3 From 201d9853f9d57efab9b819ff07745141a5265e98 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Sep 2012 18:25:51 -0400 Subject: Debug display for baked vs. composite status, via setting DebugAvatarCompositeBaked --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llviewerjointmesh.cpp | 5 +++++ indra/newview/llviewerjointmesh.h | 1 + indra/newview/llvoavatar.cpp | 20 ++++++++++++++++---- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 69986af83b..674685f3bc 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1948,6 +1948,17 @@ Boolean Value 1 + + DebugAvatarCompositeBaked + + Comment + Colorize avatar meshes based on baked/composite state. + Persist + 1 + Type + Boolean + Value + 0 DebugBeaconLineWidth diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 5d1aa870a3..c3f8f42a2a 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -219,6 +219,11 @@ void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) mColor[3] = alpha; } +void LLViewerJointMesh::setColor( const LLColor4& color ) +{ + mColor = color; +} + //-------------------------------------------------------------------- // LLViewerJointMesh::getTexture() diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index dd5dae1dc1..630981b4a0 100755 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -99,6 +99,7 @@ public: // Sets the shape color void setColor( F32 red, F32 green, F32 blue, F32 alpha ); + void setColor( const LLColor4& color ); // Sets the shininess void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4894f21e67..d92caf1edb 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5763,7 +5763,7 @@ BOOL LLVOAvatar::loadMeshNodes() // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. // Do not touch!!! - mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f ); + mesh->setColor( LLColor4::white ); LLPolyMesh *poly_mesh = NULL; @@ -6503,7 +6503,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL LLColor4 color = mTexHairColor->getColor(); for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color ); } } } @@ -6764,6 +6764,10 @@ void LLVOAvatar::updateMeshTextures() for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img ); + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + mBakedTextureDatas[i].mMeshes[k]->setColor(LLColor4::red); + } } } else if (!mUseLocalAppearance && is_layer_baked[i]) @@ -6794,6 +6798,10 @@ void LLVOAvatar::updateMeshTextures() for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet ); + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + mBakedTextureDatas[i].mMeshes[k]->setColor( LLColor4::yellow ); + } } } } @@ -6807,7 +6815,7 @@ void LLVOAvatar::updateMeshTextures() LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color ); mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } } @@ -7721,6 +7729,10 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked ); + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + mBakedTextureDatas[i].mMeshes[k]->setColor( LLColor4::green ); + } } if (mBakedTextureDatas[i].mTexLayerSet) { @@ -7741,7 +7753,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) { for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( LLColor4::white ); } } } -- cgit v1.2.3 From 1229f42ade088f69164b59742305119bacc8f4de Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 5 Sep 2012 18:55:07 -0700 Subject: CHUI-285 : Clear the needs refresh flag when refreshing, comment clean up. --- indra/newview/llconversationview.cpp | 15 ++++++++++++++- indra/newview/llconversationview.h | 1 + indra/newview/llimfloatercontainer.cpp | 1 - 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 2f71e92a7d..9f3df93aba 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -100,7 +100,8 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const void LLConversationViewSession::refresh() { // Refresh the session view from its model data - // LLConversationItemSession* vmi = dynamic_cast(getViewModelItem()); + LLConversationItem* vmi = dynamic_cast(getViewModelItem()); + vmi->resetRefresh(); // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() @@ -122,4 +123,16 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati { } +void LLConversationViewParticipant::refresh() +{ + // Refresh the participant view from its model data + LLConversationItem* vmi = dynamic_cast(getViewModelItem()); + vmi->resetRefresh(); + + // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + + // Do the regular upstream refresh + LLFolderViewItem::refresh(); +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 27ceb2af3b..a3755d9722 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -81,6 +81,7 @@ public: bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } + virtual void refresh(); private: LLUUID mUUID; // UUID of the participant }; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 1be0c5f075..56648d09b5 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -552,7 +552,6 @@ void LLIMFloaterContainer::repositioningWidgets() } } -// CHUI-137 : Temporary implementation of conversations list void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) { bool is_nearby_chat = uuid.isNull(); -- cgit v1.2.3 From 85d0bcc0630bfbf8b50be3a47a113c4f8d6ec9df Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 6 Sep 2012 02:53:55 +0000 Subject: Extracted mWearableDatas from LLAgentWearables into llappearance/LLWearableData. Moved LLDriverParam into llappearance --- indra/llappearance/CMakeLists.txt | 4 + indra/llappearance/llavatarappearance.cpp | 60 ++- indra/llappearance/llavatarappearance.h | 21 +- indra/llappearance/lldriverparam.cpp | 614 ++++++++++++++++++++++++++++ indra/llappearance/lldriverparam.h | 133 ++++++ indra/llappearance/lltexlayer.cpp | 5 +- indra/llappearance/llwearable.h | 7 + indra/llappearance/llwearabledata.cpp | 353 ++++++++++++++++ indra/llappearance/llwearabledata.h | 108 +++++ indra/llcharacter/llcharacter.cpp | 2 +- indra/llcharacter/llcharacter.h | 2 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llagentwearables.cpp | 360 +++++------------ indra/newview/llagentwearables.h | 34 +- indra/newview/lldriverparam.cpp | 647 ------------------------------ indra/newview/lldriverparam.h | 128 ------ indra/newview/llfloateravatartextures.cpp | 4 +- indra/newview/lllocalbitmaps.cpp | 2 +- indra/newview/llpaneleditwearable.cpp | 2 +- indra/newview/llphysicsmotion.cpp | 12 +- indra/newview/llsidepanelappearance.cpp | 2 +- indra/newview/llviewerwearable.cpp | 35 +- indra/newview/llviewerwearable.h | 8 +- indra/newview/llvoavatar.cpp | 68 +--- indra/newview/llvoavatar.h | 14 - indra/newview/llvoavatarself.cpp | 30 +- indra/newview/llvoavatarself.h | 5 +- 27 files changed, 1436 insertions(+), 1226 deletions(-) create mode 100644 indra/llappearance/lldriverparam.cpp create mode 100644 indra/llappearance/lldriverparam.h create mode 100644 indra/llappearance/llwearabledata.cpp create mode 100644 indra/llappearance/llwearabledata.h delete mode 100644 indra/newview/lldriverparam.cpp delete mode 100644 indra/newview/lldriverparam.h diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 0206f76546..41da898457 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -42,6 +42,7 @@ include_directories( set(llappearance_SOURCE_FILES llavatarappearance.cpp + lldriverparam.cpp llinventoryicon.cpp lllocaltextureobject.cpp lltexglobalcolor.cpp @@ -49,6 +50,7 @@ set(llappearance_SOURCE_FILES lltexlayerparams.cpp lltexturemanagerbridge.cpp llwearable.cpp + llwearabledata.cpp llwearabletype.cpp llviewervisualparam.cpp llavatarappearancedefines.cpp @@ -58,6 +60,7 @@ set(llappearance_HEADER_FILES CMakeLists.txt llavatarappearance.h + lldriverparam.h llinventoryicon.h lljointpickname.h lllocaltextureobject.h @@ -66,6 +69,7 @@ set(llappearance_HEADER_FILES lltexlayerparams.h lltexturemanagerbridge.h llwearable.h + llwearabledata.h llwearabletype.h llviewervisualparam.h llavatarappearancedefines.h diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 75b9c1ffa5..0f0942d8dc 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -29,16 +29,19 @@ #include "llavatarappearance.h" #include "lldeleteutils.h" #include "lltexglobalcolor.h" +#include "llwearabledata.h" const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); -LLAvatarAppearance::LLAvatarAppearance() : +LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : LLCharacter(), + mIsDummy(FALSE), mTexSkinColor( NULL ), mTexHairColor( NULL ), mTexEyeColor( NULL ), - mIsDummy(FALSE) + mWearableData(wearable_data) { + llassert(mWearableData); } // virtual @@ -51,6 +54,17 @@ LLAvatarAppearance::~LLAvatarAppearance() using namespace LLAvatarAppearanceDefines; +// virtual +BOOL LLAvatarAppearance::isValid() const +{ + // This should only be called on ourself. + if (!isSelf()) + { + llerrs << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << llendl; + } + return TRUE; +} + //static BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) { @@ -178,5 +192,47 @@ LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) con } } +// Unlike most wearable functions, this works for both self and other. +// virtual +BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const +{ + if (mIsDummy) return TRUE; + + switch(type) + { + case LLWearableType::WT_SHAPE: + case LLWearableType::WT_SKIN: + case LLWearableType::WT_HAIR: + case LLWearableType::WT_EYES: + return TRUE; // everyone has all bodyparts + default: + break; // Do nothing + } + + /* switch(type) + case LLWearableType::WT_SHIRT: + indicator_te = TEX_UPPER_SHIRT; */ + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); + tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + ++tex_iter) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; + if (texture_dict->mWearableType == type) + { + // If you're checking another avatar's clothing, you don't have component textures. + // Thus, you must check to see if the corresponding baked texture is defined. + // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing + // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that + // gets baked into a texture that always exists (upper or lower). + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); + } + return FALSE; + } + } + return FALSE; +} diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 0e746b3b9d..2209ede927 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -33,6 +33,7 @@ class LLTexLayerSet; class LLTexGlobalColor; +class LLWearableData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLAvatarAppearance @@ -47,9 +48,12 @@ class LLAvatarAppearance : public LLCharacter ** ** ** INITIALIZATION **/ +private: + // Hide default constructor. + LLAvatarAppearance() {} public: - LLAvatarAppearance(); + LLAvatarAppearance(LLWearableData* wearable_data); virtual ~LLAvatarAppearance(); /** Initialization @@ -62,6 +66,7 @@ public: **/ public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + virtual BOOL isValid() const; virtual BOOL isUsingBakedTextures() const = 0; /** State @@ -145,15 +150,13 @@ public: **/ public: - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const = 0; - - virtual U32 getWearableCount(const LLWearableType::EType type) const = 0; - virtual U32 getWearableCount(const U32 tex_index) const = 0; - - virtual LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) = 0; - virtual const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const = 0; - + LLWearableData* getWearableData() { return mWearableData; } + const LLWearableData* getWearableData() const { return mWearableData; } + virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; + virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; +private: + LLWearableData* mWearableData; }; #endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp new file mode 100644 index 0000000000..1092b525d0 --- /dev/null +++ b/indra/llappearance/lldriverparam.cpp @@ -0,0 +1,614 @@ +/** + * @file lldriverparam.cpp + * @brief A visual parameter that drives (controls) other visual parameters. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldriverparam.h" + +#include "llavatarappearance.h" +#include "llwearable.h" +#include "llwearabledata.h" + +//----------------------------------------------------------------------------- +// LLDriverParamInfo +//----------------------------------------------------------------------------- + +LLDriverParamInfo::LLDriverParamInfo() : + mDriverParam(NULL) +{ +} + +BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); + + if( !LLViewerVisualParamInfo::parseXml( node )) + return FALSE; + + LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" ); + if( !param_driver_node ) + return FALSE; + + for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" ); + child; + child = param_driver_node->getNextNamedChild()) + { + S32 driven_id; + static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); + if( child->getFastAttributeS32( id_string, driven_id ) ) + { + F32 min1 = mMinWeight; + F32 max1 = mMaxWeight; + F32 max2 = max1; + F32 min2 = max1; + + // driven ________ // + // ^ /| |\ // + // | / | | \ // + // | / | | \ // + // | / | | \ // + // | / | | \ // + //-------|----|-------|----|-------> driver // + // | min1 max1 max2 min2 + + static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1"); + child->getFastAttributeF32( min1_string, min1 ); // optional + static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1"); + child->getFastAttributeF32( max1_string, max1 ); // optional + static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2"); + child->getFastAttributeF32( max2_string, max2 ); // optional + static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2"); + child->getFastAttributeF32( min2_string, min2 ); // optional + + // Push these on the front of the deque, so that we can construct + // them in order later (faster) + mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) ); + } + else + { + llerrs << " Unable to resolve driven parameter: " << driven_id << llendl; + return FALSE; + } + } + return TRUE; +} + +//virtual +void LLDriverParamInfo::toStream(std::ostream &out) +{ + LLViewerVisualParamInfo::toStream(out); + out << "driver" << "\t"; + out << mDrivenInfoList.size() << "\t"; + for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) + { + LLDrivenEntryInfo driven = *iter; + out << driven.mDrivenID << "\t"; + } + + out << std::endl; + + if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() && + mDriverParam->getAvatarAppearance()->isValid()) + { + for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) + { + LLDrivenEntryInfo driven = *iter; + LLViewerVisualParam *param = + (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID); + if (param) + { + param->getInfo()->toStream(out); + if (param->getWearableType() != mWearableType) + { + if(param->getCrossWearable()) + { + out << "cross-wearable" << "\t"; + } + else + { + out << "ERROR!" << "\t"; + } + } + else + { + out << "valid" << "\t"; + } + } + else + { + llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " + << mDriverParam->getAvatarAppearance() + << " for driver parameter " << getID() << llendl; + } + out << std::endl; + } + } +} + +//----------------------------------------------------------------------------- +// LLDriverParam +//----------------------------------------------------------------------------- + +LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) : + mCurrentDistortionParam( NULL ), + mAvatarAppearance(appearance), + mWearablep(wearable) +{ + llassert(mAvatarAppearance); + if (mWearablep) + { + llassert(mAvatarAppearance->isSelf()); + } + mDefaultVec.clear(); +} + +LLDriverParam::~LLDriverParam() +{ +} + +BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return FALSE; + mInfo = info; + mID = info->mID; + info->mDriverParam = this; + + setWeight(getDefaultWeight(), FALSE ); + + return TRUE; +} + +/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const +{ + llassert(wearable); + LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable); + *new_param = *this; + return new_param; +} + +void LLDriverParam::setWeight(F32 weight, BOOL upload_bake) +{ + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + if (mIsAnimating) + { + // allow overshoot when animating + mCurWeight = weight; + } + else + { + mCurWeight = llclamp(weight, min_weight, max_weight); + } + + // driven ________ + // ^ /| |\ ^ + // | / | | \ | + // | / | | \ | + // | / | | \ | + // | / | | \ | + //-------|----|-------|----|-------> driver + // | min1 max1 max2 min2 + + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + LLDrivenEntryInfo* info = driven->mInfo; + + F32 driven_weight = 0.f; + F32 driven_min = driven->mParam->getMinWeight(); + F32 driven_max = driven->mParam->getMaxWeight(); + + if (mIsAnimating) + { + // driven param doesn't interpolate (textures, for example) + if (!driven->mParam->getAnimating()) + { + continue; + } + if( mCurWeight < info->mMin1 ) + { + if (info->mMin1 == min_weight) + { + if (info->mMin1 == info->mMax1) + { + driven_weight = driven_max; + } + else + { + //up slope extrapolation + F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 ); + driven_weight = driven_min + t * (driven_max - driven_min); + } + } + else + { + driven_weight = driven_min; + } + + setDrivenWeight(driven,driven_weight,upload_bake); + continue; + } + else + if ( mCurWeight > info->mMin2 ) + { + if (info->mMin2 == max_weight) + { + if (info->mMin2 == info->mMax2) + { + driven_weight = driven_max; + } + else + { + //down slope extrapolation + F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 ); + driven_weight = driven_max + t * (driven_min - driven_max); + } + } + else + { + driven_weight = driven_min; + } + + setDrivenWeight(driven,driven_weight,upload_bake); + continue; + } + } + + driven_weight = getDrivenWeight(driven, mCurWeight); + setDrivenWeight(driven,driven_weight,upload_bake); + } +} + +F32 LLDriverParam::getTotalDistortion() +{ + F32 sum = 0.f; + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + sum += driven->mParam->getTotalDistortion(); + } + + return sum; +} + +const LLVector4a &LLDriverParam::getAvgDistortion() +{ + // It's not actually correct to take the average of averages, but it good enough here. + LLVector4a sum; + sum.clear(); + S32 count = 0; + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + sum.add(driven->mParam->getAvgDistortion()); + count++; + } + sum.mul( 1.f/(F32)count); + + mDefaultVec = sum; + return mDefaultVec; +} + +F32 LLDriverParam::getMaxDistortion() +{ + F32 max = 0.f; + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + F32 param_max = driven->mParam->getMaxDistortion(); + if( param_max > max ) + { + max = param_max; + } + } + + return max; +} + + +LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) +{ + LLVector4a sum; + sum.clear(); + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); + } + return sum; +} + +const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + mCurrentDistortionParam = NULL; + const LLVector4a* v = NULL; + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + v = driven->mParam->getFirstDistortion( index, poly_mesh ); + if( v ) + { + mCurrentDistortionParam = driven->mParam; + break; + } + } + + return v; +}; + +const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + llassert( mCurrentDistortionParam ); + if( !mCurrentDistortionParam ) + { + return NULL; + } + + LLDrivenEntry* driven = NULL; + entry_list_t::iterator iter; + + // Set mDriven iteration to the right point + for( iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + driven = &(*iter); + if( driven->mParam == mCurrentDistortionParam ) + { + break; + } + } + + llassert(driven); + if (!driven) + { + return NULL; // shouldn't happen, but... + } + + // We're already in the middle of a param's distortions, so get the next one. + const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); + if( (!v) && (iter != mDriven.end()) ) + { + // This param is finished, so start the next param. It might not have any + // distortions, though, so we have to loop to find the next param that does. + for( iter++; iter != mDriven.end(); iter++ ) + { + driven = &(*iter); + v = driven->mParam->getFirstDistortion( index, poly_mesh ); + if( v ) + { + mCurrentDistortionParam = driven->mParam; + break; + } + } + } + + return v; +}; + +S32 LLDriverParam::getDrivenParamsCount() const +{ + return mDriven.size(); +} + +const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const +{ + if (0 > index || index >= mDriven.size()) + { + return NULL; + } + return mDriven[index].mParam; +} + +//----------------------------------------------------------------------------- +// setAnimationTarget() +//----------------------------------------------------------------------------- +void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake ) +{ + LLVisualParam::setAnimationTarget(target_value, upload_bake); + + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + F32 driven_weight = getDrivenWeight(driven, mTargetWeight); + + // this isn't normally necessary, as driver params handle interpolation of their driven params + // but texture params need to know to assume their final value at beginning of interpolation + driven->mParam->setAnimationTarget(driven_weight, upload_bake); + } +} + +//----------------------------------------------------------------------------- +// stopAnimating() +//----------------------------------------------------------------------------- +void LLDriverParam::stopAnimating(BOOL upload_bake) +{ + LLVisualParam::stopAnimating(upload_bake); + + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + driven->mParam->setAnimating(FALSE); + } +} + +/*virtual*/ +BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params) +{ + BOOL success = TRUE; + LLDriverParamInfo::entry_info_list_t::iterator iter; + for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); ++iter) + { + LLDrivenEntryInfo *driven_info = &(*iter); + S32 driven_id = driven_info->mDrivenID; + + // check for already existing links. Do not overwrite. + BOOL found = FALSE; + for (entry_list_t::iterator driven_iter = mDriven.begin(); driven_iter != mDriven.end() && !found; ++driven_iter) + { + if (driven_iter->mInfo->mDrivenID == driven_id) + { + found = TRUE; + } + } + + if (!found) + { + LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id); + bool push = param && (!only_cross_params || param->getCrossWearable()); + if (push) + { + mDriven.push_back(LLDrivenEntry( param, driven_info )); + } + else + { + success = FALSE; + } + } + } + + return success; +} + +void LLDriverParam::resetDrivenParams() +{ + mDriven.clear(); + mDriven.reserve(getInfo()->mDrivenInfoList.size()); +} + +void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) +{ + bool needs_update = (getWearableType()==driven_type); + + // if the driver has a driven entry for the passed-in wearable type, we need to refresh the value + for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + LLDrivenEntry* driven = &(*iter); + if (driven && driven->mParam && driven->mParam->getCrossWearable() && driven->mParam->getWearableType() == driven_type) + { + needs_update = true; + } + } + + + if (needs_update) + { + LLWearableType::EType driver_type = (LLWearableType::EType)getWearableType(); + + // If we've gotten here, we've added a new wearable of type "type" + // Thus this wearable needs to get updates from the driver wearable. + // The call to setVisualParamWeight seems redundant, but is necessary + // as the number of driven wearables has changed since the last update. -Nyx + LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type); + if (wearable) + { + wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false); + } + } +} + + +//----------------------------------------------------------------------------- +// getDrivenWeight() +//----------------------------------------------------------------------------- +F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight) +{ + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + const LLDrivenEntryInfo* info = driven->mInfo; + + F32 driven_weight = 0.f; + F32 driven_min = driven->mParam->getMinWeight(); + F32 driven_max = driven->mParam->getMaxWeight(); + + if( input_weight <= info->mMin1 ) + { + if( info->mMin1 == info->mMax1 && + info->mMin1 <= min_weight) + { + driven_weight = driven_max; + } + else + { + driven_weight = driven_min; + } + } + else + if( input_weight <= info->mMax1 ) + { + F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 ); + driven_weight = driven_min + t * (driven_max - driven_min); + } + else + if( input_weight <= info->mMax2 ) + { + driven_weight = driven_max; + } + else + if( input_weight <= info->mMin2 ) + { + F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 ); + driven_weight = driven_max + t * (driven_min - driven_max); + } + else + { + if (info->mMax2 >= max_weight) + { + driven_weight = driven_max; + } + else + { + driven_weight = driven_min; + } + } + + return driven_weight; +} + +void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) +{ + bool use_self = false; + if(mWearablep && + mAvatarAppearance->isValid() && + driven->mParam->getCrossWearable()) + { + LLWearable* wearable = dynamic_cast (mWearablep); + if (mAvatarAppearance->getWearableData()->isOnTop(wearable)) + { + use_self = true; + } + } + + if (use_self) + { + // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values + mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); + } + else + { + driven->mParam->setWeight( driven_weight, upload_bake ); + } +} diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h new file mode 100644 index 0000000000..30e71daad9 --- /dev/null +++ b/indra/llappearance/lldriverparam.h @@ -0,0 +1,133 @@ +/** + * @file lldriverparam.h + * @brief A visual parameter that drives (controls) other visual parameters. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDRIVERPARAM_H +#define LL_LLDRIVERPARAM_H + +#include "llviewervisualparam.h" +#include "llwearabletype.h" + +class LLAvatarAppearance; +class LLDriverParam; +class LLWearable; + +//----------------------------------------------------------------------------- + +struct LLDrivenEntryInfo +{ + LLDrivenEntryInfo( S32 id, F32 min1, F32 max1, F32 max2, F32 min2 ) + : mDrivenID( id ), mMin1( min1 ), mMax1( max1 ), mMax2( max2 ), mMin2( min2 ) {} + S32 mDrivenID; + F32 mMin1; + F32 mMax1; + F32 mMax2; + F32 mMin2; +}; + +struct LLDrivenEntry +{ + LLDrivenEntry( LLViewerVisualParam* param, LLDrivenEntryInfo *info ) + : mParam( param ), mInfo( info ) {} + LLViewerVisualParam* mParam; + LLDrivenEntryInfo* mInfo; +}; + +//----------------------------------------------------------------------------- + +class LLDriverParamInfo : public LLViewerVisualParamInfo +{ + friend class LLDriverParam; +public: + LLDriverParamInfo(); + /*virtual*/ ~LLDriverParamInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + + /*virtual*/ void toStream(std::ostream &out); + +protected: + typedef std::deque entry_info_list_t; + entry_info_list_t mDrivenInfoList; + LLDriverParam* mDriverParam; // backpointer +}; + +//----------------------------------------------------------------------------- + +class LLDriverParam : public LLViewerVisualParam +{ +private: + // Hide the default constructor. Force construction with LLAvatarAppearance. + LLDriverParam() {} +public: + LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable = NULL); + ~LLDriverParam(); + + // Special: These functions are overridden by child classes + LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLDriverParamInfo *info); + + LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } + const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + + void updateCrossDrivenParams(LLWearableType::EType driven_type); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake ); + /*virtual*/ void stopAnimating(BOOL upload_bake); + /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); + /*virtual*/ void resetDrivenParams(); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); + /*virtual*/ F32 getMaxDistortion(); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + + S32 getDrivenParamsCount() const; + const LLViewerVisualParam* getDrivenParam(S32 index) const; + +protected: + F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); + void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); + + + LLVector4a mDefaultVec; // temp holder + typedef std::vector entry_list_t; + entry_list_t mDriven; + LLViewerVisualParam* mCurrentDistortionParam; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance* mAvatarAppearance; + LLWearable* mWearablep; +}; + +#endif // LL_LLDRIVERPARAM_H diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index a741a83af7..9b70f737a0 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -40,6 +40,7 @@ #include "lltexturemanagerbridge.h" #include "llui.h" #include "llwearable.h" +#include "llwearabledata.h" #include "llvertexbuffer.h" #include "llviewervisualparam.h" @@ -1560,11 +1561,11 @@ U32 LLTexLayerTemplate::updateWearableCache() const return 0; } LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te); - U32 num_wearables = getAvatarAppearance()->getWearableCount(wearable_type); + U32 num_wearables = getAvatarAppearance()->getWearableData()->getWearableCount(wearable_type); U32 added = 0; for (U32 i = 0; i < num_wearables; i++) { - LLWearable* wearable = getAvatarAppearance()->getWearable(wearable_type, i); + LLWearable* wearable = getAvatarAppearance()->getWearableData()->getWearable(wearable_type, i); if (!wearable) { continue; diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index 8a99debac8..e1cd26bdef 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -33,6 +33,7 @@ #include "llwearabletype.h" #include "lllocaltextureobject.h" +class LLMD5; class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; @@ -98,6 +99,12 @@ public: typedef std::map texture_id_map_t; const texture_id_map_t& getTextureIDMap() const { return mTextureIDMap; } + // Something happened that requires the wearable to be updated (e.g. worn/unworn). + virtual void setUpdated() const = 0; + + // Update the baked texture hash. + virtual void addToBakedTextureHash(LLMD5& hash) const = 0; + protected: virtual void createVisualParams() = 0; diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp new file mode 100644 index 0000000000..d70bbf286a --- /dev/null +++ b/indra/llappearance/llwearabledata.cpp @@ -0,0 +1,353 @@ +/** + * @file llwearabledata.cpp + * @brief LLWearableData class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llwearabledata.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "lldriverparam.h" +#include "llmd5.h" + +LLWearableData::LLWearableData() : + mAvatarAppearance(NULL) +{ +} + +// virtual +LLWearableData::~LLWearableData() +{ +} + +using namespace LLAvatarAppearanceDefines; + +LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) +{ + LLWearable *old_wearable = getWearable(type,index); + if (!old_wearable) + { + pushWearable(type,wearable); + return; + } + + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + llwarns << "invalid type, type " << type << " index " << index << llendl; + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + llwarns << "invalid index, type " << type << " index " << index << llendl; + } + else + { + wearable_vec[index] = wearable; + old_wearable->setUpdated(); + const BOOL removed = FALSE; + wearableUpdated(wearable, removed); + } +} + +U32 LLWearableData::pushWearable(const LLWearableType::EType type, + LLWearable *wearable, + bool trigger_updated /* = true */) +{ + if (wearable == NULL) + { + // no null wearables please! + llwarns << "Null wearable sent for type " << type << llendl; + return MAX_CLOTHING_PER_TYPE; + } + if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) + { + mWearableDatas[type].push_back(wearable); + if (trigger_updated) + { + const BOOL removed = FALSE; + wearableUpdated(wearable, removed); + } + return mWearableDatas[type].size()-1; + } + return MAX_CLOTHING_PER_TYPE; +} + +// virtual +void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed) +{ + wearable->setUpdated(); + if (!removed) + { + pullCrossWearableValues(wearable->getType()); + } +} + +void LLWearableData::popWearable(LLWearable *wearable) +{ + if (wearable == NULL) + { + // nothing to do here. move along. + return; + } + + U32 index = getWearableIndex(wearable); + const LLWearableType::EType type = wearable->getType(); + + if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type)) + { + popWearable(type, index); + } +} + +void LLWearableData::popWearable(const LLWearableType::EType type, U32 index) +{ + LLWearable *wearable = getWearable(type, index); + if (wearable) + { + mWearableDatas[type].erase(mWearableDatas[type].begin() + index); + const BOOL removed = TRUE; + wearableUpdated(wearable, removed); + } +} + +void LLWearableData::clearWearableType(const LLWearableType::EType type) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + wearable_vec.clear(); +} + +bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return false; + } + + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (0 > index_a || index_a >= wearable_vec.size()) return false; + if (0 > index_b || index_b >= wearable_vec.size()) return false; + + LLWearable* wearable = wearable_vec[index_a]; + wearable_vec[index_a] = wearable_vec[index_b]; + wearable_vec[index_b] = wearable; + return true; +} + +void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type) +{ + llassert(mAvatarAppearance); + // scan through all of the avatar's visual parameters + for (LLViewerVisualParam* param = (LLViewerVisualParam*) mAvatarAppearance->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) mAvatarAppearance->getNextVisualParam()) + { + if( param ) + { + LLDriverParam *driver_param = dynamic_cast(param); + if(driver_param) + { + // parameter is a driver parameter, have it update its cross-driven params + driver_param->updateCrossDrivenParams(type); + } + } + } +} + + +U32 LLWearableData::getWearableIndex(const LLWearable *wearable) const +{ + if (wearable == NULL) + { + return MAX_CLOTHING_PER_TYPE; + } + + const LLWearableType::EType type = wearable->getType(); + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + llwarns << "tried to get wearable index with an invalid type!" << llendl; + return MAX_CLOTHING_PER_TYPE; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + for(U32 index = 0; index < wearable_vec.size(); index++) + { + if (wearable_vec[index] == wearable) + { + return index; + } + } + + return MAX_CLOTHING_PER_TYPE; +} + +BOOL LLWearableData::isOnTop(LLWearable* wearable) const +{ + if (!wearable) return FALSE; + const LLWearableType::EType type = wearable->getType(); + return ( getTopWearable(type) == wearable ); +} + +const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return 0; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + return wearable_vec.size(); +} + +U32 LLWearableData::getWearableCount(const U32 tex_index) const +{ + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); + return getWearableCount(wearable_type); +} + +LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, + BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache +{ + LLUUID hash_id; + bool hash_computed = false; + LLMD5 hash; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); + + for (U8 i=0; i < baked_dict->mWearables.size(); i++) + { + const LLWearableType::EType baked_type = baked_dict->mWearables[i]; + const U32 num_wearables = getWearableCount(baked_type); + for (U32 index = 0; index < num_wearables; ++index) + { + const LLWearable* wearable = getWearable(baked_type,index); + if (wearable) + { + wearable->addToBakedTextureHash(hash); + hash_computed = true; + } + } + } + if (hash_computed) + { + hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES); + + if (!generate_valid_hash) + { + invalidateBakedTextureHash(hash); + } + hash.finalize(); + hash.raw_digest(hash_id.mData); + } + + return hash_id; +} + + diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h new file mode 100644 index 0000000000..2931424131 --- /dev/null +++ b/indra/llappearance/llwearabledata.h @@ -0,0 +1,108 @@ +/** + * @file llwearabledata.h + * @brief LLWearableData class header file + * + * $LicenseInfo:firstyear=20012license=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_WEARABLEDATA_H +#define LL_WEARABLEDATA_H + +#include "llavatarappearancedefines.h" +#include "llerror.h" + +class LLAvatarAppearance; + +class LLWearableData +{ + // *TODO: Figure out why this is causing compile error. + //LOG_CLASS(LLWearableData); + + //-------------------------------------------------------------------- + // Constructors / destructors / Initializers + //-------------------------------------------------------------------- +public: + LLWearableData(); + virtual ~LLWearableData(); + + void setAvatarAppearance(LLAvatarAppearance* appearance) { mAvatarAppearance = appearance; } + +protected: + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; + LLWearable* getTopWearable(const LLWearableType::EType type); + const LLWearable* getTopWearable(const LLWearableType::EType type) const; + LLWearable* getBottomWearable(const LLWearableType::EType type); + const LLWearable* getBottomWearable(const LLWearableType::EType type) const; + U32 getWearableCount(const LLWearableType::EType type) const; + U32 getWearableCount(const U32 tex_index) const; + U32 getWearableIndex(const LLWearable *wearable) const; + + BOOL isOnTop(LLWearable* wearable) const; + + static const U32 MAX_CLOTHING_PER_TYPE = 5; + + //-------------------------------------------------------------------- + // Setters + //-------------------------------------------------------------------- +protected: + // Low-level data structure setter - public access is via setWearableItem, etc. + void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); + U32 pushWearable(const LLWearableType::EType type, LLWearable *wearable, + bool trigger_updated = true); + virtual void wearableUpdated(LLWearable *wearable, BOOL removed); + void popWearable(LLWearable *wearable); + void popWearable(const LLWearableType::EType type, U32 index); + void clearWearableType(const LLWearableType::EType type); + bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b); + +private: + void pullCrossWearableValues(const LLWearableType::EType type); + + //-------------------------------------------------------------------- + // Server Communication + //-------------------------------------------------------------------- +public: + LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, + BOOL generate_valid_hash = TRUE); +protected: + virtual void invalidateBakedTextureHash(LLMD5& hash) const {} + + //-------------------------------------------------------------------- + // Member variables + //-------------------------------------------------------------------- +private: + LLAvatarAppearance* mAvatarAppearance; + typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) + typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type + wearableentry_map_t mWearableDatas; + +}; + + + +#endif // LL_WEARABLEDATA_H + diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 0a6a8f9fa6..85cf1cd3f5 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -286,7 +286,7 @@ void LLCharacter::removeAnimationData(std::string name) //----------------------------------------------------------------------------- // setVisualParamWeight() //----------------------------------------------------------------------------- -BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL upload_bake) +BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake) { S32 index = which_param->getID(); visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 3ebb2bffb0..2f2b2405b6 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -197,7 +197,7 @@ public: void addVisualParam(LLVisualParam *param); void addSharedVisualParam(LLVisualParam *param); - virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 214071fa67..21b1512e58 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -158,7 +158,6 @@ set(viewer_SOURCE_FILES lldrawpooltree.cpp lldrawpoolwater.cpp lldrawpoolwlsky.cpp - lldriverparam.cpp lldynamictexture.cpp llemote.cpp llenvmanager.cpp @@ -728,7 +727,6 @@ set(viewer_HEADER_FILES lldrawpooltree.h lldrawpoolwater.h lldrawpoolwlsky.h - lldriverparam.h lldynamictexture.h llemote.h llenvmanager.h diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 08238e1aea..40cedc1b35 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -119,7 +119,7 @@ void LLAgentWearables::dump() llinfos << "Type: " << i << " count " << count << llendl; for (U32 j=0; joutputRezTiming("Sending wearables request"); - sendAgentWearablesRequest(); - } +{ + llassert(avatar); + avatar->outputRezTiming("Sending wearables request"); + sendAgentWearablesRequest(); + setAvatarAppearance(avatar); } // wearables @@ -312,7 +312,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() { for (U32 index=0; index < getWearableCount((LLWearableType::EType)type); ++index) { - LLViewerWearable* wearable = getWearable((LLWearableType::EType)type,index); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type,index); if (wearable) { if (wearable->getItemID().isNull()) @@ -354,7 +354,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() U8 type_u8 = (U8)type; gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8); - LLViewerWearable* wearable = getWearable((LLWearableType::EType)type, 0); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)type, 0); if (wearable) { //llinfos << "Sending wearable " << wearable->getName() << llendl; @@ -382,7 +382,7 @@ void LLAgentWearables::sendAgentWearablesUpdate() void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update, const std::string new_name) { - LLViewerWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); if(!old_wearable) return; bool name_changed = !new_name.empty() && (new_name != old_wearable->getName()); if (name_changed || old_wearable->isDirty() || old_wearable->isOldVersion()) @@ -465,7 +465,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, llwarns << "LLAgent::saveWearableAs() not copyable." << llendl; return; } - LLViewerWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); if (!old_wearable) { llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl; @@ -518,7 +518,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) { - LLViewerWearable* wearable = getWearable(type, index); + LLViewerWearable* wearable = getViewerWearable(type, index); llassert(wearable); if (wearable) { @@ -553,7 +553,7 @@ void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& LLUUID curr_item_id = getWearableItemID((LLWearableType::EType)i,j); if (curr_item_id == item_id) { - LLViewerWearable* old_wearable = getWearable((LLWearableType::EType)i,j); + LLViewerWearable* old_wearable = getViewerWearable((LLWearableType::EType)i,j); llassert(old_wearable); if (!old_wearable) continue; @@ -647,7 +647,7 @@ const LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& it { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - const LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + const LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -664,7 +664,7 @@ LLViewerWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getItemID() == base_item_id)) { return curr_wearable; @@ -680,7 +680,7 @@ LLViewerWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_i { for (U32 j=0; j < getWearableCount((LLWearableType::EType)i); j++) { - LLViewerWearable * curr_wearable = getWearable((LLWearableType::EType)i, j); + LLViewerWearable * curr_wearable = getViewerWearable((LLWearableType::EType)i, j); if (curr_wearable && (curr_wearable->getAssetID() == asset_id)) { return curr_wearable; @@ -699,215 +699,55 @@ void LLAgentWearables::sendAgentWearablesRequest() gAgent.sendReliableMessage(); } -// static -BOOL LLAgentWearables::selfHasWearable(LLWearableType::EType type) +LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) { - return (gAgentWearables.getWearableCount(type) > 0); + return dynamic_cast (getWearable(type, index)); } -LLViewerWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) +const LLViewerWearable* LLAgentWearables::getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) const { - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; - } + return dynamic_cast (getWearable(type, index)); } -void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index, LLViewerWearable *wearable) -{ - - LLViewerWearable *old_wearable = getWearable(type,index); - if (!old_wearable) - { - pushWearable(type,wearable); - return; - } - - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - llwarns << "invalid type, type " << type << " index " << index << llendl; - return; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - llwarns << "invalid index, type " << type << " index " << index << llendl; - } - else - { - wearable_vec[index] = wearable; - old_wearable->setLabelUpdated(); - wearableUpdated(wearable); - checkWearableAgainstInventory(wearable); - } -} - -U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLViewerWearable *wearable) -{ - if (wearable == NULL) - { - // no null wearables please! - llwarns << "Null wearable sent for type " << type << llendl; - return MAX_CLOTHING_PER_TYPE; - } - if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE) - { - mWearableDatas[type].push_back(wearable); - wearableUpdated(wearable); - checkWearableAgainstInventory(wearable); - return mWearableDatas[type].size()-1; - } - return MAX_CLOTHING_PER_TYPE; -} - -void LLAgentWearables::wearableUpdated(LLViewerWearable *wearable) +// static +BOOL LLAgentWearables::selfHasWearable(LLWearableType::EType type) { - gAgentAvatarp->wearableUpdated(wearable->getType(), FALSE); - wearable->refreshName(); - wearable->setLabelUpdated(); - - wearable->pullCrossWearableValues(); - - // Hack pt 2. If the wearable we just loaded has definition version 24, - // then force a re-save of this wearable after slamming the version number to 22. - // This number was incorrectly incremented for internal builds before release, and - // this fix will ensure that the affected wearables are re-saved with the right version number. - // the versions themselves are compatible. This code can be removed before release. - if( wearable->getDefinitionVersion() == 24 ) - { - wearable->setDefinitionVersion(22); - U32 index = getWearableIndex(wearable); - llinfos << "forcing werable type " << wearable->getType() << " to version 22 from 24" << llendl; - saveWearable(wearable->getType(),index,TRUE); - } - + return (gAgentWearables.getWearableCount(type) > 0); } -void LLAgentWearables::popWearable(LLViewerWearable *wearable) +// virtual +void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed) { - if (wearable == NULL) - { - // nothing to do here. move along. - return; - } - - U32 index = getWearableIndex(wearable); - LLWearableType::EType type = wearable->getType(); - - if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type)) + if (isAgentAvatarValid()) { - popWearable(type, index); + const BOOL upload_result = removed; + gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result); } -} -void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) -{ - LLViewerWearable *wearable = getWearable(type, index); - if (wearable) - { - mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - if (isAgentAvatarValid()) - { - gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); - } - wearable->setLabelUpdated(); - } -} + LLWearableData::wearableUpdated(wearable, removed); -U32 LLAgentWearables::getWearableIndex(const LLViewerWearable *wearable) const -{ - if (wearable == NULL) + if (!removed) { - return MAX_CLOTHING_PER_TYPE; - } + LLViewerWearable* viewer_wearable = dynamic_cast(wearable); + viewer_wearable->refreshName(); - const LLWearableType::EType type = wearable->getType(); - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - llwarns << "tried to get wearable index with an invalid type!" << llendl; - return MAX_CLOTHING_PER_TYPE; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - for(U32 index = 0; index < wearable_vec.size(); index++) - { - if (wearable_vec[index] == wearable) + // Hack pt 2. If the wearable we just loaded has definition version 24, + // then force a re-save of this wearable after slamming the version number to 22. + // This number was incorrectly incremented for internal builds before release, and + // this fix will ensure that the affected wearables are re-saved with the right version number. + // the versions themselves are compatible. This code can be removed before release. + if( wearable->getDefinitionVersion() == 24 ) { - return index; + wearable->setDefinitionVersion(22); + U32 index = getWearableIndex(wearable); + llinfos << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << llendl; + saveWearable(wearable->getType(),index,TRUE); } - } - - return MAX_CLOTHING_PER_TYPE; -} -const LLViewerWearable* LLAgentWearables::getWearable(const LLWearableType::EType type, U32 index) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; + checkWearableAgainstInventory(viewer_wearable); } } -LLViewerWearable* LLAgentWearables::getTopWearable(const LLWearableType::EType type) -{ - U32 count = getWearableCount(type); - if ( count == 0) - { - return NULL; - } - - return getWearable(type, count-1); -} - -LLViewerWearable* LLAgentWearables::getBottomWearable(const LLWearableType::EType type) -{ - if (getWearableCount(type) == 0) - { - return NULL; - } - - return getWearable(type, 0); -} - -U32 LLAgentWearables::getWearableCount(const LLWearableType::EType type) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return 0; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - return wearable_vec.size(); -} - -U32 LLAgentWearables::getWearableCount(const U32 tex_index) const -{ - const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); - return getWearableCount(wearable_type); -} - - BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const { return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end(); @@ -920,7 +760,7 @@ U32 LLAgentWearables::itemUpdatePendingCount() const const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 index) const { - const LLViewerWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getViewerWearable(type,index); if (wearable) return wearable->getItemID(); else @@ -929,7 +769,7 @@ const LLUUID LLAgentWearables::getWearableItemID(LLWearableType::EType type, U32 const LLUUID LLAgentWearables::getWearableAssetID(LLWearableType::EType type, U32 index) const { - const LLViewerWearable *wearable = getWearable(type,index); + const LLViewerWearable *wearable = getViewerWearable(type,index); if (wearable) return wearable->getAssetID(); else @@ -1095,7 +935,7 @@ void LLAgentWearables::recoverMissingWearableDone() void LLAgentWearables::addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index) { - LLViewerWearable* wearable = getWearable((LLWearableType::EType)wearable_type, wearable_index); + LLViewerWearable* wearable = getViewerWearable((LLWearableType::EType)wearable_type, wearable_index); if (!wearable) { llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl; @@ -1305,7 +1145,7 @@ void LLAgentWearables::removeWearable(const LLWearableType::EType type, bool do_ } else { - LLViewerWearable* old_wearable = getWearable(type,index); + LLViewerWearable* old_wearable = getViewerWearable(type,index); if (old_wearable) { @@ -1360,10 +1200,10 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo //LLAgentDumper dumper("removeWearable"); if (do_remove_all) { - S32 max_entry = mWearableDatas[type].size()-1; + S32 max_entry = getWearableCount(type)-1; for (S32 i=max_entry; i>=0; i--) { - LLViewerWearable* old_wearable = getWearable(type,i); + LLViewerWearable* old_wearable = getViewerWearable(type,i); //queryWearableCache(); // moved below if (old_wearable) { @@ -1371,11 +1211,11 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo old_wearable->removeFromAvatar(TRUE); } } - mWearableDatas[type].clear(); + clearWearableType(type); } else { - LLViewerWearable* old_wearable = getWearable(type, index); + LLViewerWearable* old_wearable = getViewerWearable(type, index); //queryWearableCache(); // moved below if (old_wearable) @@ -1439,8 +1279,8 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it { pushWearable(type,new_wearable); } - wearableUpdated(new_wearable); - checkWearableAgainstInventory(new_wearable); + const BOOL removed = FALSE; + wearableUpdated(new_wearable, removed); } } @@ -1491,7 +1331,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearab { // Remove old wearable, if any // MULTI_WEARABLE: hardwired to 0 - LLViewerWearable* old_wearable = getWearable(type,0); + LLViewerWearable* old_wearable = getViewerWearable(type,0); if (old_wearable) { const LLUUID& old_item_id = old_wearable->getItemID(); @@ -1560,9 +1400,10 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara if (do_append && getWearableItemID(type,0).notNull()) { new_wearable->setItemID(new_item->getUUID()); - mWearableDatas[type].push_back(new_wearable); + const bool trigger_updated = false; + pushWearable(type, new_wearable, trigger_updated); llinfos << "Added additional wearable for type " << type - << " size is now " << mWearableDatas[type].size() << llendl; + << " size is now " << getWearableCount(type) << llendl; checkWearableAgainstInventory(new_wearable); } else @@ -1570,7 +1411,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara // Replace the old wearable with a new one. llassert(new_item->getAssetUUID() == new_wearable->getAssetID()); - LLViewerWearable *old_wearable = getWearable(type,0); + LLViewerWearable *old_wearable = getViewerWearable(type,0); LLUUID old_item_id; if (old_wearable) { @@ -1585,7 +1426,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWeara gInventory.notifyObservers(); } llinfos << "Replaced current element 0 for type " << type - << " size is now " << mWearableDatas[type].size() << llendl; + << " size is now " << getWearableCount(type) << llendl; } //llinfos << "LLVOAvatar::setWearableItem()" << llendl; @@ -1652,46 +1493,14 @@ void LLAgentWearables::queryWearableCache() } } -LLUUID LLAgentWearables::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, - BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache +// virtual +void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const { - LLUUID hash_id; - bool hash_computed = false; - LLMD5 hash; - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index); - - for (U8 i=0; i < baked_dict->mWearables.size(); i++) - { - const LLWearableType::EType baked_type = baked_dict->mWearables[i]; - const U32 num_wearables = getWearableCount(baked_type); - for (U32 index = 0; index < num_wearables; ++index) - { - const LLViewerWearable* wearable = getWearable(baked_type,index); - if (wearable) - { - LLUUID asset_id = wearable->getAssetID(); - hash.update((const unsigned char*)asset_id.mData, UUID_BYTES); - hash_computed = true; - } - } - } - if (hash_computed) + // Add some garbage into the hash so that it becomes invalid. + if (isAgentAvatarValid()) { - hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES); - - // Add some garbage into the hash so that it becomes invalid. - if (!generate_valid_hash) - { - if (isAgentAvatarValid()) - { - hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES); - } - } - hash.finalize(); - hash.raw_digest(hash_id.mData); + hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES); } - - return hash_id; } // User has picked "remove from avatar" from a menu. @@ -1875,13 +1684,13 @@ void LLAgentWearables::checkWearablesLoaded() const // Returns false if the given wearable is already topmost/bottommost // (depending on closer_to_body parameter). -bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) +bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const { - const LLViewerWearable* wearable = getWearableFromItemID(item_id); + const LLWearable* wearable = getWearableFromItemID(item_id); if (!wearable) return false; LLWearableType::EType wtype = wearable->getType(); - const LLViewerWearable* marginal_wearable = closer_to_body ? getBottomWearable(wtype) : getTopWearable(wtype); + const LLWearable* marginal_wearable = closer_to_body ? getBottomWearable(wtype) : getTopWearable(wtype); if (!marginal_wearable) return false; return wearable != marginal_wearable; @@ -1918,7 +1727,7 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake) { for (S32 count = 0; count < (S32)getWearableCount((LLWearableType::EType)type); ++count) { - LLViewerWearable *wearable = getWearable((LLWearableType::EType)type,count); + LLViewerWearable *wearable = getViewerWearable((LLWearableType::EType)type,count); llassert(wearable); if (wearable) { @@ -1933,28 +1742,39 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos if (!item) return false; if (!item->isWearableType()) return false; - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(item->getWearableType()); - if (wearable_iter == mWearableDatas.end()) return false; - - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (wearable_vec.empty()) return false; + LLWearableType::EType type = item->getWearableType(); + U32 wearable_count = getWearableCount(type); + if (0 == wearable_count) return false; const LLUUID& asset_id = item->getAssetUUID(); //nowhere to move if the wearable is already on any boundary (closest to the body/furthest from the body) - if (closer_to_body && asset_id == wearable_vec.front()->getAssetID()) return false; - if (!closer_to_body && asset_id == wearable_vec.back()->getAssetID()) return false; + if (closer_to_body) + { + LLViewerWearable* bottom_wearable = dynamic_cast( getBottomWearable(type) ); + if (bottom_wearable->getAssetID() == asset_id) + { + return false; + } + } + else // !closer_to_body + { + LLViewerWearable* top_wearable = dynamic_cast( getTopWearable(type) ); + if (top_wearable->getAssetID() == asset_id) + { + return false; + } + } - for (U32 i = 0; i < wearable_vec.size(); ++i) + for (U32 i = 0; i < wearable_count; ++i) { - LLViewerWearable* wearable = wearable_vec[i]; + LLViewerWearable* wearable = getViewerWearable(type, i); if (!wearable) continue; if (wearable->getAssetID() != asset_id) continue; //swapping wearables U32 swap_i = closer_to_body ? i-1 : i+1; - wearable_vec[i] = wearable_vec[swap_i]; - wearable_vec[swap_i] = wearable; + swapWearables(type, i, swap_i); return true; } diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 41995dd55b..a60fbc969b 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -37,6 +37,7 @@ #include "llinventorymodel.h" #include "llviewerinventory.h" #include "llavatarappearancedefines.h" +#include "llwearabledata.h" class LLInventoryItem; class LLVOAvatarSelf; @@ -44,7 +45,7 @@ class LLViewerWearable; class LLInitialWearablesFetch; class LLViewerObject; -class LLAgentWearables : public LLInitClass +class LLAgentWearables : public LLInitClass, public LLWearableData { //-------------------------------------------------------------------- // Constructors / destructors / Initializers @@ -78,7 +79,7 @@ public: bool isCOFChangeInProgress() const { return mCOFChangeInProgress; } void updateWearablesLoaded(); void checkWearablesLoaded() const; - bool canMoveWearable(const LLUUID& item_id, bool closer_to_body); + bool canMoveWearable(const LLUUID& item_id, bool closer_to_body) const; // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1. bool canWearableBeRemoved(const LLViewerWearable* wearable) const; @@ -94,36 +95,22 @@ public: const LLViewerWearable* getWearableFromItemID(const LLUUID& item_id) const; LLViewerWearable* getWearableFromItemID(const LLUUID& item_id); LLViewerWearable* getWearableFromAssetID(const LLUUID& asset_id); + LLViewerWearable* getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLViewerWearable* getViewerWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; LLInventoryItem* getWearableInventoryItem(LLWearableType::EType type, U32 index /*= 0*/); static BOOL selfHasWearable(LLWearableType::EType type); - LLViewerWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); - const LLViewerWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; - LLViewerWearable* getTopWearable(const LLWearableType::EType type); - LLViewerWearable* getBottomWearable(const LLWearableType::EType type); - U32 getWearableCount(const LLWearableType::EType type) const; - U32 getWearableCount(const U32 tex_index) const; - - static const U32 MAX_CLOTHING_PER_TYPE = 5; - //-------------------------------------------------------------------- // Setters //-------------------------------------------------------------------- - private: - // Low-level data structure setter - public access is via setWearableItem, etc. - void setWearable(const LLWearableType::EType type, U32 index, LLViewerWearable *wearable); - U32 pushWearable(const LLWearableType::EType type, LLViewerWearable *wearable); - void wearableUpdated(LLViewerWearable *wearable); - void popWearable(LLViewerWearable *wearable); - void popWearable(const LLWearableType::EType type, U32 index); - + /*virtual*/void wearableUpdated(LLWearable *wearable, BOOL removed); public: void setWearableItem(LLInventoryItem* new_item, LLViewerWearable* wearable, bool do_append = false); void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLViewerWearable* >& wearables, BOOL remove); void setWearableName(const LLUUID& item_id, const std::string& new_name); + // *TODO: Move this into llappearance/LLWearableData ? void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLAvatarAppearanceDefines::ETextureIndex texture_type, U32 wearable_index); - U32 getWearableIndex(const LLViewerWearable *wearable) const; protected: void setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append = false); @@ -171,10 +158,9 @@ protected: public: // Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant) static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data); - LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, - BOOL generate_valid_hash = TRUE); protected: + /*virtual*/ void invalidateBakedTextureHash(LLMD5& hash) const; void sendAgentWearablesUpdate(); void sendAgentWearablesRequest(); void queryWearableCache(); @@ -243,10 +229,6 @@ private: // Member variables //-------------------------------------------------------------------- private: - typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) - typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type - wearableentry_map_t mWearableDatas; - static BOOL mInitialWearablesUpdateReceived; BOOL mWearablesLoaded; std::set mItemsAwaitingWearableUpdate; diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp deleted file mode 100644 index 5abf72d51f..0000000000 --- a/indra/newview/lldriverparam.cpp +++ /dev/null @@ -1,647 +0,0 @@ -/** - * @file lldriverparam.cpp - * @brief A visual parameter that drives (controls) other visual parameters. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lldriverparam.h" - -#include "llfasttimer.h" -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "llagent.h" -#include "llviewerwearable.h" -#include "llagentwearables.h" - -//----------------------------------------------------------------------------- -// LLDriverParamInfo -//----------------------------------------------------------------------------- - -LLDriverParamInfo::LLDriverParamInfo() -{ -} - -BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); - - if( !LLViewerVisualParamInfo::parseXml( node )) - return FALSE; - - LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" ); - if( !param_driver_node ) - return FALSE; - - for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" ); - child; - child = param_driver_node->getNextNamedChild()) - { - S32 driven_id; - static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); - if( child->getFastAttributeS32( id_string, driven_id ) ) - { - F32 min1 = mMinWeight; - F32 max1 = mMaxWeight; - F32 max2 = max1; - F32 min2 = max1; - - // driven ________ // - // ^ /| |\ // - // | / | | \ // - // | / | | \ // - // | / | | \ // - // | / | | \ // - //-------|----|-------|----|-------> driver // - // | min1 max1 max2 min2 - - static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1"); - child->getFastAttributeF32( min1_string, min1 ); // optional - static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1"); - child->getFastAttributeF32( max1_string, max1 ); // optional - static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2"); - child->getFastAttributeF32( max2_string, max2 ); // optional - static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2"); - child->getFastAttributeF32( min2_string, min2 ); // optional - - // Push these on the front of the deque, so that we can construct - // them in order later (faster) - mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) ); - } - else - { - llerrs << " Unable to resolve driven parameter: " << driven_id << llendl; - return FALSE; - } - } - return TRUE; -} - -//virtual -void LLDriverParamInfo::toStream(std::ostream &out) -{ - LLViewerVisualParamInfo::toStream(out); - out << "driver" << "\t"; - out << mDrivenInfoList.size() << "\t"; - for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) - { - LLDrivenEntryInfo driven = *iter; - out << driven.mDrivenID << "\t"; - } - - out << std::endl; - - if(isAgentAvatarValid()) - { - for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++) - { - LLDrivenEntryInfo driven = *iter; - LLViewerVisualParam *param = (LLViewerVisualParam*)gAgentAvatarp->getVisualParam(driven.mDrivenID); - if (param) - { - param->getInfo()->toStream(out); - if (param->getWearableType() != mWearableType) - { - if(param->getCrossWearable()) - { - out << "cross-wearable" << "\t"; - } - else - { - out << "ERROR!" << "\t"; - } - } - else - { - out << "valid" << "\t"; - } - } - else - { - llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl; - } - out << std::endl; - } - } -} - -//----------------------------------------------------------------------------- -// LLDriverParam -//----------------------------------------------------------------------------- - -LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : - mCurrentDistortionParam( NULL ), - mAvatarp(avatarp), - mWearablep(NULL) -{ - mDefaultVec.clear(); -} - -LLDriverParam::LLDriverParam(LLWearable *wearablep) : - mCurrentDistortionParam( NULL ), - mAvatarp(NULL), - mWearablep(wearablep) -{ - mDefaultVec.clear(); -} - -LLDriverParam::~LLDriverParam() -{ -} - -BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - - setWeight(getDefaultWeight(), FALSE ); - - return TRUE; -} - -void LLDriverParam::setWearable(LLWearable *wearablep) -{ - if (wearablep) - { - mWearablep = wearablep; - mAvatarp = NULL; - } -} - -void LLDriverParam::setAvatar(LLVOAvatar *avatarp) -{ - if (avatarp) - { - mWearablep = NULL; - mAvatarp = avatarp; - } -} - -/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const -{ - LLDriverParam *new_param; - if (wearable) - { - new_param = new LLDriverParam(wearable); - } - else - { - if (mWearablep) - { - new_param = new LLDriverParam(mWearablep); - } - else - { - new_param = new LLDriverParam(mAvatarp); - } - } - *new_param = *this; - return new_param; -} - -#if 0 // obsolete -BOOL LLDriverParam::parseData(LLXmlTreeNode* node) -{ - LLDriverParamInfo* info = new LLDriverParamInfo; - - info->parseXml(node); - if (!setInfo(info)) - { - delete info; - return FALSE; - } - return TRUE; -} -#endif - -void LLDriverParam::setWeight(F32 weight, BOOL upload_bake) -{ - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - if (mIsAnimating) - { - // allow overshoot when animating - mCurWeight = weight; - } - else - { - mCurWeight = llclamp(weight, min_weight, max_weight); - } - - // driven ________ - // ^ /| |\ ^ - // | / | | \ | - // | / | | \ | - // | / | | \ | - // | / | | \ | - //-------|----|-------|----|-------> driver - // | min1 max1 max2 min2 - - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - LLDrivenEntryInfo* info = driven->mInfo; - - F32 driven_weight = 0.f; - F32 driven_min = driven->mParam->getMinWeight(); - F32 driven_max = driven->mParam->getMaxWeight(); - - if (mIsAnimating) - { - // driven param doesn't interpolate (textures, for example) - if (!driven->mParam->getAnimating()) - { - continue; - } - if( mCurWeight < info->mMin1 ) - { - if (info->mMin1 == min_weight) - { - if (info->mMin1 == info->mMax1) - { - driven_weight = driven_max; - } - else - { - //up slope extrapolation - F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 ); - driven_weight = driven_min + t * (driven_max - driven_min); - } - } - else - { - driven_weight = driven_min; - } - - setDrivenWeight(driven,driven_weight,upload_bake); - continue; - } - else - if ( mCurWeight > info->mMin2 ) - { - if (info->mMin2 == max_weight) - { - if (info->mMin2 == info->mMax2) - { - driven_weight = driven_max; - } - else - { - //down slope extrapolation - F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 ); - driven_weight = driven_max + t * (driven_min - driven_max); - } - } - else - { - driven_weight = driven_min; - } - - setDrivenWeight(driven,driven_weight,upload_bake); - continue; - } - } - - driven_weight = getDrivenWeight(driven, mCurWeight); - setDrivenWeight(driven,driven_weight,upload_bake); - } -} - -F32 LLDriverParam::getTotalDistortion() -{ - F32 sum = 0.f; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getTotalDistortion(); - } - - return sum; -} - -const LLVector4a &LLDriverParam::getAvgDistortion() -{ - // It's not actually correct to take the average of averages, but it good enough here. - LLVector4a sum; - sum.clear(); - S32 count = 0; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - sum.add(driven->mParam->getAvgDistortion()); - count++; - } - sum.mul( 1.f/(F32)count); - - mDefaultVec = sum; - return mDefaultVec; -} - -F32 LLDriverParam::getMaxDistortion() -{ - F32 max = 0.f; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - F32 param_max = driven->mParam->getMaxDistortion(); - if( param_max > max ) - { - max = param_max; - } - } - - return max; -} - - -LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) -{ - LLVector4a sum; - sum.clear(); - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); - } - return sum; -} - -const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - mCurrentDistortionParam = NULL; - const LLVector4a* v = NULL; - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - v = driven->mParam->getFirstDistortion( index, poly_mesh ); - if( v ) - { - mCurrentDistortionParam = driven->mParam; - break; - } - } - - return v; -}; - -const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - llassert( mCurrentDistortionParam ); - if( !mCurrentDistortionParam ) - { - return NULL; - } - - LLDrivenEntry* driven = NULL; - entry_list_t::iterator iter; - - // Set mDriven iteration to the right point - for( iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - driven = &(*iter); - if( driven->mParam == mCurrentDistortionParam ) - { - break; - } - } - - llassert(driven); - if (!driven) - { - return NULL; // shouldn't happen, but... - } - - // We're already in the middle of a param's distortions, so get the next one. - const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); - if( (!v) && (iter != mDriven.end()) ) - { - // This param is finished, so start the next param. It might not have any - // distortions, though, so we have to loop to find the next param that does. - for( iter++; iter != mDriven.end(); iter++ ) - { - driven = &(*iter); - v = driven->mParam->getFirstDistortion( index, poly_mesh ); - if( v ) - { - mCurrentDistortionParam = driven->mParam; - break; - } - } - } - - return v; -}; - -//----------------------------------------------------------------------------- -// setAnimationTarget() -//----------------------------------------------------------------------------- -void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake ) -{ - LLVisualParam::setAnimationTarget(target_value, upload_bake); - - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - F32 driven_weight = getDrivenWeight(driven, mTargetWeight); - - // this isn't normally necessary, as driver params handle interpolation of their driven params - // but texture params need to know to assume their final value at beginning of interpolation - driven->mParam->setAnimationTarget(driven_weight, upload_bake); - } -} - -//----------------------------------------------------------------------------- -// stopAnimating() -//----------------------------------------------------------------------------- -void LLDriverParam::stopAnimating(BOOL upload_bake) -{ - LLVisualParam::stopAnimating(upload_bake); - - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - driven->mParam->setAnimating(FALSE); - } -} - -/*virtual*/ -BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params) -{ - BOOL success = TRUE; - LLDriverParamInfo::entry_info_list_t::iterator iter; - for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); ++iter) - { - LLDrivenEntryInfo *driven_info = &(*iter); - S32 driven_id = driven_info->mDrivenID; - - // check for already existing links. Do not overwrite. - BOOL found = FALSE; - for (entry_list_t::iterator driven_iter = mDriven.begin(); driven_iter != mDriven.end() && !found; ++driven_iter) - { - if (driven_iter->mInfo->mDrivenID == driven_id) - { - found = TRUE; - } - } - - if (!found) - { - LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id); - bool push = param && (!only_cross_params || param->getCrossWearable()); - if (push) - { - mDriven.push_back(LLDrivenEntry( param, driven_info )); - } - else - { - success = FALSE; - } - } - } - - return success; -} - -void LLDriverParam::resetDrivenParams() -{ - mDriven.clear(); - mDriven.reserve(getInfo()->mDrivenInfoList.size()); -} - -void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) -{ - bool needs_update = (getWearableType()==driven_type); - - // if the driver has a driven entry for the passed-in wearable type, we need to refresh the value - for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - LLDrivenEntry* driven = &(*iter); - if (driven && driven->mParam && driven->mParam->getCrossWearable() && driven->mParam->getWearableType() == driven_type) - { - needs_update = true; - } - } - - - if (needs_update) - { - LLWearableType::EType driver_type = (LLWearableType::EType)getWearableType(); - - // If we've gotten here, we've added a new wearable of type "type" - // Thus this wearable needs to get updates from the driver wearable. - // The call to setVisualParamWeight seems redundant, but is necessary - // as the number of driven wearables has changed since the last update. -Nyx - LLWearable *wearable = gAgentWearables.getTopWearable(driver_type); - if (wearable) - { - wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false); - } - } -} - - -//----------------------------------------------------------------------------- -// getDrivenWeight() -//----------------------------------------------------------------------------- -F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight) -{ - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - const LLDrivenEntryInfo* info = driven->mInfo; - - F32 driven_weight = 0.f; - F32 driven_min = driven->mParam->getMinWeight(); - F32 driven_max = driven->mParam->getMaxWeight(); - - if( input_weight <= info->mMin1 ) - { - if( info->mMin1 == info->mMax1 && - info->mMin1 <= min_weight) - { - driven_weight = driven_max; - } - else - { - driven_weight = driven_min; - } - } - else - if( input_weight <= info->mMax1 ) - { - F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 ); - driven_weight = driven_min + t * (driven_max - driven_min); - } - else - if( input_weight <= info->mMax2 ) - { - driven_weight = driven_max; - } - else - if( input_weight <= info->mMin2 ) - { - F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 ); - driven_weight = driven_max + t * (driven_min - driven_max); - } - else - { - if (info->mMax2 >= max_weight) - { - driven_weight = driven_max; - } - else - { - driven_weight = driven_min; - } - } - - return driven_weight; -} - -void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) -{ - bool use_self = false; - if(isAgentAvatarValid() && - mWearablep && - driven->mParam->getCrossWearable()) - { - LLViewerWearable* wearable = dynamic_cast (mWearablep); - if (wearable->isOnTop()) - { - use_self = true; - } - } - - if (use_self) - { - // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values - gAgentAvatarp->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); - } - else - { - driven->mParam->setWeight( driven_weight, upload_bake ); - } -} diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h deleted file mode 100644 index 7a4d711d4e..0000000000 --- a/indra/newview/lldriverparam.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file lldriverparam.h - * @brief A visual parameter that drives (controls) other visual parameters. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLDRIVERPARAM_H -#define LL_LLDRIVERPARAM_H - -#include "llviewervisualparam.h" -#include "llwearabletype.h" - -class LLPhysicsMotion; -class LLVOAvatar; -class LLWearable; - -//----------------------------------------------------------------------------- - -struct LLDrivenEntryInfo -{ - LLDrivenEntryInfo( S32 id, F32 min1, F32 max1, F32 max2, F32 min2 ) - : mDrivenID( id ), mMin1( min1 ), mMax1( max1 ), mMax2( max2 ), mMin2( min2 ) {} - S32 mDrivenID; - F32 mMin1; - F32 mMax1; - F32 mMax2; - F32 mMin2; -}; - -struct LLDrivenEntry -{ - LLDrivenEntry( LLViewerVisualParam* param, LLDrivenEntryInfo *info ) - : mParam( param ), mInfo( info ) {} - LLViewerVisualParam* mParam; - LLDrivenEntryInfo* mInfo; -}; - -//----------------------------------------------------------------------------- - -class LLDriverParamInfo : public LLViewerVisualParamInfo -{ - friend class LLDriverParam; -public: - LLDriverParamInfo(); - /*virtual*/ ~LLDriverParamInfo() {}; - - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - - /*virtual*/ void toStream(std::ostream &out); - -protected: - typedef std::deque entry_info_list_t; - entry_info_list_t mDrivenInfoList; -}; - -//----------------------------------------------------------------------------- - -class LLDriverParam : public LLViewerVisualParam -{ - friend class LLPhysicsMotion; // physics motion needs to access driven params directly. -public: - LLDriverParam(LLVOAvatar *avatarp); - LLDriverParam(LLWearable *wearablep); - ~LLDriverParam(); - - // Special: These functions are overridden by child classes - LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLDriverParamInfo *info); - - void setWearable(LLWearable *wearablep); - void setAvatar(LLVOAvatar *avatarp); - void updateCrossDrivenParams(LLWearableType::EType driven_type); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. - /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); - /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake ); - /*virtual*/ void stopAnimating(BOOL upload_bake); - /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); - /*virtual*/ void resetDrivenParams(); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector4a& getAvgDistortion(); - /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); - -protected: - F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); - void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); - - - LLVector4a mDefaultVec; // temp holder - typedef std::vector entry_list_t; - entry_list_t mDriven; - LLViewerVisualParam* mCurrentDistortionParam; - // Backlink only; don't make this an LLPointer. - LLVOAvatar* mAvatarp; - LLWearable* mWearablep; -}; - -#endif // LL_LLDRIVERPARAM_H diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 68bdf9a8d6..048837acfe 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -82,7 +82,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, if (avatarp->isSelf()) { const LLWearableType::EType wearable_type = tex_entry->mWearableType; - LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(te); @@ -174,7 +174,7 @@ void LLFloaterAvatarTextures::onClickDump(void* data) LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType((ETextureIndex)i); if (avatarp->isSelf()) { - LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, 0); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0); if (wearable) { LLLocalTextureObject *lto = wearable->getLocalTextureObject(i); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 3a199135b6..834172f58f 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -483,7 +483,7 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp U32 count = gAgentWearables.getWearableCount(type); for(U32 wearable_iter = 0; wearable_iter < count; wearable_iter++) { - LLViewerWearable* wearable = gAgentWearables.getWearable(type, wearable_iter); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_iter); if (wearable) { std::vector texture_list = wearable->getLocalTextureListSeq(); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 9aadca1d80..43bb1f57e0 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -922,7 +922,7 @@ void LLPanelEditWearable::onCommitSexChange() } bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; - LLViewerWearable* wearable = gAgentWearables.getWearable(type, index); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); if (wearable) { wearable->setVisualParamWeight(param->getID(), is_new_sex_male, FALSE); diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index cb6989c9dd..ded7d66022 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -166,7 +166,7 @@ protected: } - void setParamValue(LLViewerVisualParam *param, + void setParamValue(const LLViewerVisualParam *param, const F32 new_value_local, F32 behavior_maxeffect); @@ -673,12 +673,10 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) 0, FALSE); } - for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); - iter != driver_param->mDriven.end(); - ++iter) + S32 num_driven = driver_param->getDrivenParamsCount(); + for (S32 i = 0; i < num_driven; ++i) { - LLDrivenEntry &entry = (*iter); - LLViewerVisualParam *driven_param = entry.mParam; + const LLViewerVisualParam *driven_param = driver_param->getDrivenParam(i); setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); } } @@ -758,7 +756,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) } // Range of new_value_local is assumed to be [0 , 1] normalized. -void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param, +void LLPhysicsMotion::setParamValue(const LLViewerVisualParam *param, F32 new_value_normalized, F32 behavior_maxeffect) { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 6a692209e9..8c4a05b116 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -389,7 +389,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearab if (!wearable) { - wearable = gAgentWearables.getWearable(LLWearableType::WT_SHAPE, 0); + wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); } if (!wearable) { diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 34f24ef330..eb3a212eae 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -632,11 +632,6 @@ void LLViewerWearable::revertValues() } } -BOOL LLViewerWearable::isOnTop() const -{ - return (this == gAgentWearables.getTopWearable(mType)); -} - void LLViewerWearable::createLayers(S32 te) { LLViewerTexLayerSet *layer_set = gAgentAvatarp->getLayerSet((ETextureIndex)te); @@ -736,27 +731,8 @@ void LLViewerWearable::destroyTextures() mSavedTEMap.clear(); } -void LLViewerWearable::pullCrossWearableValues() -{ - // scan through all of the avatar's visual parameters - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->getNextVisualParam()) - { - if( param ) - { - LLDriverParam *driver_param = dynamic_cast(param); - if(driver_param) - { - // parameter is a driver parameter, have it update its - driver_param->updateCrossDrivenParams(getType()); - } - } - } -} - - -void LLViewerWearable::setLabelUpdated() const +// virtual +void LLViewerWearable::setUpdated() const { gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); } @@ -771,6 +747,13 @@ void LLViewerWearable::refreshName() } } +// virtual +void LLViewerWearable::addToBakedTextureHash(LLMD5& hash) const +{ + LLUUID asset_id = getAssetID(); + hash.update((const unsigned char*)asset_id.mData, UUID_BYTES); +} + struct LLWearableSaveData { LLWearableType::EType mType; diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index ccc26000f2..b3c1e3c3ba 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -86,17 +86,17 @@ public: void revertValues(); void saveValues(); - void pullCrossWearableValues(); - - BOOL isOnTop() const; // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). - void setLabelUpdated() const; + /*virtual*/void setUpdated() const; // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem, // not the wearable asset itself. void refreshName(); + // Update the baked texture hash. + /*virtual*/void addToBakedTextureHash(LLMD5& hash) const; + protected: typedef std::map te_map_t; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b86c5d5e8f..2309ea3488 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -644,7 +644,7 @@ static F32 calc_bouncy_animation(F32 x); LLVOAvatar::LLVOAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : - LLAvatarAppearance(), + LLAvatarAppearance(&gAgentWearables), LLViewerObject(id, pcode, regionp), mSpecialRenderMode(0), mAttachmentGeometryBytes(0), @@ -5860,30 +5860,6 @@ void LLVOAvatar::updateVisualParams() updateHeadOffset(); } -// virtual -U32 LLVOAvatar::getWearableCount(const LLWearableType::EType type) const -{ - return gAgentWearables.getWearableCount(type); -} - -// virtual -U32 LLVOAvatar::getWearableCount(const U32 tex_index) const -{ - return gAgentWearables.getWearableCount(tex_index); -} - -// virtual -LLWearable* LLVOAvatar::getWearable(const LLWearableType::EType type, U32 index /*= 0*/) -{ - return gAgentWearables.getWearable(type, index); -} - -// virtual -const LLWearable* LLVOAvatar::getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const -{ - return gAgentWearables.getWearable(type, index); -} - //----------------------------------------------------------------------------- // isActive() //----------------------------------------------------------------------------- @@ -7008,48 +6984,6 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const } } -// Unlike most wearable functions, this works for both self and other. -BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const -{ - if (mIsDummy) return TRUE; - - switch(type) - { - case LLWearableType::WT_SHAPE: - case LLWearableType::WT_SKIN: - case LLWearableType::WT_HAIR: - case LLWearableType::WT_EYES: - return TRUE; // everyone has all bodyparts - default: - break; // Do nothing - } - - /* switch(type) - case LLWearableType::WT_SHIRT: - indicator_te = TEX_UPPER_SHIRT; */ - for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); - ++tex_iter) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; - if (texture_dict->mWearableType == type) - { - // If you're checking another avatar's clothing, you don't have component textures. - // Thus, you must check to see if the corresponding baked texture is defined. - // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing - // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that - // gets baked into a texture that always exists (upper or lower). - if (texture_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); - } - return FALSE; - } - } - return FALSE; -} - //----------------------------------------------------------------------------- // clampAttachmentPositions() //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5f780da145..54719d2671 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -227,17 +227,6 @@ public: /*virtual*/BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode bool isBuilt() const { return mIsBuilt; } -/******************************************************************************** - ** ** - ** WEARABLES - **/ -public: - /*virtual*/ U32 getWearableCount(const LLWearableType::EType type) const; - /*virtual*/ U32 getWearableCount(const U32 tex_index) const; - - /*virtual*/ LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); - /*virtual*/ const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; - private: //aligned members LL_ALIGN_16(LLVector4a mImpostorExtents[2]); @@ -755,9 +744,6 @@ public: ** WEARABLES **/ -public: - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; - //-------------------------------------------------------------------- // Attachments //-------------------------------------------------------------------- diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index e836a5e4a8..c1984fa738 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -74,9 +74,7 @@ LLPointer gAgentAvatarp = NULL; BOOL isAgentAvatarValid() { - return (gAgentAvatarp.notNull() && - (gAgentAvatarp->getRegion() != NULL) && - (!gAgentAvatarp->isDead())); + return (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()); } void selfStartPhase(const std::string& phase_name) @@ -669,10 +667,16 @@ BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) return LLVOAvatar::updateCharacter(agent); } +// virtual +BOOL LLVOAvatarSelf::isValid() const +{ + return ((getRegion() != NULL) && !isDead()); +} + // virtual void LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - if (isAgentAvatarValid()) + if (isValid()) { LLVOAvatar::idleUpdate(agent, world, time); idleUpdateTractorBeam(); @@ -695,7 +699,7 @@ void LLVOAvatarSelf::resetJointPositions( void ) return LLVOAvatar::resetJointPositions(); } // virtual -BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake ) +BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake ) { if (!which_param) { @@ -723,7 +727,7 @@ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bak return setParamWeight(param,weight,upload_bake); } -BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) +BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) { if (!param) { @@ -736,7 +740,7 @@ BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL U32 size = gAgentWearables.getWearableCount(type); for (U32 count = 0; count < size; ++count) { - LLViewerWearable *wearable = gAgentWearables.getWearable(type,count); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count); if (wearable) { wearable->setVisualParamWeight(param->getID(), weight, upload_bake); @@ -762,7 +766,7 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation() // apply wearable visual params to avatar for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) { - LLViewerWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); + LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); if (wearable) { wearable->writeToAvatar(); @@ -1257,7 +1261,7 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) // Make sure the inventory is in sync with the avatar. // Update COF contents, don't trigger appearance update. - if (!isAgentAvatarValid()) + if (!isValid()) { llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; } @@ -1780,7 +1784,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te return; } LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(type); - if (!gAgentWearables.getWearable(wearable_type,index)) + if (!gAgentWearables.getViewerWearable(wearable_type,index)) { // no wearable is loaded, cannot set the texture. return; @@ -1796,7 +1800,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te LLViewerTexLayerSet *layer_set = getLayerSet(type); if (layer_set) { - layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index)); + layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getViewerWearable(wearable_type,index)); } } @@ -2286,7 +2290,7 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) { - LLViewerWearable *wearable = gAgentWearables.getWearable(wearable_type, wearable_index); + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, wearable_index); if (wearable) { const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); @@ -2361,7 +2365,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const { LLWearableType::EType type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType(i); - LLViewerWearable* wearable = gAgentWearables.getWearable(type, wearable_index); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_index); if (wearable) { return wearable->getLocalTextureObject(i); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 12886d2d36..2fe960cd1e 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -97,7 +97,7 @@ public: void resetJointPositions( void ); - /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ void updateVisualParams(); @@ -111,7 +111,7 @@ public: private: // helper function. Passed in param is assumed to be in avatar's parameter list. - BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); + BOOL setParamWeight(const LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); @@ -131,6 +131,7 @@ private: public: /*virtual*/ bool isSelf() const { return true; } + /*virtual*/ BOOL isValid() const; //-------------------------------------------------------------------- // Updates -- cgit v1.2.3 From 1a913365b594de81de56896a9fbdfd6d8c4f21e0 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 6 Sep 2012 23:08:10 +0300 Subject: CHUI-319 FIXED ("User has said something new" text shown when navigating chat history with More History button) - Added flag to chat history whether to show notification about unread messages or not --- indra/newview/llchathistory.cpp | 5 +++-- indra/newview/llchathistory.h | 6 +++++- indra/newview/skins/default/xui/en/floater_conversation_preview.xml | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e3d57ab7ae..3636f9e9d2 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -585,7 +585,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mBottomSeparatorPad(p.bottom_separator_pad), mTopHeaderPad(p.top_header_pad), mBottomHeaderPad(p.bottom_header_pad), - mIsLastMessageFromLog(false) + mIsLastMessageFromLog(false), + mNotifyAboutUnreadMsg(p.notify_unread_msg) { LLTextEditor::Params editor_params(p); editor_params.rect = getLocalRect(); @@ -707,7 +708,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL bool from_me = chat.mFromID == gAgent.getID(); mEditor->setPlainText(use_plain_text_chat_history); - if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) + if (mNotifyAboutUnreadMsg && !mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty()) { mUnreadChatSources.insert(chat.mFromName); mMoreChatPanel->setVisible(TRUE); diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 28344e6a10..990c52f31b 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -60,6 +60,8 @@ class LLChatHistory : public LLUICtrl Optional more_chat_text; + Optional notify_unread_msg; + Params() : message_header("message_header"), message_separator("message_separator"), @@ -71,7 +73,8 @@ class LLChatHistory : public LLUICtrl bottom_separator_pad("bottom_separator_pad"), top_header_pad("top_header_pad"), bottom_header_pad("bottom_header_pad"), - more_chat_text("more_chat_text") + more_chat_text("more_chat_text"), + notify_unread_msg("notify_unread_msg", true) {} }; @@ -122,6 +125,7 @@ class LLChatHistory : public LLUICtrl LLUUID mLastFromID; LLDate mLastMessageTime; bool mIsLastMessageFromLog; + bool mNotifyAboutUnreadMsg; //std::string mLastMessageTimeStr; std::string mMessageHeaderFilename; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index c837a0ee57..28ba03ebe9 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -45,6 +45,7 @@ visible="true" height="310" name="chat_history" + notify_unread_msg="false" parse_highlights="true" parse_urls="true" left="5" -- cgit v1.2.3 From fd17cb601465b3433b647b895baede9b0fd822dd Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 6 Sep 2012 23:16:22 +0300 Subject: CHUI-320 FIXED (Inconsistent name formatting in conversation log depending if user started conversation or not) - On P2P session started, before creating entry of conversation log, requesting avatar name in form of Display Name (user.name) --- indra/newview/llconversationlog.cpp | 23 ++++++++++++++++++++--- indra/newview/llconversationlog.h | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 7db6a93709..e80a709203 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llconversationlog.h" #include "lltrans.h" @@ -152,6 +153,7 @@ void LLConversation::setListenIMFloaterOpened() mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); } } + /************************************************************************/ /* LLConversationLogFriendObserver implementation */ /************************************************************************/ @@ -262,9 +264,16 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); if (session) { - LLConversation conversation(*session); - LLConversationLog::instance().logConversation(conversation); - session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + if (LLIMModel::LLIMSession::P2P_SESSION == session->mSessionType) + { + LLAvatarNameCache::get(session->mOtherParticipantID, boost::bind(&LLConversationLog::onAvatarNameCache, this, _1, _2, session)); + } + else + { + LLConversation conversation(*session); + LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); + } } } @@ -425,3 +434,11 @@ void LLConversationLog::onVoiceChannelConnected(const LLUUID& session_id, const } } } + +void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session) +{ + LLConversation conversation(*session); + conversation.setConverstionName(av_name.getCompleteName()); + LLConversationLog::instance().logConversation(conversation); + session->mVoiceChannel->setStateChangedCallback(boost::bind(&LLConversationLog::onVoiceChannelConnected, this, _5, _2)); +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 9fd54c61c9..0d7f0080e5 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -62,6 +62,7 @@ public: void setIsVoice(bool is_voice); void setIsPast (bool is_past) { mIsConversationPast = is_past; } + void setConverstionName(std::string conv_name) { mConversationName = conv_name; } /* * Resets flag of unread offline message to false when im floater with this conversation is opened. @@ -156,6 +157,8 @@ private: bool saveToFile(const std::string& filename); bool loadFromFile(const std::string& filename); + void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, LLIMModel::LLIMSession* session); + typedef std::vector conversations_vec_t; std::vector mConversations; std::set mObservers; -- cgit v1.2.3 From 973f54ace7706c6e3b12cc3364b4c7ffb1b841c9 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 6 Sep 2012 23:18:59 +0300 Subject: CHUI-324 FIXED (No sort order field set by default in conversation log) - Corrected value in settings XML --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b98fea7032..593381cb29 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10105,7 +10105,7 @@ Type U32 Value - 2 + 1 SortFriendsFirst -- cgit v1.2.3 From 62eb7ec0301c0313cedc2fcb63df8779b22a6d26 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Thu, 6 Sep 2012 23:34:47 +0300 Subject: CHUI-318 FIXED (User cannot navigate forward in chat history viewer once the More History option is selected.) - Added spinner so that user could select desired history page. Also displaying total count of pages. --- indra/newview/llfloaterconversationpreview.cpp | 11 +++++++ indra/newview/llfloaterconversationpreview.h | 3 ++ .../xui/en/floater_conversation_preview.xml | 36 +++++++++++++++++----- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 7083fb987d..c9d9d7aa3b 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -29,6 +29,7 @@ #include "llfloaterconversationpreview.h" #include "llimview.h" #include "lllineeditor.h" +#include "llspinctrl.h" #include "lltrans.h" LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) @@ -69,6 +70,15 @@ BOOL LLFloaterConversationPreview::postBuild() LLLogChat::loadChatHistory(file, mMessages, true); mCurrentPage = mMessages.size() / mPageSize; + mPageSpinner = getChild("history_page_spin"); + mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); + mPageSpinner->setMinValue(1); + mPageSpinner->setMaxValue(mCurrentPage + 1); + mPageSpinner->set(mCurrentPage + 1); + + std::string total_page_num = llformat("/ %d", mCurrentPage + 1); + getChild("page_num_label")->setValue(total_page_num); + return LLFloater::postBuild(); } @@ -128,6 +138,7 @@ void LLFloaterConversationPreview::showHistory() void LLFloaterConversationPreview::onMoreHistoryBtnClick() { + mCurrentPage = mPageSpinner->getValueF32(); if (--mCurrentPage < 0) { return; diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index 2246a44761..0341e5d2a0 100644 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -29,6 +29,8 @@ #include "llchathistory.h" #include "llfloater.h" +class LLSpinCtrl; + class LLFloaterConversationPreview : public LLFloater { public: @@ -45,6 +47,7 @@ private: void onMoreHistoryBtnClick(); void showHistory(); + LLSpinCtrl* mPageSpinner; LLChatHistory* mChatHistory; LLUUID mSessionID; int mCurrentPage; diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml index 28ba03ebe9..d74c2c252d 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -51,14 +51,36 @@ left="5" width="390"> - + name="page_label" + right="-110" + top_pad="7" + value="Page" + width="35"> + + + + -- cgit v1.2.3 From 3990180c5951e68a1ecabc538be1560e0eeffaec Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 6 Sep 2012 22:08:33 +0000 Subject: Adding appearance utility package --- .hgignore | 5 ++ debian/changelog | 6 ++ debian/control | 8 +++ debian/rules | 75 ++++++++++++++++++++----- debian/secondlife-appearance-utility.substvars | 1 + indra/CMakeLists.txt | 1 + indra/appearance_utility/CMakeLists.txt | 54 ++++++++++++++++++ indra/appearance_utility/appearance_utility.cpp | 37 ++++++++++++ indra/appearance_utility/wrapper.sh | 25 +++++++++ 9 files changed, 197 insertions(+), 15 deletions(-) create mode 100644 debian/secondlife-appearance-utility.substvars create mode 100644 indra/appearance_utility/CMakeLists.txt create mode 100644 indra/appearance_utility/appearance_utility.cpp create mode 100755 indra/appearance_utility/wrapper.sh diff --git a/.hgignore b/.hgignore index b180d92003..06d31e2f88 100644 --- a/.hgignore +++ b/.hgignore @@ -50,6 +50,11 @@ indra/web/doc/asset-upload/plugins/verify-texture installed.xml libraries tarfile_tmp +debian/secondlife-viewer* +debian/secondlife-appearance-utility* +debian/files +build-stamp +configure-stamp ^indra/lib/python/mulib.* ^web/locale.* ^web/secondlife.com.* diff --git a/debian/changelog b/debian/changelog index ce54b54c6f..b3df2fcab3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +secondlife-viewer (0.4) unstable; urgency=low + + * Adding appearance utility package + + -- Don Kjer Thu, 06 Sep 2012 19:32:55 +0000 + secondlife-viewer (0.3) unstable; urgency=low * Initial debian configuration diff --git a/debian/control b/debian/control index 50b9ed9a26..9ebd71df65 100644 --- a/debian/control +++ b/debian/control @@ -14,3 +14,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Second Life Viewer Second Life is an online virtual world developed by Linden Lab. +Package: secondlife-appearance-utility +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + ia32-libs, + ia32-libs-gtk +Description: Second Life Appearance Utility + Utility for manipulating Second Life avatar appearance. + diff --git a/debian/rules b/debian/rules index c41f02d4fb..10301bf7d3 100755 --- a/debian/rules +++ b/debian/rules @@ -9,11 +9,19 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -SRCDIR=build-linux-i686/newview/packaged -DESTDIR=$(CURDIR)/debian/secondlife-viewer -BASEDIR=opt/linden/viewer +BASEDIR=opt/linden + +VIEWER_PKG=secondlife-viewer +VIEWER_PACKAGEDIR=build-linux-i686/newview/packaged +VIEWER_DESTDIR=$(CURDIR)/debian/$(VIEWER_PKG) VIEWER_VERSION:=$(shell dpkg-parsechangelog | grep ^Version | sed 's/^Version: //') -INSTALLDIR:=$(BASEDIR)/SecondLife-i686-$(VIEWER_VERSION) +VIEWER_INSTALLDIR:=$(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) + +UTILITY_PKG=secondlife-appearance-utility +UTILITY_SRCDIR=indra/appearance_utility +UTILITY_PACKAGEDIR=build-linux-i686/appearance_utility +UTILITY_DESTDIR=$(CURDIR)/debian/$(UTILITY_PKG) +UTILITY_INSTALLDIR:=$(BASEDIR)/utilities configure: configure-stamp configure-stamp: @@ -50,24 +58,61 @@ install: build dh_installdirs # Add here commands to install the package into debian/secondlife-viewer. - for file in $$(find $(SRCDIR) -type f -o -type l | sed 's~$(SRCDIR)/~~'); do \ + for file in $$(find $(VIEWER_PACKAGEDIR) -type f -o -type l | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \ + # create containing directory \ + install -v -m 755 -o root -g root -d "$$(dirname "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file")"; \ + PERM=644; \ + if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + PERM=755; \ + fi; \ + if [ -L "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + REAL="$$( readlink -f $(VIEWER_PACKAGEDIR)/$$file )"; \ + RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(VIEWER_PACKAGEDIR)/~~' )"; \ + echo dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \ + dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \ + else \ + install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file"; \ + fi; \ + done + dh_link -p $(VIEWER_PKG) /$(VIEWER_INSTALLDIR)/secondlife /usr/bin/secondlife + dh_link -p $(VIEWER_PKG) $(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/viewer/SecondLife + + # Add here commands to install the package into debian/secondlife-appearance-utility + # create containing directory + install -v -m 755 -o root -g root -d "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)" + # install utility wrapper + install -v -m 755 -o root -g root "$(UTILITY_SRCDIR)/wrapper.sh" "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/wrapper.sh" + # install appearance-utility + install -v -m 755 -o root -g root "$(UTILITY_PACKAGEDIR)/appearance-utility-bin" "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/appearance-utility-bin" + dh_link -p $(UTILITY_PKG) $(UTILITY_INSTALLDIR)/wrapper.sh $(UTILITY_INSTALLDIR)/appearance-utility + # install xml/image resources from viewer package + for file in $$(find $(VIEWER_PACKAGEDIR)/character -name "avatar_*.xml" -o -name "*.tga" | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \ + # create containing directory \ + install -v -m 755 -o root -g root -d "$$(dirname "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/$$file")"; \ + PERM=644; \ + if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + PERM=755; \ + fi; \ + install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/$$file"; \ + done + # install viewer libraries + for file in $$(find $(VIEWER_PACKAGEDIR)/lib -type f -o -type l | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \ # create containing directory \ - install -v -m 755 -o root -g root -d "$$(dirname "$(DESTDIR)/$(INSTALLDIR)/$$file")"; \ + install -v -m 755 -o root -g root -d "$$(dirname "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/$$file")"; \ PERM=644; \ - if [ -x "$(SRCDIR)/$$file" ]; then \ + if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ PERM=755; \ fi; \ - if [ -L "$(SRCDIR)/$$file" ]; then \ - REAL="$$( readlink -f $(SRCDIR)/$$file )"; \ - RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(SRCDIR)/~~' )"; \ - echo dh_link "$(INSTALLDIR)/$$RELATIVE" "$(INSTALLDIR)/$$file" ; \ - dh_link "$(INSTALLDIR)/$$RELATIVE" "$(INSTALLDIR)/$$file" ; \ + if [ -L "$(VIEWER_PACKAGEDIR)/$$file" ]; then \ + REAL="$$( readlink -f $(VIEWER_PACKAGEDIR)/$$file )"; \ + RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(VIEWER_PACKAGEDIR)/~~' )"; \ + echo dh_link -p $(UTILITY_PKG) "$(UTILITY_INSTALLDIR)/$$RELATIVE" "$(UTILITY_INSTALLDIR)/$$file" ; \ + dh_link -p $(UTILITY_PKG) "$(UTILITY_INSTALLDIR)/$$RELATIVE" "$(UTILITY_INSTALLDIR)/$$file" ; \ else \ - install -v -m $$PERM -o root -g root "$(SRCDIR)/$$file" "$(DESTDIR)/$(INSTALLDIR)/$$file"; \ + install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(UTILITY_DESTDIR)/$(UTILITY_INSTALLDIR)/$$file"; \ fi; \ done - dh_link /$(INSTALLDIR)/secondlife /usr/bin/secondlife - dh_link $(BASEDIR)/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/SecondLife + dh_link -p $(UTILITY_PKG) /$(UTILITY_INSTALLDIR)/appearance-utility /usr/bin/appearance-utility # Build architecture-independent files here. diff --git a/debian/secondlife-appearance-utility.substvars b/debian/secondlife-appearance-utility.substvars new file mode 100644 index 0000000000..abd3ebebc3 --- /dev/null +++ b/debian/secondlife-appearance-utility.substvars @@ -0,0 +1 @@ +misc:Depends= diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 078b17bf53..4e209ff75a 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -83,6 +83,7 @@ if (VIEWER) if (LINUX) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) add_subdirectory(${VIEWER_PREFIX}linux_updater) + add_subdirectory(${VIEWER_PREFIX}appearance_utility) add_dependencies(viewer linux-crash-logger-strip-target linux-updater) elseif (DARWIN) add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) diff --git a/indra/appearance_utility/CMakeLists.txt b/indra/appearance_utility/CMakeLists.txt new file mode 100644 index 0000000000..c38f811b44 --- /dev/null +++ b/indra/appearance_utility/CMakeLists.txt @@ -0,0 +1,54 @@ +# -*- cmake -*- + +project(appearance_utility) + +include(00-Common) +include(CURL) +include(CARes) +include(OpenSSL) +include(UI) +include(LLAppearance) +include(LLCommon) +include(LLVFS) +include(LLXML) +include(LLUI) +include(Linking) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} + ${CURL_INCLUDE_DIRS} + ${CARES_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIRS} + ${UI_INCLUDE_DIRS} + ${LLAPPEARANCE_INCLUDE_DIRS} + ) + +set(appearance_utility_SOURCE_FILES appearance_utility.cpp) + +set(appearance_utility_HEADER_FILES CMakeLists.txt) + +set_source_files_properties(${appearance_utility_HEADER_FILES} + PROPERTIES HEADER_FILES_ONLY TRUE) + +list(APPEND appearance_utility_SOURCE_FILES ${appearance_utility_HEADER_FILES}) + +add_executable(appearance-utility-bin ${appearance_utility_SOURCE_FILES}) + +target_link_libraries(appearance-utility-bin + ${CURL_LIBRARIES} + ${CARES_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${CRYPTO_LIBRARIES} + ${UI_LIBRARIES} + ${LLAPPEARANCE_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLUI_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ) + +add_custom_target(appearance-utility-bin-target ALL + DEPENDS appearance-utility-bin) diff --git a/indra/appearance_utility/appearance_utility.cpp b/indra/appearance_utility/appearance_utility.cpp new file mode 100644 index 0000000000..62b1cfd237 --- /dev/null +++ b/indra/appearance_utility/appearance_utility.cpp @@ -0,0 +1,37 @@ +/** + * @file appearance_utility.cpp + * @author Don Kjer , Nyx Linden + * @brief Utility for processing avatar appearance without a full viewer 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 "linden_common.h" +#include "llerrorcontrol.h" + +int main(int argc, char** argv) +{ + printf("Test app\n"); + return 0; +} + + diff --git a/indra/appearance_utility/wrapper.sh b/indra/appearance_utility/wrapper.sh new file mode 100755 index 0000000000..87d2179a13 --- /dev/null +++ b/indra/appearance_utility/wrapper.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Simple wrapper for secondlife utilities. + +## - Avoids an often-buggy X feature that doesn't really benefit us anyway. +export SDL_VIDEO_X11_DGAMOUSE=0 + +## - Works around a problem with misconfigured 64-bit systems not finding GL +export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}":/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri + +## - The 'scim' GTK IM module widely crashes the viewer. Avoid it. +if [ "$GTK_IM_MODULE" = "scim" ]; then + export GTK_IM_MODULE=xim +fi + +EXECUTABLE="$(basename "$0")-bin" +SCRIPTSRC="$(readlink -f "$0" || echo "$0")" +RUN_PATH="$(dirname "${SCRIPTSRC}" || echo .)" +cd "${RUN_PATH}" + +export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" + +# Run the program. +"./$EXECUTABLE" "$@" +exit $? -- cgit v1.2.3 From ee5e689331ff6ba44cebaf9e9fb48f7bc3f590c4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Sep 2012 16:32:17 -0700 Subject: CHUI-285 : Completed. Update the names of the participants. --- indra/newview/llconversationmodel.cpp | 8 ++++++++ indra/newview/llconversationmodel.h | 3 +++ indra/newview/llparticipantlist.cpp | 5 ++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index aa21b08ec8..fa49987d15 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -193,6 +193,14 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, { } +void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) +{ + mName = av_name.mDisplayName; + // *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername + // *TODO : we need to request or initiate a list resort + mNeedsRefresh = true; +} + void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 5947055e0f..26c7a29d76 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" #include "llfolderviewmodel.h" +#include "llavatarname.h" // Implementation of conversations list @@ -149,6 +150,8 @@ public: void setIsMuted(bool is_muted) { mIsMuted = is_muted; mNeedsRefresh = true; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } + void onAvatarNameCache(const LLAvatarName& av_name); + void dumpDebugData(); private: diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index fa3432fc89..2282734109 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -652,6 +652,8 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); + // Binds avatar's name update callback + LLAvatarNameCache::get(avatar_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant, _2)); if (mAvatarList) { mAvatarList->getIDs().push_back(avatar_id); @@ -670,9 +672,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) mAvalineUpdater->watchAvalineCaller(avatar_id); } - // *TODO : Merov : need to declare and bind a name update callback on that "participant" instance. See LLAvatarListItem::updateAvatarName() for pattern. - // For the moment, we'll get the correct name only if it's already in the name cache (see call to LLAvatarNameCache::get() here above) - // *TODO : Merov : need to update the online/offline status of the participant. // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) -- cgit v1.2.3 From 47fe3b48fe32f9eb810a23d82eb08c11c41ac335 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 10 Sep 2012 13:48:37 +0300 Subject: CHUI-268 (Transfer the common functionality from LLNearbyChat and LLIMFloater to LLIMConversation): moved appendMessage() to base class --- indra/newview/llimconversation.cpp | 40 ++++++++++++++++++++++++++++++++++ indra/newview/llimconversation.h | 5 +++++ indra/newview/llimfloater.cpp | 19 ---------------- indra/newview/llimfloater.h | 1 - indra/newview/llnearbychat.cpp | 44 ++------------------------------------ indra/newview/llnearbychat.h | 2 -- 6 files changed, 47 insertions(+), 64 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index d8c81a7849..ef3b4f7404 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -223,6 +223,46 @@ void LLIMConversation::onFocusLost() LLTransientDockableFloater::onFocusLost(); } +std::string LLIMConversation::appendTime() +{ + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"]"; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + + return timeStr; +} + +void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args) +{ + LLChat& tmp_chat = const_cast(chat); + + if(tmp_chat.mTimeStr.empty()) + tmp_chat.mTimeStr = appendTime(); + + if (!chat.mMuted) + { + tmp_chat.mFromName = chat.mFromName; + LLSD chat_args; + if (args) chat_args = args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = + !mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + + if (mChatHistory) + { + mChatHistory->appendMessage(chat, chat_args); + } + } +} + void LLIMConversation::buildParticipantList() { diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index 50feb12aed..41a76c206e 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -104,6 +104,11 @@ protected: /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + // prepare chat's params and out one message to chatHistory + void appendMessage(const LLChat& chat, const LLSD &args = 0); + + std::string appendTime(); + bool mIsNearbyChat; bool mIsP2PChat; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 7b475c1e0b..2474fe0891 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -848,25 +848,6 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) } } -void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast(chat); - - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = !mIsP2PChat - || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - - mChatHistory->appendMessage(chat, chat_args); - } -} - void LLIMFloater::updateMessages() { std::list messages; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 7b2c9e7aef..e4a67a3d56 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -152,7 +152,6 @@ private: BOOL isInviteAllowed() const; BOOL inviteToSession(const uuid_vec_t& agent_ids); - void appendMessage(const LLChat& chat, const LLSD &args = 0); static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index c2ad8cfda3..ddd271e23f 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -69,7 +69,7 @@ S32 LLNearbyChat::sLastSpecialChatChannel = 0; -// --- 2 functions in the global namespace :( --- +// --- function in the global namespace :( --- bool isWordsName(const std::string& name) { // checking to see if it's display name plus username in parentheses @@ -89,22 +89,6 @@ bool isWordsName(const std::string& name) } } -std::string appendTime() -{ - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"]"; - - LLSD substitution; - - substitution["datetime"] = (S32) utc_time; - LLStringUtil::format (timeStr, substitution); - - return timeStr; -} - - const S32 EXPANDED_HEIGHT = 266; const S32 COLLAPSED_HEIGHT = 60; const S32 EXPANDED_MIN_HEIGHT = 150; @@ -129,6 +113,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& llsd) mSpeakerMgr(NULL), mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) { + mIsP2PChat = false; mIsNearbyChat = true; setIsChrome(TRUE); mKey = LLSD(); @@ -604,31 +589,6 @@ void LLNearbyChat::sendChat( EChatType type ) } } - -void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) -{ - LLChat& tmp_chat = const_cast(chat); - - if(tmp_chat.mTimeStr.empty()) - tmp_chat.mTimeStr = appendTime(); - - if (!chat.mMuted) - { - tmp_chat.mFromName = chat.mFromName; - LLSD chat_args; - if (args) chat_args = args; - chat_args["use_plain_text_chat_history"] = - gSavedSettings.getBOOL("PlainTextChatHistory"); - chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); - chat_args["show_names_for_p2p_conv"] = true; - - if (mChatHistory) - { - mChatHistory->appendMessage(chat, chat_args); - } - } -} - void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { appendMessage(chat, args); diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 1db7afc01f..2cbafbfa62 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -108,8 +108,6 @@ protected: private: - // prepare chat's params and out one message to chatHistory - void appendMessage(const LLChat& chat, const LLSD &args = 0); void onNearbySpeakers (); /*virtual*/ void refresh(); -- cgit v1.2.3 From d9309bd16334a7d76da1b02e8fc43117a06ef7b2 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 7 Sep 2012 12:34:21 +0300 Subject: CHUI-323 FIXED (Local chat message panel out of position in Conversation floater): Prevented too early creation LLNearbyChat --- indra/newview/llimconversation.cpp | 28 ++++++++++++++-------------- indra/newview/llnearbychathandler.cpp | 3 ++- indra/newview/llnotificationhandlerutil.cpp | 2 +- indra/newview/llnotificationtiphandler.cpp | 2 +- indra/newview/llviewerwindow.cpp | 6 +++--- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index ef3b4f7404..216c5bbd70 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -148,7 +148,7 @@ BOOL LLIMConversation::postBuild() updateHeaderAndToolbar(); - mSaveRect = !getHost(); + mSaveRect = isTornOff(); initRectControl(); if (isChatMultiTab()) @@ -349,11 +349,11 @@ void LLIMConversation::hideOrShowTitle() LLView* floater_contents = getChild("contents_view"); LLRect floater_rect = getLocalRect(); - S32 top_border_of_contents = floater_rect.mTop - (getHost()? 0 : floater_header_size); + S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); - mDragHandle->setVisible(!getHost()); + mDragHandle->setVisible(isTornOff()); floater_contents->setShape(contents_rect); } @@ -371,8 +371,8 @@ void LLIMConversation::hideAllStandardButtons() void LLIMConversation::updateHeaderAndToolbar() { - bool is_hosted = !!getHost(); - if (is_hosted) + bool is_torn_off = !getHost(); + if (!is_torn_off) { hideAllStandardButtons(); } @@ -381,7 +381,7 @@ void LLIMConversation::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - !is_hosted + is_torn_off && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -389,21 +389,21 @@ void LLIMConversation::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = is_hosted || is_participant_list_visible; + bool is_expanded = !is_torn_off || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(!is_hosted); + mDragHandle->setTitleVisible(is_torn_off); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(is_hosted || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_hosted? "tear_off_icon" : "return_icon")); + mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mCloseBtn->setVisible(is_hosted && !mIsNearbyChat); + mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); enableDisableCallBtn(); @@ -440,7 +440,7 @@ void LLIMConversation::processChatHistoryStyleUpdate() } } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (nearby_chat) { nearby_chat->reloadMessages(); @@ -510,8 +510,8 @@ void LLIMConversation::onClose(bool app_quitting) void LLIMConversation::onTearOffClicked() { - setFollows(getHost()? FOLLOWS_NONE : FOLLOWS_ALL); - mSaveRect = !getHost(); + setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); + mSaveRect = isTornOff(); initRectControl(); LLFloater::onClickTearOff(this); updateHeaderAndToolbar(); diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index ca3fffeffd..f3e17ea61b 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -487,6 +487,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, if(chat_msg.mText.empty()) return;//don't process empty messages + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + // Build notification data LLSD chat; chat["message"] = chat_msg.mText; @@ -537,7 +539,6 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); nearby_chat->addMessage(chat_msg, true, args); if(chat_msg.mSourceType == CHAT_SOURCE_AGENT diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 2484040ac4..9fd73746e8 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -181,7 +181,7 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( // static void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type) { - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (nearby_chat) { LLChat chat_msg(notification->getMessage()); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index ef6668247c..a293e6acb6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -86,7 +86,7 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) // don't show toast if Nearby Chat is opened LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); - if (nearby_chat && nearby_chat->isChatVisible()) + if (nearby_chat->isChatVisible()) { return false; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 791cadaee4..403288b2fd 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2493,7 +2493,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); // Traverses up the hierarchy if( keyboard_focus ) @@ -2561,10 +2561,10 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, // no view has keyboard focus, this is a printable character key (and no modifier key is // pressed except shift), then give focus to nearby chat (STORM-560) - if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && + if ( nearby_chat && gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { - LLChatEntry* chat_editor = nearby_chat->getChatBox(); + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance("nearby_chat")->getChatBox(); if (chat_editor) { // passing NULL here, character will be added later when it is handled by character handler. -- cgit v1.2.3 From 42dbf23dc56e0ab6842dd14b5701ffdb359f8bb6 Mon Sep 17 00:00:00 2001 From: Paul ProductEngine Date: Fri, 7 Sep 2012 21:35:08 +0300 Subject: CHUI-325 FIXED (Cap conversation log to 30 days, purge older data on login) - Remove conversations older than 30 days from call log --- indra/newview/llconversationlog.cpp | 22 ++++++++++++++++++++++ indra/newview/llconversationlog.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index e80a709203..cc02e18698 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -30,6 +30,8 @@ #include "llconversationlog.h" #include "lltrans.h" +const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec + struct Conversation_params { Conversation_params(time_t time) @@ -139,6 +141,14 @@ const std::string LLConversation::createTimestamp(const time_t& utc_time) return timeStr; } +bool LLConversation::isOlderThan(U32 days) const +{ + time_t now = time_corrected(); + U32 age = (U32)((now - mTime) / SEC_PER_DAY); // age of conversation in days + + return age > days; +} + void LLConversation::setListenIMFloaterOpened() { LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); @@ -394,10 +404,22 @@ bool LLConversationLog::loadFromFile(const std::string& filename) params.mHistoryFileName = std::string(history_file_name); LLConversation conversation(params); + + // CHUI-325 + // The conversation log should be capped to the last 30 days. Conversations with the last utterance + // being over 30 days old should be purged from the conversation log text file on login. + if (conversation.isOlderThan(CONVERSATION_LIFETIME)) + { + continue; + } + mConversations.push_back(conversation); } fclose(fp); + LLFile::remove(filename); + cache(); + notifyObservers(); return true; } diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 0d7f0080e5..16be37d67a 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -64,6 +64,8 @@ public: void setIsPast (bool is_past) { mIsConversationPast = is_past; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } + bool isOlderThan(U32 days) const; + /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ -- cgit v1.2.3 From 2b2fd9e97526d10b0b4d34154cc0a46f957acba7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 7 Sep 2012 17:48:09 -0400 Subject: enhanced XML archetype dumping, added to per-avatar menus --- indra/newview/llviewermenu.cpp | 9 +++++- indra/newview/llvoavatar.cpp | 37 ++++++++++++++++++---- indra/newview/llvoavatar.h | 6 ++-- .../skins/default/xui/en/menu_attachment_other.xml | 8 +++++ .../skins/default/xui/en/menu_attachment_self.xml | 8 +++++ .../skins/default/xui/en/menu_avatar_other.xml | 8 +++++ .../skins/default/xui/en/menu_avatar_self.xml | 16 ++++++++++ .../default/xui/en/menu_inspect_avatar_gear.xml | 8 +++++ .../default/xui/en/menu_inspect_self_gear.xml | 8 +++++ 9 files changed, 99 insertions(+), 9 deletions(-) mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_attachment_other.xml mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_attachment_self.xml mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_avatar_other.xml mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_avatar_self.xml mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml mode change 100644 => 100755 indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3c0136c258..9c748c7f86 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1600,7 +1600,14 @@ class LLAdvancedAppearanceToXML : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLVOAvatar::dumpArchetypeXML(NULL); + std::string emptyname; + LLVOAvatar* avatar = + find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if (!avatar) + { + avatar = gAgentAvatarp; + } + avatar->dumpArchetypeXML(emptyname); return true; } }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d92caf1edb..39ad8fc8d6 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -36,6 +36,7 @@ #include #include +#include #include "llaudioengine.h" #include "noise.h" @@ -7762,11 +7763,35 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) dirtyMesh(); } -// static -void LLVOAvatar::dumpArchetypeXML( void* ) +void LLVOAvatar::dumpArchetypeXML(const std::string& filename ) { + std::string outfilename(filename); + if (outfilename.empty()) + { + std::string fullname = getFullname(); + if (!fullname.empty()) + { + typedef std::map file_num_type; + static file_num_type file_nums; + file_num_type::iterator it = file_nums.find(fullname); + S32 num = 0; + if (it != file_nums.end()) + { + num = it->second; + } + std::ostringstream temp; + temp << std::setw(4) << std::setfill('0') << num; + file_nums[fullname] = num+1; + outfilename = fullname + " " + temp.str() + ".xml"; + } + } + if (outfilename.empty()) + { + outfilename = std::string("new archetype.xml"); + } + LLAPRFile outfile; - outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml"), LL_APR_WB ); + outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,outfilename), LL_APR_WB ); apr_file_t* file = outfile.getFileHandle(); if (!file) { @@ -7782,12 +7807,12 @@ void LLVOAvatar::dumpArchetypeXML( void* ) apr_file_printf( file, "\n\t\n" ); // only body parts, not clothing. - for (S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_EYES; type++) + for (S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_COUNT; type++) { const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); apr_file_printf( file, "\n\t\t\n", wearable_name.c_str() ); - for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam()) + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) { LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; if( (viewer_param->getWearableType() == type) && @@ -7803,7 +7828,7 @@ void LLVOAvatar::dumpArchetypeXML( void* ) if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0); + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); if( te_image ) { std::string uuid_str; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 3f65dec11c..5ec2009971 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -710,7 +710,9 @@ public: //-------------------------------------------------------------------- public: BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } - BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode + BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode + BOOL isUsingLocalAppearance() const { return mUseLocalAppearance; } + private: BOOL mAppearanceAnimating; LLFrameTimer mAppearanceMorphTimer; @@ -1014,7 +1016,7 @@ private: // General //-------------------------------------------------------------------- public: - static void dumpArchetypeXML(void*); + void dumpArchetypeXML(const std::string& filename); static void dumpBakedStatus(); const std::string getBakedStatusForPrintout() const; void dumpAvatarTEs(const std::string& context) const; diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml old mode 100644 new mode 100755 index b46b62ec4d..6f92273097 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -79,6 +79,14 @@ + + + + diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml old mode 100644 new mode 100755 index b8128da358..84e26268bd --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -123,6 +123,14 @@ name="Edit Outfit"> + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml old mode 100644 new mode 100755 index d9bdfece38..0e79b0fee3 --- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -261,4 +261,20 @@ + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml old mode 100644 new mode 100755 index 76b188220d..4fdfb2281b --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml @@ -112,6 +112,14 @@ + + + + diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml old mode 100644 new mode 100755 index 5e7b16ed4a..f935f0f312 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml @@ -249,4 +249,12 @@ + + + + -- cgit v1.2.3 From 5f8b94094877730082340dc21ff0162b6177a427 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 8 Sep 2012 01:10:00 +0000 Subject: Fleshing out appearance-utility standalone app. Added input/output processing, argument parsing, and general error handling. --- indra/appearance_utility/appearance_utility.cpp | 396 +++++++++++++++++++++++- 1 file changed, 394 insertions(+), 2 deletions(-) diff --git a/indra/appearance_utility/appearance_utility.cpp b/indra/appearance_utility/appearance_utility.cpp index 62b1cfd237..130bca84a8 100644 --- a/indra/appearance_utility/appearance_utility.cpp +++ b/indra/appearance_utility/appearance_utility.cpp @@ -25,13 +25,405 @@ * $/LicenseInfo$ */ +#include +#include +#include + #include "linden_common.h" + +#include "llapp.h" +#include "llapr.h" #include "llerrorcontrol.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "llsdutil.h" + +enum EResult +{ + RV_SUCCESS = 0, + RV_UNKNOWN_ERROR, + RV_BAD_ARGUMENTS, + RV_UNABLE_OPEN, + RV_UNABLE_TO_PARSE, +}; + +static const std::string MESSAGE_RV_UNKNOWN("Unknown error."); +static const std::string MESSAGE_RV_ARGUMENTS +("Invalid arguments: "); +static const std::string MESSAGE_RV_UNABLE_OPEN("Unable to open file: "); +static const std::string MESSAGE_RV_UNABLE_TO_PARSE("Unable to parse input LLSD."); + +static const apr_getopt_option_t APPEARANCE_UTILITY_OPTIONS[] = +{ + {"tbd", 't', 0, "Extract dump information from a mesh asset."}, + {"output", 'o', 1, "The output file to write to. Default is stdout"}, + {"agent-id", 'a', 1, "The agent-id of the user."}, + {"grid", 'g', 1, "The grid."}, + {"help", 'h', 0, "Print the help message."}, + {0, 0, 0, 0} +}; + +const std::string NOTHING_EXTRA(""); + +/** + * Helper to return the standard error based on the return value. + */ +LLSD spit_error(EResult rv, const std::string& extra = NOTHING_EXTRA); + +/** + * Helper to generate an error output based on code and message. + */ +LLSD spit_error(const std::string& key, const std::string& message); + + + +LLSD spit_error(EResult value, const std::string& extra) +{ + LLSD rv; + switch(value) + { + case RV_UNKNOWN_ERROR: + rv = spit_error("unknown", MESSAGE_RV_UNKNOWN); + case RV_BAD_ARGUMENTS: + rv = spit_error("arguments", MESSAGE_RV_ARGUMENTS + extra); + break; + case RV_UNABLE_OPEN: + rv = spit_error("file", MESSAGE_RV_UNABLE_OPEN + extra); + break; + case RV_UNABLE_TO_PARSE: + rv = spit_error("input", MESSAGE_RV_UNABLE_TO_PARSE); + break; + default: + rv = spit_error("arguments", "Invalid arguments to spit_error"); + break; + } + return rv; +} + +LLSD spit_error(const std::string& key, const std::string& message) +{ + LLSD rv; + rv["success"] = false; + rv["error"]["key"] = key; + rv["error"]["message"] = message; + return rv; +} + + +std::string usage(const char* command) +{ + std::ostringstream ostr; + ostr << "Utilities for processing agent appearance data." + << std::endl << std::endl + << "Usage:" << std::endl + << "\t" << command << " [options] filename" << std::endl << std::endl + << "Will read from stdin if filename is set to '-'." << std::endl << std::endl + << "Options:" << std::endl; + const apr_getopt_option_t* option = &APPEARANCE_UTILITY_OPTIONS[0]; + while(option->name) + { + ostr << "\t--" << option->name << "\t\t" + << option->description << std::endl; + ++option; + } + ostr << std::endl << "Return Values:" << std::endl + << "\t0\t\tSuccess." << std::endl + << "\t1\t\tUnknown error." << std::endl + << "\t2\t\tBad arguments." << std::endl + << "\t3\t\tUnable to open file. Possibly wrong filename" + << " or bad permissions." << std::endl + << "\t4\t\tUnable to parse input LLSD." << std::endl + << std::endl + << "Output:" << std::endl + << "If a non-zero status code is returned, additional error information" + << " will be returned on stderr." << std::endl + << "* This will be in the form of an LLSD document." << std::endl + << "* Check ['error']['message'] to get a human readable message." << std::endl + << "If a zero status code is returned, processed output will be written" + << " to the file specified by --out (or stdout, if not specified)." << std::endl + << std::endl + << std::endl; + return ostr.str(); +} + +EResult process_tbd(LLSD& input, std::ostream& output, LLSD& error_llsd) +{ + EResult rv = RV_SUCCESS; + + LLSD result; + result["success"] = true; + result["input"] = input; + output << LLSDOStreamer(result); + + return rv; +} + +/** + * @brief Called by main() to ensure proper cleanup. Basically main(). + */ +EResult process_command(int argc, char** argv, LLSD& error_llsd) +{ + EResult rv = RV_SUCCESS; + + ////// BEGIN OPTION PARSING ////// + // Check for '-' as last option, since apr doesn't seem to like that. + bool read_stdin = false; + bool write_stdout = true; + if (std::string(argv[argc-1]) == "-") + { + read_stdin = true; + argc--; + } + + apr_status_t apr_err; + const char* opt_arg = NULL; + int opt_id = 0; + apr_getopt_t* os = NULL; + if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv)) + { + std::cerr << "Unable to initialize apr" << std::endl; + rv = RV_UNKNOWN_ERROR; + error_llsd = spit_error(rv); + return rv; + } + + bool tbd = false; + LLUUID agent_id; + std::string output_filename; + std::string grid; + while(true) + { + apr_err = apr_getopt_long(os, APPEARANCE_UTILITY_OPTIONS, &opt_id, &opt_arg); + if(APR_STATUS_IS_EOF(apr_err)) break; + if(apr_err) + { + char buf[MAX_STRING]; /* Flawfinder: ignore */ + std::cerr << "Error parsing options: " + << apr_strerror(apr_err, buf, MAX_STRING) << std::endl; + std::cerr << usage(os->argv[0]) << std::endl; + rv = RV_BAD_ARGUMENTS; + error_llsd = spit_error(rv, buf); + return rv; + } + switch (opt_id) + { + case 't': + tbd = true; + break; + case 'o': + output_filename.assign(opt_arg); + write_stdout=false; + break; + case 'a': + agent_id.set(opt_arg); + if (agent_id.isNull()) + { + const char* INVALID_AGENT_ID="agent-id must be a valid uuid."; + std::cerr << "Incorrect arguments. " << INVALID_AGENT_ID + << std::endl << usage(argv[0]) << std::endl; + rv = RV_BAD_ARGUMENTS; + error_llsd = spit_error(rv, INVALID_AGENT_ID); + return rv; + } + break; + case 'g': + grid = opt_arg; + break; + case 'h': + std::cout << usage(os->argv[0]); + return RV_SUCCESS; + default: + std::cerr << usage(os->argv[0]); + rv = RV_BAD_ARGUMENTS; + error_llsd = spit_error(rv, "Unknown option."); + return rv; + } + } + ////// END OPTION PARSING ////// + + ///// BEGIN ARGUMENT VALIDATION ///// + std::string input_filename; + + // Make sure we don't have more than one command specified. + if (!tbd) + { + const char* INVALID_MODE="Must specify mode. (tbd)"; + std::cerr << "Incorrect arguments. " << INVALID_MODE + << std::endl; + std::cerr << usage(os->argv[0]); + rv = RV_BAD_ARGUMENTS; + error_llsd = spit_error(rv, INVALID_MODE); + return rv; + } + + // *TODO: Add debug mode(s). Skip this in debug mode. + LLError::setDefaultLevel(LLError::LEVEL_WARN); + + if (!read_stdin) + { + bool valid_input_filename = false; + // Try to grab the input filename. + if (os->argv && os->argv[os->ind]) + { + input_filename.assign(os->argv[os->ind]); + if (! input_filename.empty() ) + { + valid_input_filename = true; + } + } + if (!valid_input_filename) + { + const char* INVALID_FILENAME="Must specify input file."; + std::cerr << "Incorrect arguments. " << INVALID_FILENAME + << std::endl << usage(os->argv[0]) << std::endl; + rv = RV_BAD_ARGUMENTS; + error_llsd = spit_error(rv, INVALID_FILENAME); + return rv; + } + } + + ///// END ARGUMENT VALIDATION ///// + + ///// BEGIN OPEN INPUT FILE //// + std::ifstream input_file; + std::stringstream data; + std::istream* input = NULL; + + if (read_stdin) + { + // Read unformated data from stdin in to memory. + const S32 BUFFER_SIZE = BUFSIZ; + char buffer[BUFFER_SIZE]; + while (true) + { + std::cin.read(buffer, BUFFER_SIZE); + // Check if anything out of the ordinary happened. + if (!std::cin) + { + // See if something 'really bad' happened, or if we just + // used up all of our buffer. + if (std::cin.bad()) + { + std::cerr << "Problem reading standard input." << std::endl; + rv = RV_UNKNOWN_ERROR; + error_llsd = spit_error(rv); + return rv; + } + else + { + // Output normally. + data.write(buffer, std::cin.gcount()); + if (std::cin.eof()) break; + + // Clear this problem. We have handled it. + std::cin.clear(); + } + } + else + { + data.write(buffer, std::cin.gcount()); + if (std::cin.eof()) break; + } + } + input = &data; + } + else + { + // Make sure we can open the input file. + input_file.open( input_filename.c_str(), std::fstream::in ); + if ( input_file.fail()) + { + std::cerr << "Couldn't open input file '" << input_filename << "'." << std::endl; + rv = RV_UNABLE_OPEN; + error_llsd = spit_error(rv, input_filename); + return rv; + } + input = &input_file; + } + ///// END OPEN INPUT FILE //// + + ///// BEGIN OPEN OUTPUT FILE //// + std::fstream output_file; + std::ostream* output = NULL; + + // Make sure we can open the output file. + if (write_stdout) + { + output = &std::cout; + } + else + { + output_file.open( output_filename.c_str(), std::fstream::out ); + if ( output_file.fail() ) + { + std::cerr << "Couldn't open output file '" << output_filename << "'." << std::endl; + rv = RV_UNABLE_OPEN; + error_llsd = spit_error(rv, output_filename); + if (!read_stdin) input_file.close(); + return rv; + } + output = &output_file; + } + ///// END OPEN OUTPUT FILE //// + + ///// BEGIN INPUT PARSING //// + LLSD input_llsd; + LLSDSerialize::fromXML( input_llsd, *input ); + if (input_llsd.isUndefined()) + { + rv = RV_UNABLE_TO_PARSE; + error_llsd = spit_error(rv); + return rv; + } + + ///// END INPUT PARSING //// + + if (tbd) + { + rv = process_tbd(input_llsd, *output, error_llsd); + } + + if (!write_stdout) output_file.close(); + if (!read_stdin) input_file.close(); + + return rv; +} + +class LLAppAppearanceUtility : public LLApp +{ +public: + LLAppAppearanceUtility() {} + virtual ~LLAppAppearanceUtility() {} + /*virtual*/ bool init(); + /*virtual*/ bool cleanup(); + /*virtual*/ bool mainLoop() { return true;} +}; + +bool LLAppAppearanceUtility::init() +{ + return true; +} + +bool LLAppAppearanceUtility::cleanup() +{ + return true; +} int main(int argc, char** argv) { - printf("Test app\n"); - return 0; + ll_init_apr(); + LLAppAppearanceUtility* app = new LLAppAppearanceUtility(); + app->init(); + LLSD error_llsd; + EResult rv = process_command(argc, argv, error_llsd); + if (RV_SUCCESS != rv) + { + std::cerr << LLSDOStreamer(error_llsd); + } + app->cleanup(); + delete app; + ll_cleanup_apr(); + return (int) rv; } -- cgit v1.2.3 From c26867bb6d1226c82c11f2f386f73b6d8e3ed749 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Sep 2012 19:53:38 -0700 Subject: CHUI-285 : Implement sort, alphabetical only for the moment --- indra/newview/llconversationmodel.cpp | 38 +++++++++++++++++++++++++--------- indra/newview/llconversationmodel.h | 15 +++----------- indra/newview/llimfloatercontainer.cpp | 16 ++++++++++++-- indra/newview/llimfloatercontainer.h | 2 ++ indra/newview/llparticipantlist.cpp | 2 -- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index fa49987d15..e810bac1d9 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -78,14 +78,6 @@ void LLConversationItem::showProperties(void) { } -bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const -{ - // We compare only by name for the moment - // *TODO : Implement the sorting by date - S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); - return (compare < 0); -} - // // LLConversationItemSession // @@ -197,12 +189,38 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam { mName = av_name.mDisplayName; // *TODO : we should also store that one, to be used in the tooltip : av_name.mUsername - // *TODO : we need to request or initiate a list resort mNeedsRefresh = true; + if (mParent) + { + mParent->requestSort(); + } } void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; -} +} + +// +// LLConversationSort +// + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ + // For the moment, we sort only by name + // *TODO : Implement the sorting by date as well (most recent first) + // *TODO : Check the type of item (session/participants) as order should be different for both (eventually) + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); + return (compare < 0); +} + +// +// LLConversationViewModel +// + +void LLConversationViewModel::sort(LLFolderViewFolder* folder) +{ + base_t::sort(folder); +} + // EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 26c7a29d76..2775bf8186 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -208,23 +208,14 @@ private: class LLConversationSort { public: - LLConversationSort(U32 order = 0) - : mSortOrder(order), - mByDate(false), - mByName(false) - { - mByDate = (order & LLConversationFilter::SO_DATE); - mByName = (order & LLConversationFilter::SO_NAME); - } + LLConversationSort(U32 order = 0) : mSortOrder(order) { } - bool isByDate() const { return mByDate; } + bool isByDate() const { return (mSortOrder & LLConversationFilter::SO_DATE); } U32 getSortOrder() const { return mSortOrder; } bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; private: U32 mSortOrder; - bool mByDate; - bool mByName; }; class LLConversationViewModel @@ -233,7 +224,7 @@ class LLConversationViewModel public: typedef LLFolderViewModel base_t; - void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort + void sort(LLFolderViewFolder* folder); bool contentsReady() { return true; } // *TODO : we need to check that participants names are available somewhat bool startDrag(std::vector& items) { return false; } // We do not allow drag of conversation items diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 56648d09b5..fa0750c39c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -45,6 +45,7 @@ #include "lltransientfloatermgr.h" #include "llviewercontrol.h" #include "llconversationview.h" +#include "llcallbacklist.h" // // LLIMFloaterContainer @@ -65,6 +66,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) LLIMFloaterContainer::~LLIMFloaterContainer() { + gIdleCallbacks.deleteFunction(idle, this); + mNewMessageConnection.disconnect(); LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); @@ -139,6 +142,9 @@ BOOL LLIMFloaterContainer::postBuild() LLAvatarNameCache::addUseDisplayNamesCallback( boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + // Add callback: we'll take care of view updates on idle + gIdleCallbacks.addFunction(idle, this); + return TRUE; } @@ -290,6 +296,13 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +//static +void LLIMFloaterContainer::idle(void* user_data) +{ + LLIMFloaterContainer* panel = (LLIMFloaterContainer*)user_data; + panel->mConversationsRoot->update(); +} + void LLIMFloaterContainer::draw() { // CHUI Notes @@ -579,7 +592,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) } if (!item) { - llinfos << "Merov debug : Couldn't create conversation session item : " << display_name << llendl; + llwarns << "Couldn't create conversation session item : " << display_name << llendl; return; } // *TODO: Should we flag LLConversationItemSession with a mIsNearbyChat? @@ -602,7 +615,6 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) // Note: usually, we do not get an updated avatar list at that point LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); - llinfos << "Merov debug : create participant, children size = " << item->getChildrenCount() << llendl; while (current_participant_model != end_participant_model) { LLConversationItem* participant_model = dynamic_cast(*current_participant_model); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index a72a3e2221..c4dd386d7c 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -75,6 +75,8 @@ public: void collapseMessagesPane(bool collapse); + // Callbacks + static void idle(void* user_data); // LLIMSessionObserver observe triggers /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 2282734109..0d1a37c835 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -675,8 +675,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Merov : need to update the online/offline status of the participant. // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) - llinfos << "Merov debug : added participant, name = " << participant->getName() << llendl; - // Add the participant model to the session's children list addParticipant(participant); -- cgit v1.2.3 From 77b33d9623c08152932282048fe847d79fcf43cd Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Fri, 7 Sep 2012 23:17:34 -0400 Subject: SH-3264 Porting over the XML loading of the avatar structure to llappearance Moved over the necessary classes to llappearance to support the loading of the avatar's structure & params from file. --- indra/llappearance/CMakeLists.txt | 10 + indra/llappearance/llavatarappearance.cpp | 1421 ++++++++++++++++++++- indra/llappearance/llavatarappearance.h | 207 ++- indra/llappearance/llavatarjoint.cpp | 261 ++++ indra/llappearance/llavatarjoint.h | 127 ++ indra/llappearance/llavatarjointmesh.cpp | 359 ++++++ indra/llappearance/llavatarjointmesh.h | 140 ++ indra/llappearance/llpolymesh.cpp | 1050 +++++++++++++++ indra/llappearance/llpolymesh.h | 369 ++++++ indra/llappearance/llpolymorph.cpp | 748 +++++++++++ indra/llappearance/llpolymorph.h | 182 +++ indra/llappearance/llpolyskeletaldistortion.cpp | 293 +++++ indra/llappearance/llpolyskeletaldistortion.h | 119 ++ indra/newview/CMakeLists.txt | 4 - indra/newview/llagentcamera.cpp | 10 +- indra/newview/llfloaterbvhpreview.cpp | 4 +- indra/newview/llfloaterimagepreview.cpp | 8 +- indra/newview/llhudeffectlookat.cpp | 2 +- indra/newview/llpolymesh.cpp | 1297 ------------------- indra/newview/llpolymesh.h | 438 ------- indra/newview/llpolymorph.h | 6 +- indra/newview/llspatialpartition.cpp | 2 +- indra/newview/llstartup.cpp | 3 + indra/newview/llviewerjoint.cpp | 121 +- indra/newview/llviewerjoint.h | 20 +- indra/newview/llviewerjointmesh.cpp | 283 +---- indra/newview/llviewerjointmesh.h | 86 +- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/llvoavatar.cpp | 1548 +++-------------------- indra/newview/llvoavatar.h | 172 +-- indra/newview/llvoavatarself.cpp | 6 +- indra/newview/llvoavatarself.h | 2 +- 32 files changed, 5466 insertions(+), 3834 deletions(-) create mode 100644 indra/llappearance/llavatarjoint.cpp create mode 100644 indra/llappearance/llavatarjoint.h create mode 100755 indra/llappearance/llavatarjointmesh.cpp create mode 100755 indra/llappearance/llavatarjointmesh.h create mode 100644 indra/llappearance/llpolymesh.cpp create mode 100644 indra/llappearance/llpolymesh.h create mode 100644 indra/llappearance/llpolymorph.cpp create mode 100644 indra/llappearance/llpolymorph.h create mode 100644 indra/llappearance/llpolyskeletaldistortion.cpp create mode 100644 indra/llappearance/llpolyskeletaldistortion.h delete mode 100644 indra/newview/llpolymesh.cpp delete mode 100644 indra/newview/llpolymesh.h diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 41da898457..c5a855a505 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -42,9 +42,14 @@ include_directories( set(llappearance_SOURCE_FILES llavatarappearance.cpp + llavatarjoint.cpp + llavatarjointmesh.cpp lldriverparam.cpp llinventoryicon.cpp lllocaltextureobject.cpp + llpolyskeletaldistortion.cpp + llpolymesh.cpp + llpolymorph.cpp lltexglobalcolor.cpp lltexlayer.cpp lltexlayerparams.cpp @@ -60,10 +65,15 @@ set(llappearance_HEADER_FILES CMakeLists.txt llavatarappearance.h + llavatarjoint.h + llavatarjointmesh.h lldriverparam.h llinventoryicon.h lljointpickname.h lllocaltextureobject.h + llpolyskeletaldistortion.h + llpolymesh.h + llpolymorph.h lltexglobalcolor.h lltexlayer.h lltexlayerparams.h diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2c03f8ba02..406e6153e0 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -29,19 +29,128 @@ #include "llavatarappearance.h" #include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" #include "imageids.h" +#include "lldir.h" #include "lldeleteutils.h" +#include "llpolymorph.h" +#include "llpolymesh.h" +#include "llpolyskeletaldistortion.h" #include "lltexglobalcolor.h" #include "llwearabledata.h" +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const std::string AVATAR_DEFAULT_CHAR = "avatar"; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); +/********************************************************************************* + ** ** + ** Begin private LLAvatarAppearance Support classes + ** + **/ + +//------------------------------------------------------------------------ +// LLAvatarBoneInfo +// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. +//------------------------------------------------------------------------ +class LLAvatarBoneInfo +{ + friend class LLAvatarAppearance; + friend class LLAvatarSkeletonInfo; +public: + LLAvatarBoneInfo() : mIsJoint(FALSE) {} + ~LLAvatarBoneInfo() + { + std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + +private: + std::string mName; + BOOL mIsJoint; + LLVector3 mPos; + LLVector3 mRot; + LLVector3 mScale; + LLVector3 mPivot; + typedef std::vector child_list_t; + child_list_t mChildList; +}; + +//------------------------------------------------------------------------ +// LLAvatarSkeletonInfo +// Overall avatar skeleton +//------------------------------------------------------------------------ +class LLAvatarSkeletonInfo +{ + friend class LLAvatarAppearance; +public: + LLAvatarSkeletonInfo() : + mNumBones(0), mNumCollisionVolumes(0) {} + ~LLAvatarSkeletonInfo() + { + std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + S32 getNumBones() const { return mNumBones; } + S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + +private: + S32 mNumBones; + S32 mNumCollisionVolumes; + typedef std::vector bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLAvatarXmlInfo +//----------------------------------------------------------------------------- + +LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo() + : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) +{ +} + +LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() +{ + std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); + deleteAndClear(mTexSkinColorInfo); + deleteAndClear(mTexHairColorInfo); + deleteAndClear(mTexEyeColorInfo); + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); + std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); +} + + +/** + ** + ** End LLAvatarAppearance Support classes + ** ** + *********************************************************************************/ + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +LLXmlTree LLAvatarAppearance::sXMLTree; +LLXmlTree LLAvatarAppearance::sSkeletonXMLTree; +LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL; +LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL; + + LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : LLCharacter(), mIsDummy(FALSE), mTexSkinColor( NULL ), mTexHairColor( NULL ), mTexEyeColor( NULL ), + mPelvisToFoot(0.f), + mHeadOffset(), + mWearableData(wearable_data) { llassert(mWearableData); @@ -55,30 +164,824 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mBakedTextureDatas[i].mMaskTexName = 0; mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); } + + mIsBuilt = FALSE; + + mNumJoints = 0; + mSkeleton = NULL; + + mNumCollisionVolumes = 0; + mCollisionVolumes = NULL; + + mRoot = new LLAvatarJoint(); + +} + +// virtual +LLAvatarAppearance::~LLAvatarAppearance() +{ + deleteAndClear(mTexSkinColor); + deleteAndClear(mTexHairColor); + deleteAndClear(mTexEyeColor); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); + mBakedTextureDatas[i].mMeshes.clear(); + + for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); + iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) + { + LLMaskedMorph* masked_morph = (*iter2); + delete masked_morph; + } + } + + mRoot->removeAllChildren(); + mJointMap.clear(); + + deleteAndClearArray(mSkeleton); + deleteAndClearArray(mCollisionVolumes); + + mNumJoints = 0; + + deleteAndClear(mTexSkinColor); + deleteAndClear(mTexHairColor); + deleteAndClear(mTexEyeColor); + + std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); + mMeshes.clear(); + + for (std::vector::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); + ++jointIter) + { + LLAvatarJoint* joint = (LLAvatarJoint *) *jointIter; + std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); + joint->mMeshParts.clear(); + } + std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); + mMeshLOD.clear(); +} + +//static +void LLAvatarAppearance::initClass() +{ + std::string xmlFile; + + xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; + BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); + if (!success) + { + llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl; + } + + // now sanity check xml file + LLXmlTreeNode* root = sXMLTree.getRoot(); + if (!root) + { + llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; + return; + } + + //------------------------------------------------------------------------- + // (root) + //------------------------------------------------------------------------- + if( !root->hasName( "linden_avatar" ) ) + { + llerrs << "Invalid avatar file header: " << xmlFile << llendl; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + { + llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl; + } + + S32 wearable_def_version = 1; + static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); + root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); + LLWearable::setCurrentDefinitionVersion( wearable_def_version ); + + std::string mesh_file_name; + + LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); + if (!skeleton_node) + { + llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl; + return; + } + + std::string skeleton_file_name; + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) + { + llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl; + } + + std::string skeleton_path; + skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); + if (!parseSkeletonFile(skeleton_path)) + { + llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; + } + + // Process XML data + + // avatar_skeleton.xml + if (sAvatarSkeletonInfo) + { //this can happen if a login attempt failed + delete sAvatarSkeletonInfo; + } + sAvatarSkeletonInfo = new LLAvatarSkeletonInfo; + if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) + { + llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; + } + // parse avatar_lad.xml + if (sAvatarXmlInfo) + { //this can happen if a login attempt failed + deleteAndClear(sAvatarXmlInfo); + } + sAvatarXmlInfo = new LLAvatarXmlInfo; + if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlColorNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } + if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) + { + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; + } +} + +using namespace LLAvatarAppearanceDefines; + +//------------------------------------------------------------------------ +// The viewer can only suggest a good size for the agent, +// the simulator will keep it inside a reasonable range. +void LLAvatarAppearance::computeBodySize() +{ + LLVector3 pelvis_scale = mPelvisp->getScale(); + + // some of the joints have not been cached + LLVector3 skull = mSkullp->getPosition(); + LLVector3 skull_scale = mSkullp->getScale(); + + LLVector3 neck = mNeckp->getPosition(); + LLVector3 neck_scale = mNeckp->getScale(); + + LLVector3 chest = mChestp->getPosition(); + LLVector3 chest_scale = mChestp->getScale(); + + // the rest of the joints have been cached + LLVector3 head = mHeadp->getPosition(); + LLVector3 head_scale = mHeadp->getScale(); + + LLVector3 torso = mTorsop->getPosition(); + LLVector3 torso_scale = mTorsop->getScale(); + + LLVector3 hip = mHipLeftp->getPosition(); + LLVector3 hip_scale = mHipLeftp->getScale(); + + LLVector3 knee = mKneeLeftp->getPosition(); + LLVector3 knee_scale = mKneeLeftp->getScale(); + + LLVector3 ankle = mAnkleLeftp->getPosition(); + LLVector3 ankle_scale = mAnkleLeftp->getScale(); + + LLVector3 foot = mFootLeftp->getPosition(); + + mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - + knee.mV[VZ] * hip_scale.mV[VZ] - + ankle.mV[VZ] * knee_scale.mV[VZ] - + foot.mV[VZ] * ankle_scale.mV[VZ]; + + LLVector3 new_body_size; + new_body_size.mV[VZ] = mPelvisToFoot + + // the sqrt(2) correction below is an approximate + // correction to get to the top of the head + F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + + head.mV[VZ] * neck_scale.mV[VZ] + + neck.mV[VZ] * chest_scale.mV[VZ] + + chest.mV[VZ] * torso_scale.mV[VZ] + + torso.mV[VZ] * pelvis_scale.mV[VZ]; + + // TODO -- measure the real depth and width + new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; + new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + + if (new_body_size != mBodySize) + { + mBodySize = new_body_size; + bodySizeChanged(); + } +} + +//----------------------------------------------------------------------------- +// parseSkeletonFile() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename) +{ + LLMemType mt(LLMemType::MTYPE_AVATAR); + + //------------------------------------------------------------------------- + // parse the file + //------------------------------------------------------------------------- + BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); + + if (!parsesuccess) + { + llerrs << "Can't parse skeleton file: " << filename << llendl; + return FALSE; + } + + // now sanity check xml file + LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); + if (!root) + { + llerrs << "No root node found in avatar skeleton file: " << filename << llendl; + return FALSE; + } + + if( !root->hasName( "linden_skeleton" ) ) + { + llerrs << "Invalid avatar skeleton file header: " << filename << llendl; + return FALSE; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) + { + llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; + return FALSE; + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// setupBone() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) +{ + LLMemType mt(LLMemType::MTYPE_AVATAR); + + LLJoint* joint = NULL; + + if (info->mIsJoint) + { + joint = getCharacterJoint(joint_num); + if (!joint) + { + llwarns << "Too many bones" << llendl; + return FALSE; + } + joint->setName( info->mName ); + } + else // collision volume + { + if (volume_num >= (S32)mNumCollisionVolumes) + { + llwarns << "Too many bones" << llendl; + return FALSE; + } + joint = (&mCollisionVolumes[volume_num]); + joint->setName( info->mName ); + } + + // add to parent + if (parent) + { + parent->addChild( joint ); + } + + joint->setPosition(info->mPos); + joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], + info->mRot.mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info->mScale); + + joint->setDefaultFromCurrentXform(); + + if (info->mIsJoint) + { + joint->setSkinOffset( info->mPivot ); + joint_num++; + } + else // collision volume + { + volume_num++; + } + + // setup children + LLAvatarBoneInfo::child_list_t::const_iterator iter; + for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) + { + LLAvatarBoneInfo *child_info = *iter; + if (!setupBone(child_info, joint, volume_num, joint_num)) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// buildSkeleton() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) +{ + LLMemType mt(LLMemType::MTYPE_AVATAR); + + //------------------------------------------------------------------------- + // allocate joints + //------------------------------------------------------------------------- + if (!allocateCharacterJoints(info->mNumBones)) + { + llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; + return FALSE; + } + + //------------------------------------------------------------------------- + // allocate volumes + //------------------------------------------------------------------------- + if (info->mNumCollisionVolumes) + { + if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) + { + llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; + return FALSE; + } + } + + S32 current_joint_num = 0; + S32 current_volume_num = 0; + LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; + for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + { + LLAvatarBoneInfo *info = *iter; + if (!setupBone(info, NULL, current_volume_num, current_joint_num)) + { + llerrs << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::buildCharacter() +// Deferred initialization and rebuild of the avatar. +//----------------------------------------------------------------------------- +void LLAvatarAppearance::buildCharacter() +{ + LLMemType mt(LLMemType::MTYPE_AVATAR); + + //------------------------------------------------------------------------- + // remove all references to our existing skeleton + // so we can rebuild it + //------------------------------------------------------------------------- + flushAllMotions(); + + //------------------------------------------------------------------------- + // remove all of mRoot's children + //------------------------------------------------------------------------- + mRoot->removeAllChildren(); + mJointMap.clear(); + mIsBuilt = FALSE; + + //------------------------------------------------------------------------- + // (re)load our skeleton and meshes + //------------------------------------------------------------------------- + LLTimer timer; + + BOOL status = loadAvatar(); + stop_glerror(); + +// gPrintMessagesThisFrame = TRUE; + lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; + + if (!status) + { + if (isSelf()) + { + llerrs << "Unable to load user's avatar" << llendl; + } + else + { + llwarns << "Unable to load other's avatar" << llendl; + } + return; + } + + //------------------------------------------------------------------------- + // initialize "well known" joint pointers + //------------------------------------------------------------------------- + mPelvisp = mRoot->findJoint("mPelvis"); + mTorsop = mRoot->findJoint("mTorso"); + mChestp = mRoot->findJoint("mChest"); + mNeckp = mRoot->findJoint("mNeck"); + mHeadp = mRoot->findJoint("mHead"); + mSkullp = mRoot->findJoint("mSkull"); + mHipLeftp = mRoot->findJoint("mHipLeft"); + mHipRightp = mRoot->findJoint("mHipRight"); + mKneeLeftp = mRoot->findJoint("mKneeLeft"); + mKneeRightp = mRoot->findJoint("mKneeRight"); + mAnkleLeftp = mRoot->findJoint("mAnkleLeft"); + mAnkleRightp = mRoot->findJoint("mAnkleRight"); + mFootLeftp = mRoot->findJoint("mFootLeft"); + mFootRightp = mRoot->findJoint("mFootRight"); + mWristLeftp = mRoot->findJoint("mWristLeft"); + mWristRightp = mRoot->findJoint("mWristRight"); + mEyeLeftp = mRoot->findJoint("mEyeLeft"); + mEyeRightp = mRoot->findJoint("mEyeRight"); + + //------------------------------------------------------------------------- + // Make sure "well known" pointers exist + //------------------------------------------------------------------------- + if (!(mPelvisp && + mTorsop && + mChestp && + mNeckp && + mHeadp && + mSkullp && + mHipLeftp && + mHipRightp && + mKneeLeftp && + mKneeRightp && + mAnkleLeftp && + mAnkleRightp && + mFootLeftp && + mFootRightp && + mWristLeftp && + mWristRightp && + mEyeLeftp && + mEyeRightp)) + { + llerrs << "Failed to create avatar." << llendl; + return; + } + + //------------------------------------------------------------------------- + // initialize the pelvis + //------------------------------------------------------------------------- + mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); + + mIsBuilt = TRUE; + stop_glerror(); + +} + +BOOL LLAvatarAppearance::loadAvatar() +{ +// LLFastTimer t(FTM_LOAD_AVATAR); + + // avatar_skeleton.xml + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + llwarns << "avatar file: buildSkeleton() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : + if( !loadSkeletonNode() ) + { + llwarns << "avatar file: loadNodeSkeleton() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : + if( !loadMeshNodes() ) + { + llwarns << "avatar file: loadNodeMesh() failed" << llendl; + return FALSE; + } + + // avatar_lad.xml : + if( sAvatarXmlInfo->mTexSkinColorInfo ) + { + mTexSkinColor = new LLTexGlobalColor( this ); + if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) + { + llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << " name=\"skin_color\" not found" << llendl; + return FALSE; + } + if( sAvatarXmlInfo->mTexHairColorInfo ) + { + mTexHairColor = new LLTexGlobalColor( this ); + if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) + { + llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << " name=\"hair_color\" not found" << llendl; + return FALSE; + } + if( sAvatarXmlInfo->mTexEyeColorInfo ) + { + mTexEyeColor = new LLTexGlobalColor( this ); + if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) + { + llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; + return FALSE; + } + } + else + { + llwarns << " name=\"eye_color\" not found" << llendl; + return FALSE; + } + + // avatar_lad.xml : + if (sAvatarXmlInfo->mLayerInfoList.empty()) + { + llwarns << "avatar file: missing node" << llendl; + return FALSE; + } + + if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) + { + llwarns << "avatar file: missing node" << llendl; + return FALSE; + } + + // avatar_lad.xml : + for (LLAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin(); + iter != sAvatarXmlInfo->mMorphMaskInfoList.end(); + ++iter) + { + LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter; + + EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); + if (baked != BAKED_NUM_INDICES) + { + LLVisualParam* morph_param; + const std::string *name = &info->mName; + morph_param = getVisualParam(name->c_str()); + if (morph_param) + { + BOOL invert = info->mInvert; + addMaskedMorph(baked, morph_param, invert, info->mLayer); + } + } + + } + + loadLayersets(); + + // avatar_lad.xml : + for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); + ++iter) + { + LLDriverParamInfo *info = *iter; + LLDriverParam* driver_param = new LLDriverParam( this ); + if (driver_param->setInfo(info)) + { + addVisualParam( driver_param ); + LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; + if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) + { + llwarns << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << llendl; + continue; + } + } + else + { + delete driver_param; + llwarns << "avatar file: driver_param->parseData() failed" << llendl; + return FALSE; + } + } + + + return TRUE; +} + +//----------------------------------------------------------------------------- +// loadSkeletonNode(): loads node from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadSkeletonNode () +{ + mRoot->addChild( &mSkeleton[0] ); + + mRoot->addChild(mMeshLOD[MESH_ID_HEAD]); + mRoot->addChild(mMeshLOD[MESH_ID_EYELASH]); + mRoot->addChild(mMeshLOD[MESH_ID_UPPER_BODY]); + mRoot->addChild(mMeshLOD[MESH_ID_LOWER_BODY]); + mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]); + mRoot->addChild(mMeshLOD[MESH_ID_HEAD]); + + LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull"); + if (skull) + { + skull->addChild(mMeshLOD[MESH_ID_HAIR] ); + } + + LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft"); + if (eyeL) + { + eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); + } + + LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight"); + if (eyeR) + { + eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); + } + + // SKELETAL DISTORTIONS + { + LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; + LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); + if (!param->setInfo(info)) + { + delete param; + return FALSE; + } + else + { + addVisualParam(param); + } + } + } + + + return TRUE; } -// virtual -LLAvatarAppearance::~LLAvatarAppearance() +//----------------------------------------------------------------------------- +// loadMeshNodes(): loads nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadMeshNodes() { - deleteAndClear(mTexSkinColor); - deleteAndClear(mTexHairColor); - deleteAndClear(mTexEyeColor); - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + for (LLAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); + meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); + ++meshinfo_iter) { - deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); - mBakedTextureDatas[i].mMeshes.clear(); + const LLAvatarXmlInfo::LLAvatarMeshInfo *info = *meshinfo_iter; + const std::string &type = info->mType; + S32 lod = info->mLOD; - for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); - iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) + LLAvatarJointMesh* mesh = NULL; + U8 mesh_id = 0; + BOOL found_mesh_id = FALSE; + + /* if (type == "hairMesh") + switch(lod) + case 0: + mesh = &mHairMesh0; */ + for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); + mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); + ++mesh_iter) { - LLMaskedMorph* masked_morph = (*iter2); - delete masked_morph; + const EMeshIndex mesh_index = mesh_iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second; + if (type.compare(mesh_dict->mName) == 0) + { + mesh_id = mesh_index; + found_mesh_id = TRUE; + break; + } + } + + if (found_mesh_id) + { + if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) + { + mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; + } + else + { + llwarns << "Avatar file: has invalid lod setting " << lod << llendl; + return FALSE; + } + } + else + { + llwarns << "Ignoring unrecognized mesh type: " << type << llendl; + return FALSE; + } + + // llinfos << "Parsing mesh data for " << type << "..." << llendl; + + // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. + // Do not touch!!! + mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f ); + + LLPolyMesh *poly_mesh = NULL; + + if (!info->mReferenceMeshName.empty()) + { + polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mMeshes.end()) + { + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); + poly_mesh->setAvatar(this); + } + else + { + // This should never happen + LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; + } + } + else + { + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); + poly_mesh->setAvatar(this); + } + + if( !poly_mesh ) + { + llwarns << "Failed to load mesh of type " << type << llendl; + return FALSE; + } + + // Multimap insert + mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); + + mesh->setMesh( poly_mesh ); + mesh->setLOD( info->mMinPixelArea ); + + for (LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); + xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); + ++xmlinfo_iter) + { + const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); + LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); + if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair->first)) + { + delete param; + return FALSE; + } + else + { + if (info_pair->second) + { + addSharedVisualParam(param); + } + else + { + addVisualParam(param); + } + } } } + + return TRUE; } -using namespace LLAvatarAppearanceDefines; +//----------------------------------------------------------------------------- +// loadLayerSets() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::loadLayersets() +{ + BOOL success = TRUE; + for (LLAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin(); + layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); + ++layerset_iter) + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSetInfo *layerset_info = *layerset_iter; + layerset_info->createVisualParams(this); + } + return success; +} + + // virtual BOOL LLAvatarAppearance::isValid() const @@ -273,4 +1176,494 @@ BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const return FALSE; } +//----------------------------------------------------------------------------- +// allocateCollisionVolumes() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) +{ + deleteAndClearArray(mCollisionVolumes); + mNumCollisionVolumes = 0; + + mCollisionVolumes = new LLAvatarJointCollisionVolume[num]; + if (!mCollisionVolumes) + { + return FALSE; + } + + mNumCollisionVolumes = num; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarBoneInfo::parseXml() +//----------------------------------------------------------------------------- +BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +{ + if (node->hasName("bone")) + { + mIsJoint = TRUE; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + llwarns << "Bone without name" << llendl; + return FALSE; + } + } + else if (node->hasName("collision_volume")) + { + mIsJoint = FALSE; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + mName = "Collision Volume"; + } + } + else + { + llwarns << "Invalid node " << node->getName() << llendl; + return FALSE; + } + + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + if (!node->getFastAttributeVector3(pos_string, mPos)) + { + llwarns << "Bone without position" << llendl; + return FALSE; + } + + static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); + if (!node->getFastAttributeVector3(rot_string, mRot)) + { + llwarns << "Bone without rotation" << llendl; + return FALSE; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!node->getFastAttributeVector3(scale_string, mScale)) + { + llwarns << "Bone without scale" << llendl; + return FALSE; + } + + if (mIsJoint) + { + static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); + if (!node->getFastAttributeVector3(pivot_string, mPivot)) + { + llwarns << "Bone without pivot" << llendl; + return FALSE; + } + } + + // parse children + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo; + if (!child_info->parseXml(child)) + { + delete child_info; + return FALSE; + } + mChildList.push_back(child_info); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarSkeletonInfo::parseXml() +//----------------------------------------------------------------------------- +BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +{ + static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); + if (!node->getFastAttributeS32(num_bones_string, mNumBones)) + { + llwarns << "Couldn't find number of bones." << llendl; + return FALSE; + } + + static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); + node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); + + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *info = new LLAvatarBoneInfo; + if (!info->parseXml(child)) + { + delete info; + llwarns << "Error parsing bone in skeleton file" << llendl; + return FALSE; + } + mBoneInfoList.push_back(info); + } + return TRUE; +} + + +//----------------------------------------------------------------------------- +// parseXmlSkeletonNode(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +{ + LLXmlTreeNode* node = root->getChildByName( "skeleton" ); + if( !node ) + { + llwarns << "avatar file: missing " << llendl; + return FALSE; + } + + LLXmlTreeNode* child; + + // SKELETON DISTORTIONS + for (child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_skeleton")) + { + if (child->getChildByName("param_morph")) + { + llwarns << "Can't specify morph param in skeleton definition." << llendl; + } + else + { + llwarns << "Unknown param type." << llendl; + } + continue; + } + + LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; + if (!info->parseXml(child)) + { + delete info; + return FALSE; + } + + mSkeletalDistortionInfoList.push_back(info); + } + + // ATTACHMENT POINTS + for (child = node->getChildByName( "attachment_point" ); + child; + child = node->getNextNamedChild()) + { + LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!child->getFastAttributeString(name_string, info->mName)) + { + llwarns << "No name supplied for attachment point." << llendl; + delete info; + continue; + } + + static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); + if (!child->getFastAttributeString(joint_string, info->mJointName)) + { + llwarns << "No bone declared in attachment point " << info->mName << llendl; + delete info; + continue; + } + + static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); + if (child->getFastAttributeVector3(position_string, info->mPosition)) + { + info->mHasPosition = TRUE; + } + + static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); + if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) + { + info->mHasRotation = TRUE; + } + static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); + if (child->getFastAttributeS32(group_string, info->mGroup)) + { + if (info->mGroup == -1) + info->mGroup = -1111; // -1 = none parsed, < -1 = bad value + } + + static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); + if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) + { + llwarns << "No id supplied for attachment point " << info->mName << llendl; + delete info; + continue; + } + + static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); + child->getFastAttributeS32(slot_string, info->mPieMenuSlice); + + static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); + child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); + + static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); + child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); + + mAttachmentInfoList.push_back(info); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlMeshNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); + node; + node = root->getNextNamedChild()) + { + LLAvatarMeshInfo *info = new LLAvatarMeshInfo; + + // attribute: type + static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); + if( !node->getFastAttributeString( type_string, info->mType ) ) + { + llwarns << "Avatar file: is missing type attribute. Ignoring element. " << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); + if (!node->getFastAttributeS32( lod_string, info->mLOD )) + { + llwarns << "Avatar file: is missing lod attribute. Ignoring element. " << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) + { + llwarns << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << llendl; + delete info; + return FALSE; // Ignore this element + } + + static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); + node->getFastAttributeString( reference_string, info->mReferenceMeshName ); + + // attribute: min_pixel_area + static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); + static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); + if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) + { + F32 min_pixel_area = 0.1f; + if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) + { + // this is square root of pixel area (sensible to use linear space in defining lods) + min_pixel_area = min_pixel_area * min_pixel_area; + } + info->mMinPixelArea = min_pixel_area; + } + + // Parse visual params for this node only if we haven't already + for (LLXmlTreeNode* child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_morph")) + { + if (child->getChildByName("param_skeleton")) + { + llwarns << "Can't specify skeleton param in a mesh definition." << llendl; + } + else + { + llwarns << "Unknown param type." << llendl; + } + continue; + } + + LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); + if (!morphinfo->parseXml(child)) + { + delete morphinfo; + delete info; + return -1; + } + BOOL shared = FALSE; + static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); + child->getFastAttributeBOOL(shared_string, shared); + + info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); + } + + mMeshInfoList.push_back(info); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlColorNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); + color_node; + color_node = root->getNextNamedChild()) + { + std::string global_color_name; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (color_node->getFastAttributeString( name_string, global_color_name ) ) + { + if( global_color_name == "skin_color" ) + { + if (mTexSkinColorInfo) + { + llwarns << "avatar file: multiple instances of skin_color" << llendl; + return FALSE; + } + mTexSkinColorInfo = new LLTexGlobalColorInfo; + if( !mTexSkinColorInfo->parseXml( color_node ) ) + { + deleteAndClear(mTexSkinColorInfo); + llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl; + return FALSE; + } + } + else if( global_color_name == "hair_color" ) + { + if (mTexHairColorInfo) + { + llwarns << "avatar file: multiple instances of hair_color" << llendl; + return FALSE; + } + mTexHairColorInfo = new LLTexGlobalColorInfo; + if( !mTexHairColorInfo->parseXml( color_node ) ) + { + deleteAndClear(mTexHairColorInfo); + llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl; + return FALSE; + } + } + else if( global_color_name == "eye_color" ) + { + if (mTexEyeColorInfo) + { + llwarns << "avatar file: multiple instances of eye_color" << llendl; + return FALSE; + } + mTexEyeColorInfo = new LLTexGlobalColorInfo; + if( !mTexEyeColorInfo->parseXml( color_node ) ) + { + llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl; + return FALSE; + } + } + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlLayerNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); + layer_node; + layer_node = root->getNextNamedChild()) + { + LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); + if( layer_info->parseXml( layer_node ) ) + { + mLayerInfoList.push_back(layer_info); + } + else + { + delete layer_info; + llwarns << "avatar file: layer_set->parseXml() failed" << llendl; + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); + if( driver ) + { + for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); + grand_child; + grand_child = driver->getNextNamedChild()) + { + if( grand_child->getChildByName( "param_driver" ) ) + { + LLDriverParamInfo* driver_info = new LLDriverParamInfo(); + if( driver_info->parseXml( grand_child ) ) + { + mDriverInfoList.push_back(driver_info); + } + else + { + delete driver_info; + llwarns << "avatar file: driver_param->parseXml() failed" << llendl; + return FALSE; + } + } + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); + if( !masks ) + { + return FALSE; + } + + for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); + grand_child; + grand_child = masks->getNextNamedChild()) + { + LLAvatarMorphInfo* info = new LLAvatarMorphInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); + if (!grand_child->getFastAttributeString(name_string, info->mName)) + { + llwarns << "No name supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); + if (!grand_child->getFastAttributeString(region_string, info->mRegion)) + { + llwarns << "No region supplied for morph mask." << llendl; + delete info; + continue; + } + + static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); + if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) + { + llwarns << "No layer supplied for morph mask." << llendl; + delete info; + continue; + } + + // optional parameter. don't throw a warning if not present. + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + grand_child->getFastAttributeBOOL(invert_string, info->mInvert); + + mMorphMaskInfoList.push_back(info); + } + + return TRUE; +} + + diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index b2ab6b069f..38a54d904d 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -30,11 +30,17 @@ #include "llcharacter.h" //#include "llframetimer.h" #include "llavatarappearancedefines.h" -#include "lljoint.h" +#include "llavatarjoint.h" +#include "lldriverparam.h" +#include "lltexlayer.h" +#include "llviewervisualparam.h" +#include "llxmltree.h" class LLTexLayerSet; class LLTexGlobalColor; class LLWearableData; +class LLAvatarBoneInfo; +class LLAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLAvatarAppearance @@ -45,6 +51,9 @@ class LLAvatarAppearance : public LLCharacter { LOG_CLASS(LLAvatarAppearance); +protected: + struct LLAvatarXmlInfo; + /******************************************************************************** ** ** ** INITIALIZATION @@ -57,6 +66,12 @@ public: LLAvatarAppearance(LLWearableData* wearable_data); virtual ~LLAvatarAppearance(); + static void initClass(); // initializes static members + virtual BOOL loadSkeletonNode(); + virtual BOOL loadMeshNodes(); + virtual BOOL loadLayersets(); + + /** Initialization ** ** *******************************************************************************/ @@ -69,16 +84,94 @@ public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent virtual BOOL isValid() const; virtual BOOL isUsingBakedTextures() const = 0; + + bool isBuilt() const { return mIsBuilt; } + /** State ** ** *******************************************************************************/ +/******************************************************************************** + ** ** + ** SKELETON + **/ + +public: + F32 getPelvisToFoot() const { return mPelvisToFoot; } + + LLVector3 mHeadOffset; // current head position + LLAvatarJoint *mRoot; + + typedef std::map joint_map_t; + joint_map_t mJointMap; + +protected: + static BOOL parseSkeletonFile(const std::string& filename); + virtual void buildCharacter(); + virtual BOOL loadAvatar(); + virtual void bodySizeChanged() = 0; + void computeBodySize(); + + BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL buildSkeleton(const LLAvatarSkeletonInfo *info); +protected: + BOOL mIsBuilt; // state of deferred character building + S32 mNumJoints; + LLJoint* mSkeleton; + + //-------------------------------------------------------------------- + // Pelvis height adjustment members. + //-------------------------------------------------------------------- +public: + LLVector3 mBodySize; +protected: + F32 mPelvisToFoot; + + //-------------------------------------------------------------------- + // Cached pointers to well known joints + //-------------------------------------------------------------------- +public: + LLJoint* mPelvisp; + LLJoint* mTorsop; + LLJoint* mChestp; + LLJoint* mNeckp; + LLJoint* mHeadp; + LLJoint* mSkullp; + LLJoint* mEyeLeftp; + LLJoint* mEyeRightp; + LLJoint* mHipLeftp; + LLJoint* mHipRightp; + LLJoint* mKneeLeftp; + LLJoint* mKneeRightp; + LLJoint* mAnkleLeftp; + LLJoint* mAnkleRightp; + LLJoint* mFootLeftp; + LLJoint* mFootRightp; + LLJoint* mWristLeftp; + LLJoint* mWristRightp; + + //-------------------------------------------------------------------- + // XML parse tree + //-------------------------------------------------------------------- +protected: + static LLXmlTree sXMLTree; // avatar config file + static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + + static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLAvatarXmlInfo* sAvatarXmlInfo; + + +/** Skeleton + ** ** + *******************************************************************************/ + /******************************************************************************** ** ** ** RENDERING **/ +public: BOOL mIsDummy; // for special views //-------------------------------------------------------------------- @@ -109,6 +202,11 @@ public: protected: virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority +protected: + typedef std::multimap polymesh_map_t; + polymesh_map_t mMeshes; + std::vector mMeshLOD; + /** Meshes ** ** *******************************************************************************/ @@ -182,12 +280,115 @@ protected: typedef std::vector bakedtexturedata_vec_t; bakedtexturedata_vec_t mBakedTextureDatas; +/******************************************************************************** + ** ** + ** PHYSICS + **/ + + //-------------------------------------------------------------------- + // Collision volumes + //-------------------------------------------------------------------- +public: + S32 mNumCollisionVolumes; + LLAvatarJointCollisionVolume* mCollisionVolumes; +protected: + BOOL allocateCollisionVolumes(U32 num); + +/** Physics + ** ** + *******************************************************************************/ /******************************************************************************** ** ** ** SUPPORT CLASSES **/ + struct LLAvatarXmlInfo + { + LLAvatarXmlInfo(); + ~LLAvatarXmlInfo(); + + BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); + BOOL parseXmlMeshNodes(LLXmlTreeNode* root); + BOOL parseXmlColorNodes(LLXmlTreeNode* root); + BOOL parseXmlLayerNodes(LLXmlTreeNode* root); + BOOL parseXmlDriverNodes(LLXmlTreeNode* root); + BOOL parseXmlMorphNodes(LLXmlTreeNode* root); + + struct LLAvatarMeshInfo + { + typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here + typedef std::vector morph_info_list_t; + + LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} + ~LLAvatarMeshInfo() + { + morph_info_list_t::iterator iter; + for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) + { + delete iter->first; + } + mPolyMorphTargetInfoList.clear(); + } + + std::string mType; + S32 mLOD; + std::string mMeshFileName; + std::string mReferenceMeshName; + F32 mMinPixelArea; + morph_info_list_t mPolyMorphTargetInfoList; + }; + typedef std::vector mesh_info_list_t; + mesh_info_list_t mMeshInfoList; + + typedef std::vector skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here + skeletal_distortion_info_list_t mSkeletalDistortionInfoList; + + struct LLAvatarAttachmentInfo + { + LLAvatarAttachmentInfo() + : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), + mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} + std::string mName; + std::string mJointName; + LLVector3 mPosition; + LLVector3 mRotationEuler; + S32 mGroup; + S32 mAttachmentID; + S32 mPieMenuSlice; + BOOL mVisibleFirstPerson; + BOOL mIsHUDAttachment; + BOOL mHasPosition; + BOOL mHasRotation; + }; + typedef std::vector attachment_info_list_t; + attachment_info_list_t mAttachmentInfoList; + + LLTexGlobalColorInfo *mTexSkinColorInfo; + LLTexGlobalColorInfo *mTexHairColorInfo; + LLTexGlobalColorInfo *mTexEyeColorInfo; + + typedef std::vector layer_info_list_t; + layer_info_list_t mLayerInfoList; + + typedef std::vector driver_info_list_t; + driver_info_list_t mDriverInfoList; + + struct LLAvatarMorphInfo + { + LLAvatarMorphInfo() + : mInvert(FALSE) {} + std::string mName; + std::string mRegion; + std::string mLayer; + BOOL mInvert; + }; + + typedef std::vector morph_info_list_t; + morph_info_list_t mMorphMaskInfoList; + }; + + class LLMaskedMorph { public: @@ -197,7 +398,9 @@ protected: BOOL mInvert; std::string mLayer; }; - +/** Support Classes + ** ** + *******************************************************************************/ }; #endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp new file mode 100644 index 0000000000..809a261633 --- /dev/null +++ b/indra/llappearance/llavatarjoint.cpp @@ -0,0 +1,261 @@ +/** + * @file llavatarjoint.cpp + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llavatarjoint.h" + +#include "llgl.h" +#include "llrender.h" +#include "llmath.h" +#include "llglheaders.h" +#include "llrendersphere.h" +#include "llavatarappearance.h" +//#include "pipeline.h" + +#define DEFAULT_LOD 0.0f + +const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +BOOL LLAvatarJoint::sDisableLOD = FALSE; + +//----------------------------------------------------------------------------- +// LLAvatarJoint() +// Class Constructor +//----------------------------------------------------------------------------- +LLAvatarJoint::LLAvatarJoint() + : LLJoint() +{ + init(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarJoint() +// Class Constructor +//----------------------------------------------------------------------------- +LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) + : LLJoint(name, parent) +{ + init(); +} + + +void LLAvatarJoint::init() +{ + mValid = FALSE; + mComponents = SC_JOINT | SC_BONE | SC_AXES; + mMinPixelArea = DEFAULT_LOD; + mPickName = PN_DEFAULT; + mVisible = TRUE; + mMeshID = 0; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJoint() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJoint::~LLAvatarJoint() +{ +} + + +//-------------------------------------------------------------------- +// setValid() +//-------------------------------------------------------------------- +void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) +{ + //---------------------------------------------------------------- + // set visibility for this joint + //---------------------------------------------------------------- + mValid = valid; + + //---------------------------------------------------------------- + // set visibility for children + //---------------------------------------------------------------- + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + joint->setValid(valid, TRUE); + } + } + +} + +//-------------------------------------------------------------------- +// isTransparent() +//-------------------------------------------------------------------- +BOOL LLAvatarJoint::isTransparent() +{ + return FALSE; +} + +//-------------------------------------------------------------------- +// setSkeletonComponents() +//-------------------------------------------------------------------- +void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive ) +{ + mComponents = comp; + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + joint->setSkeletonComponents(comp, recursive); + } + } +} + +void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive) +{ + mVisible = visible; + + if (recursive) + { + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + joint->setVisible(visible, recursive); + } + } +} + + +void LLAvatarJoint::setMeshesToChildren() +{ + removeAllChildren(); + for (std::vector::iterator iter = mMeshParts.begin(); + iter != mMeshParts.end(); iter++) + { + addChild((LLAvatarJoint*) *iter); + } +} +//----------------------------------------------------------------------------- +// LLAvatarJointCollisionVolume() +//----------------------------------------------------------------------------- + +LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() +{ + mUpdateXform = FALSE; +} + +LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent) : LLAvatarJoint(name, parent) +{ + +} + +LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) +{ + mUpdateXform = TRUE; + + LLVector3 result = offset; + result.scaleVec(getScale()); + result.rotVec(getWorldRotation()); + result += getWorldPosition(); + + return result; +} + +void LLAvatarJointCollisionVolume::renderCollision() +{ + updateWorldMatrix(); + + gGL.pushMatrix(); + gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); + + gGL.diffuseColor3f( 0.f, 0.f, 1.f ); + + gGL.begin(LLRender::LINES); + + LLVector3 v[] = + { + LLVector3(1,0,0), + LLVector3(-1,0,0), + LLVector3(0,1,0), + LLVector3(0,-1,0), + + LLVector3(0,0,-1), + LLVector3(0,0,1), + }; + + //sides + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[3].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[3].mV); + + + //top + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[4].mV); + + + //bottom + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[5].mV); + + gGL.end(); + + gGL.popMatrix(); +} + + +// End diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h new file mode 100644 index 0000000000..cbfc1b73ea --- /dev/null +++ b/indra/llappearance/llavatarjoint.h @@ -0,0 +1,127 @@ +/** + * @file llavatarjoint.h + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINT_H +#define LL_LLAVATARJOINT_H + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "lljoint.h" +#include "lljointpickname.h" + +class LLFace; +class LLAvatarJointMesh; + +//----------------------------------------------------------------------------- +// class LLViewerJoint +//----------------------------------------------------------------------------- +class LLAvatarJoint : + public LLJoint +{ +public: + LLAvatarJoint(); + LLAvatarJoint(const std::string &name, LLJoint *parent = NULL); + virtual ~LLAvatarJoint(); + + // Gets the validity of this joint + BOOL getValid() { return mValid; } + + // Sets the validity of this joint + virtual void setValid( BOOL valid, BOOL recursive=FALSE ); + + // Returns true if this object is transparent. + // This is used to determine in which order to draw objects. + virtual BOOL isTransparent(); + + // Returns true if this object should inherit scale modifiers from its immediate parent + virtual BOOL inheritScale() { return FALSE; } + + + enum Components + { + SC_BONE = 1, + SC_JOINT = 2, + SC_AXES = 4 + }; + + // Selects which skeleton components to draw + void setSkeletonComponents( U32 comp, BOOL recursive = TRUE ); + + // Returns which skeleton components are enables for drawing + U32 getSkeletonComponents() { return mComponents; } + + // Sets the level of detail for this node as a minimum + // pixel area threshold. If the current pixel area for this + // object is less than the specified threshold, the node is + // not traversed. In addition, if a value is specified (not + // default of 0.0), and the pixel area is larger than the + // specified minimum, the node is rendered, but no other siblings + // of this node under the same parent will be. + F32 getLOD() { return mMinPixelArea; } + void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } + + void setPickName(LLJointPickName name) { mPickName = name; } + LLJointPickName getPickName() { return mPickName; } + + void setVisible( BOOL visible, BOOL recursive ); + + // Takes meshes in mMeshParts and sets each one as a child joint + void setMeshesToChildren(); + +public: + static BOOL sDisableLOD; + std::vector mMeshParts; //LLViewerJointMesh* + void setMeshID( S32 id ) {mMeshID = id;} + +protected: + void init(); + + BOOL mValid; + U32 mComponents; + F32 mMinPixelArea; + LLJointPickName mPickName; + BOOL mVisible; + S32 mMeshID; +}; + +class LLAvatarJointCollisionVolume : public LLAvatarJoint +{ +public: + LLAvatarJointCollisionVolume(); + LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent = NULL); + virtual ~LLAvatarJointCollisionVolume() {}; + + virtual BOOL inheritScale() { return TRUE; } + + void renderCollision(); + + LLVector3 getVolumePos(LLVector3 &offset); +}; + +#endif // LL_LLAVATARJOINT_H + + diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp new file mode 100755 index 0000000000..92c213126a --- /dev/null +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -0,0 +1,359 @@ +/** + * @file LLAvatarJointMesh.cpp + * @brief Implementation of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" +#include "imageids.h" +#include "llfasttimer.h" +#include "llrender.h" + +#include "llavatarjointmesh.h" +#include "llavatarappearance.h" +//#include "llapr.h" +//#include "llbox.h" +//#include "lldrawable.h" +//#include "lldrawpoolavatar.h" +//#include "lldrawpoolbump.h" +//#include "lldynamictexture.h" +//#include "llface.h" +//#include "llgldbg.h" +//#include "llglheaders.h" +#include "lltexlayer.h" +//#include "llviewercamera.h" +//#include "llviewercontrol.h" +//#include "llviewertexturelist.h" +//#include "llsky.h" +//#include "pipeline.h" +//#include "llviewershadermgr.h" +#include "llmath.h" +#include "v4math.h" +#include "m3math.h" +#include "m4math.h" +#include "llmatrix4a.h" + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::LLSkinJoint +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::LLSkinJoint() +{ + mJoint = NULL; +} + +//----------------------------------------------------------------------------- +// ~LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::~LLSkinJoint() +{ + mJoint = NULL; +} + + +//----------------------------------------------------------------------------- +// LLSkinJoint::setupSkinJoint() +//----------------------------------------------------------------------------- +BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) +{ + // find the named joint + mJoint = joint; + if ( !mJoint ) + { + llinfos << "Can't find joint" << llendl; + } + + // compute the inverse root skin matrix + mRootToJointSkinOffset.clearVec(); + + LLVector3 rootSkinOffset; + while (joint) + { + rootSkinOffset += joint->getSkinOffset(); + joint = (LLAvatarJoint*)joint->getParent(); + } + + mRootToJointSkinOffset = -rootSkinOffset; + mRootToParentJointSkinOffset = mRootToJointSkinOffset; + mRootToParentJointSkinOffset += mJoint->getSkinOffset(); + + return TRUE; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +BOOL LLAvatarJointMesh::sPipelineRender = FALSE; +EAvatarRenderPass LLAvatarJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; +U32 LLAvatarJointMesh::sClothingMaskImageName = 0; +LLColor4 LLAvatarJointMesh::sClothingInnerColor; + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh() +//----------------------------------------------------------------------------- +LLAvatarJointMesh::LLAvatarJointMesh() + : + mTexture( NULL ), + mLayerSet( NULL ), + mTestImageName( 0 ), + mFaceIndexCount(0), + mIsTransparent(FALSE) +{ + + mColor[0] = 1.0f; + mColor[1] = 1.0f; + mColor[2] = 1.0f; + mColor[3] = 1.0f; + mShiny = 0.0f; + mCullBackFaces = TRUE; + + mMesh = NULL; + + mNumSkinJoints = 0; + mSkinJoints = NULL; + + mFace = NULL; + + mMeshID = 0; + mUpdateXform = FALSE; + + mValid = FALSE; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJointMesh() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJointMesh::~LLAvatarJointMesh() +{ + mMesh = NULL; + mTexture = NULL; + freeSkinData(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::allocateSkinData() +//----------------------------------------------------------------------------- +BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) +{ + mSkinJoints = new LLSkinJoint[ numSkinJoints ]; + mNumSkinJoints = numSkinJoints; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::freeSkinData() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::freeSkinData() +{ + mNumSkinJoints = 0; + delete [] mSkinJoints; + mSkinJoints = NULL; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) +{ + *red = mColor[0]; + *green = mColor[1]; + *blue = mColor[2]; + *alpha = mColor[3]; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) +{ + mColor[0] = red; + mColor[1] = green; + mColor[2] = blue; + mColor[3] = alpha; +} + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getTexture() +//-------------------------------------------------------------------- +//LLViewerTexture *LLAvatarJointMesh::getTexture() +//{ +// return mTexture; +//} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setTexture() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) +{ + mTexture = texture; + + // texture and dynamic_texture are mutually exclusive + if( texture ) + { + mLayerSet = NULL; + //texture->bindTexture(0); + //texture->setClamp(TRUE, TRUE); + } +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setLayerSet() +// Sets the shape texture (takes precedence over normal texture) +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) +{ + mLayerSet = layer_set; + + // texture and dynamic_texture are mutually exclusive + if( layer_set ) + { + mTexture = NULL; + } +} + + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getMesh() +//-------------------------------------------------------------------- +LLPolyMesh *LLAvatarJointMesh::getMesh() +{ + return mMesh; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::setMesh() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) +{ + // set the mesh pointer + mMesh = mesh; + + // release any existing skin joints + freeSkinData(); + + if ( mMesh == NULL ) + { + return; + } + + // acquire the transform from the mesh object + setPosition( mMesh->getPosition() ); + setRotation( mMesh->getRotation() ); + setScale( mMesh->getScale() ); + + // create skin joints if necessary + if ( mMesh->hasWeights() && !mMesh->isLOD()) + { + U32 numJointNames = mMesh->getNumJointNames(); + + allocateSkinData( numJointNames ); + std::string *jointNames = mMesh->getJointNames(); + + U32 jn; + for (jn = 0; jn < numJointNames; jn++) + { + //llinfos << "Setting up joint " << jointNames[jn] << llendl; + LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) ); + mSkinJoints[jn].setupSkinJoint( joint ); + } + } + + // setup joint array + if (!mMesh->isLOD()) + { + setupJoint((LLAvatarJoint*)getRoot()); + } + +// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl; +} + +//----------------------------------------------------------------------------- +// setupJoint() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) +{ +// llinfos << "Mesh: " << getName() << llendl; + +// S32 joint_count = 0; + U32 sj; + for (sj=0; sjmJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) + { + // ...then just add ourselves + LLAvatarJoint* jointp = js.mJoint; + mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); +// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl; +// joint_count++; + } + // otherwise add our parent and ourselves + else + { + mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); +// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl; +// joint_count++; + mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); +// llinfos << "joint " << joint_count << current_joint->getName() << llendl; +// joint_count++; + } + } + + // depth-first traversal + for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); + iter != current_joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); + setupJoint(child_joint); + } +} + + +// End diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h new file mode 100755 index 0000000000..dcd202bdaf --- /dev/null +++ b/indra/llappearance/llavatarjointmesh.h @@ -0,0 +1,140 @@ +/** + * @file llavatarjointmesh.h + * @brief Implementation of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINTMESH_H +#define LL_LLAVATARJOINTMESH_H + +#include "llavatarjoint.h" +#include "llgltexture.h" +#include "llpolymesh.h" +#include "v4color.h" + +class LLDrawable; +class LLFace; +class LLCharacter; +class LLTexLayerSet; + +typedef enum e_avatar_render_pass +{ + AVATAR_RENDER_PASS_SINGLE, + AVATAR_RENDER_PASS_CLOTHING_INNER, + AVATAR_RENDER_PASS_CLOTHING_OUTER +} EAvatarRenderPass; + +class LLSkinJoint +{ +public: + LLSkinJoint(); + ~LLSkinJoint(); + BOOL setupSkinJoint( LLAvatarJoint *joint); + + LLAvatarJoint *mJoint; + LLVector3 mRootToJointSkinOffset; + LLVector3 mRootToParentJointSkinOffset; +}; + +//----------------------------------------------------------------------------- +// class LLViewerJointMesh +//----------------------------------------------------------------------------- +class LLAvatarJointMesh : public LLAvatarJoint +{ + friend class LLAvatarAppearance; +protected: + LLColor4 mColor; // color value +// LLColor4 mSpecular; // specular color (always white for now) + F32 mShiny; // shiny value + LLPointer mTexture; // ptr to a global texture + LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar + U32 mTestImageName; // handle to a temporary texture for previewing uploads + LLPolyMesh* mMesh; // ptr to a global polymesh + BOOL mCullBackFaces; // true by default + LLFace* mFace; // ptr to a face w/ AGP copy of mesh + + U32 mFaceIndexCount; + BOOL mIsTransparent; + + U32 mNumSkinJoints; + LLSkinJoint* mSkinJoints; + S32 mMeshID; + +public: + static BOOL sPipelineRender; + //RN: this is here for testing purposes + static U32 sClothingMaskImageName; + static EAvatarRenderPass sRenderPass; + static LLColor4 sClothingInnerColor; + +public: + // Constructor + LLAvatarJointMesh(); + + // Destructor + virtual ~LLAvatarJointMesh(); + + // Gets the shape color + void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); + + // Sets the shape color + void setColor( F32 red, F32 green, F32 blue, F32 alpha ); + + // Sets the shininess + void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; + + // Sets the shape texture + void setTexture( LLGLTexture *texture ); + + void setTestTexture( U32 name ) { mTestImageName = name; } + + // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) + void setLayerSet( LLTexLayerSet* layer_set ); + + // Gets the poly mesh + LLPolyMesh *getMesh(); + + // Sets the poly mesh + void setMesh( LLPolyMesh *mesh ); + + // Sets up joint matrix data for rendering + void setupJoint(LLAvatarJoint* current_joint); + + // Render time method to upload batches of joint matrices + void uploadJointMatrices(); + + // Sets ID for picking + void setMeshID( S32 id ) {mMeshID = id;} + + // Gets ID for picking + S32 getMeshID() { return mMeshID; } + +private: + // Allocate skin data + BOOL allocateSkinData( U32 numSkinJoints ); + + // Free skin data + void freeSkinData(); +}; + +#endif // LL_LLAVATARJOINTMESH_H diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp new file mode 100644 index 0000000000..b1370ab1e3 --- /dev/null +++ b/indra/llappearance/llpolymesh.cpp @@ -0,0 +1,1050 @@ +/** + * @file llpolymesh.cpp + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" +#include "llpolymesh.h" +#include "llfasttimer.h" +#include "llmemory.h" + +//#include "llviewercontrol.h" +#include "llxmltree.h" +#include "llavatarappearance.h" +#include "llwearable.h" +#include "lldir.h" +#include "llvolume.h" +#include "llendianswizzle.h" + + +#define HEADER_ASCII "Linden Mesh 1.0" +#define HEADER_BINARY "Linden Binary Mesh 1.0" + +//extern LLControlGroup gSavedSettings; // read only + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name); +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name); +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name); + +//----------------------------------------------------------------------------- +// Global table of loaded LLPolyMeshes +//----------------------------------------------------------------------------- +LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList; + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData() +//----------------------------------------------------------------------------- +LLPolyMeshSharedData::LLPolyMeshSharedData() +{ + mNumVertices = 0; + mBaseCoords = NULL; + mBaseNormals = NULL; + mBaseBinormals = NULL; + mTexCoords = NULL; + mDetailTexCoords = NULL; + mWeights = NULL; + mHasWeights = FALSE; + mHasDetailTexCoords = FALSE; + + mNumFaces = 0; + mFaces = NULL; + + mNumJointNames = 0; + mJointNames = NULL; + + mTriangleIndices = NULL; + mNumTriangleIndices = 0; + + mReferenceData = NULL; + + mLastIndexOffset = -1; +} + +//----------------------------------------------------------------------------- +// ~LLPolyMeshSharedData() +//----------------------------------------------------------------------------- +LLPolyMeshSharedData::~LLPolyMeshSharedData() +{ + freeMeshData(); + for_each(mMorphData.begin(), mMorphData.end(), DeletePointer()); + mMorphData.clear(); +} + +//----------------------------------------------------------------------------- +// setupLOD() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data) +{ + mReferenceData = reference_data; + + if (reference_data) + { + mBaseCoords = reference_data->mBaseCoords; + mBaseNormals = reference_data->mBaseNormals; + mBaseBinormals = reference_data->mBaseBinormals; + mTexCoords = reference_data->mTexCoords; + mDetailTexCoords = reference_data->mDetailTexCoords; + mWeights = reference_data->mWeights; + mHasWeights = reference_data->mHasWeights; + mHasDetailTexCoords = reference_data->mHasDetailTexCoords; + } +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::freeMeshData() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::freeMeshData() +{ + if (!mReferenceData) + { + mNumVertices = 0; + + ll_aligned_free_16(mBaseCoords); + mBaseCoords = NULL; + + ll_aligned_free_16(mBaseNormals); + mBaseNormals = NULL; + + ll_aligned_free_16(mBaseBinormals); + mBaseBinormals = NULL; + + ll_aligned_free_16(mTexCoords); + mTexCoords = NULL; + + ll_aligned_free_16(mDetailTexCoords); + mDetailTexCoords = NULL; + + ll_aligned_free_16(mWeights); + mWeights = NULL; + } + + mNumFaces = 0; + delete [] mFaces; + mFaces = NULL; + + mNumJointNames = 0; + delete [] mJointNames; + mJointNames = NULL; + + delete [] mTriangleIndices; + mTriangleIndices = NULL; + +// mVertFaceMap.deleteAllData(); +} + +// compate_int is used by the qsort function to sort the index array +int compare_int(const void *a, const void *b); + +//----------------------------------------------------------------------------- +// genIndices() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::genIndices(S32 index_offset) +{ + if (index_offset == mLastIndexOffset) + { + return; + } + + delete []mTriangleIndices; + mTriangleIndices = new U32[mNumTriangleIndices]; + + S32 cur_index = 0; + for (S32 i = 0; i < mNumFaces; i++) + { + mTriangleIndices[cur_index] = mFaces[i][0] + index_offset; + cur_index++; + mTriangleIndices[cur_index] = mFaces[i][1] + index_offset; + cur_index++; + mTriangleIndices[cur_index] = mFaces[i][2] + index_offset; + cur_index++; + } + + mLastIndexOffset = index_offset; +} + +//-------------------------------------------------------------------- +// LLPolyMeshSharedData::getNumKB() +//-------------------------------------------------------------------- +U32 LLPolyMeshSharedData::getNumKB() +{ + U32 num_kb = sizeof(LLPolyMesh); + + if (!isLOD()) + { + num_kb += mNumVertices * + ( sizeof(LLVector3) + // coords + sizeof(LLVector3) + // normals + sizeof(LLVector2) ); // texCoords + } + + if (mHasDetailTexCoords && !isLOD()) + { + num_kb += mNumVertices * sizeof(LLVector2); // detailTexCoords + } + + if (mHasWeights && !isLOD()) + { + num_kb += mNumVertices * sizeof(float); // weights + } + + num_kb += mNumFaces * sizeof(LLPolyFace); // faces + + num_kb /= 1024; + return num_kb; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateVertexData() +//----------------------------------------------------------------------------- +BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) +{ + U32 i; + mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); + for (i = 0; i < numVertices; i++) + { + mBaseCoords[i].clear(); + mBaseNormals[i].clear(); + mBaseBinormals[i].clear(); + mTexCoords[i].clear(); + mWeights[i] = 0.f; + } + mNumVertices = numVertices; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateFaceData() +//----------------------------------------------------------------------------- +BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) +{ + mFaces = new LLPolyFace[ numFaces ]; + mNumFaces = numFaces; + mNumTriangleIndices = mNumFaces * 3; + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateJointNames() +//----------------------------------------------------------------------------- +BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) +{ + mJointNames = new std::string[ numJointNames ]; + mNumJointNames = numJointNames; + return TRUE; +} + +//-------------------------------------------------------------------- +// LLPolyMeshSharedData::loadMesh() +//-------------------------------------------------------------------- +BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) +{ + //------------------------------------------------------------------------- + // Open the file + //------------------------------------------------------------------------- + if(fileName.empty()) + { + llerrs << "Filename is Empty!" << llendl; + return FALSE; + } + LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ + if (!fp) + { + llerrs << "can't open: " << fileName << llendl; + return FALSE; + } + + //------------------------------------------------------------------------- + // Read a chunk + //------------------------------------------------------------------------- + char header[128]; /*Flawfinder: ignore*/ + if (fread(header, sizeof(char), 128, fp) != 128) + { + llwarns << "Short read" << llendl; + } + + //------------------------------------------------------------------------- + // Check for proper binary header + //------------------------------------------------------------------------- + BOOL status = FALSE; + if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ + { + lldebugs << "Loading " << fileName << llendl; + + //---------------------------------------------------------------- + // File Header (seek past it) + //---------------------------------------------------------------- + fseek(fp, 24, SEEK_SET); + + //---------------------------------------------------------------- + // HasWeights + //---------------------------------------------------------------- + U8 hasWeights; + size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); + if (numRead != 1) + { + llerrs << "can't read HasWeights flag from " << fileName << llendl; + return FALSE; + } + if (!isLOD()) + { + mHasWeights = (hasWeights==0) ? FALSE : TRUE; + } + + //---------------------------------------------------------------- + // HasDetailTexCoords + //---------------------------------------------------------------- + U8 hasDetailTexCoords; + numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); + if (numRead != 1) + { + llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl; + return FALSE; + } + + //---------------------------------------------------------------- + // Position + //---------------------------------------------------------------- + LLVector3 position; + numRead = fread(position.mV, sizeof(float), 3, fp); + llendianswizzle(position.mV, sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Position from " << fileName << llendl; + return FALSE; + } + setPosition( position ); + + //---------------------------------------------------------------- + // Rotation + //---------------------------------------------------------------- + LLVector3 rotationAngles; + numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); + llendianswizzle(rotationAngles.mV, sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read RotationAngles from " << fileName << llendl; + return FALSE; + } + + U8 rotationOrder; + numRead = fread(&rotationOrder, sizeof(U8), 1, fp); + + if (numRead != 1) + { + llerrs << "can't read RotationOrder from " << fileName << llendl; + return FALSE; + } + + rotationOrder = 0; + + setRotation( mayaQ( rotationAngles.mV[0], + rotationAngles.mV[1], + rotationAngles.mV[2], + (LLQuaternion::Order)rotationOrder ) ); + + //---------------------------------------------------------------- + // Scale + //---------------------------------------------------------------- + LLVector3 scale; + numRead = fread(scale.mV, sizeof(float), 3, fp); + llendianswizzle(scale.mV, sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Scale from " << fileName << llendl; + return FALSE; + } + setScale( scale ); + + //------------------------------------------------------------------------- + // Release any existing mesh geometry + //------------------------------------------------------------------------- + freeMeshData(); + + U16 numVertices = 0; + + //---------------------------------------------------------------- + // NumVertices + //---------------------------------------------------------------- + if (!isLOD()) + { + numRead = fread(&numVertices, sizeof(U16), 1, fp); + llendianswizzle(&numVertices, sizeof(U16), 1); + if (numRead != 1) + { + llerrs << "can't read NumVertices from " << fileName << llendl; + return FALSE; + } + + allocateVertexData( numVertices ); + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseCoords[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseNormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; + } + } + + //---------------------------------------------------------------- + // TexCoords + //---------------------------------------------------------------- + numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); + llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); + if (numRead != numVertices) + { + llerrs << "can't read TexCoords from " << fileName << llendl; + return FALSE; + } + + //---------------------------------------------------------------- + // DetailTexCoords + //---------------------------------------------------------------- + if (mHasDetailTexCoords) + { + numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); + llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); + if (numRead != numVertices) + { + llerrs << "can't read DetailTexCoords from " << fileName << llendl; + return FALSE; + } + } + + //---------------------------------------------------------------- + // Weights + //---------------------------------------------------------------- + if (mHasWeights) + { + numRead = fread(mWeights, sizeof(float), numVertices, fp); + llendianswizzle(mWeights, sizeof(float), numVertices); + if (numRead != numVertices) + { + llerrs << "can't read Weights from " << fileName << llendl; + return FALSE; + } + } + } + + //---------------------------------------------------------------- + // NumFaces + //---------------------------------------------------------------- + U16 numFaces; + numRead = fread(&numFaces, sizeof(U16), 1, fp); + llendianswizzle(&numFaces, sizeof(U16), 1); + if (numRead != 1) + { + llerrs << "can't read NumFaces from " << fileName << llendl; + return FALSE; + } + allocateFaceData( numFaces ); + + + //---------------------------------------------------------------- + // Faces + //---------------------------------------------------------------- + U32 i; + U32 numTris = 0; + for (i = 0; i < numFaces; i++) + { + S16 face[3]; + numRead = fread(face, sizeof(U16), 3, fp); + llendianswizzle(face, sizeof(U16), 3); + if (numRead != 3) + { + llerrs << "can't read Face[" << i << "] from " << fileName << llendl; + return FALSE; + } + if (mReferenceData) + { + llassert(face[0] < mReferenceData->mNumVertices); + llassert(face[1] < mReferenceData->mNumVertices); + llassert(face[2] < mReferenceData->mNumVertices); + } + + if (isLOD()) + { + // store largest index in case of LODs + for (S32 j = 0; j < 3; j++) + { + if (face[j] > mNumVertices - 1) + { + mNumVertices = face[j] + 1; + } + } + } + mFaces[i][0] = face[0]; + mFaces[i][1] = face[1]; + mFaces[i][2] = face[2]; + +// S32 j; +// for(j = 0; j < 3; j++) +// { +// LLDynamicArray *face_list = mVertFaceMap.getIfThere(face[j]); +// if (!face_list) +// { +// face_list = new LLDynamicArray; +// mVertFaceMap.addData(face[j], face_list); +// } +// face_list->put(i); +// } + + numTris++; + } + + lldebugs << "verts: " << numVertices + << ", faces: " << numFaces + << ", tris: " << numTris + << llendl; + + //---------------------------------------------------------------- + // NumSkinJoints + //---------------------------------------------------------------- + if (!isLOD()) + { + U16 numSkinJoints = 0; + if ( mHasWeights ) + { + numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); + llendianswizzle(&numSkinJoints, sizeof(U16), 1); + if (numRead != 1) + { + llerrs << "can't read NumSkinJoints from " << fileName << llendl; + return FALSE; + } + allocateJointNames( numSkinJoints ); + } + + //---------------------------------------------------------------- + // SkinJoints + //---------------------------------------------------------------- + for (i=0; i < numSkinJoints; i++) + { + char jointName[64+1]; + numRead = fread(jointName, sizeof(jointName)-1, 1, fp); + jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination + if (numRead != 1) + { + llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl; + return FALSE; + } + + std::string *jn = &mJointNames[i]; + *jn = jointName; + } + + //------------------------------------------------------------------------- + // look for morph section + //------------------------------------------------------------------------- + char morphName[64+1]; + morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination + while(fread(&morphName, sizeof(char), 64, fp) == 64) + { + if (!strcmp(morphName, "End Morphs")) + { + // we reached the end of the morphs + break; + } + LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName)); + + BOOL result = morph_data->loadBinary(fp, this); + + if (!result) + { + delete morph_data; + continue; + } + + mMorphData.insert(morph_data); + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_cleavage(morph_data, + .75f, + "Breast_Physics_LeftRight_Driven")); + } + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_InOut_Driven")); + } + if (!strcmp(morphName, "Breast_Gravity")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Torso")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Torso_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Legs")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Legs_UpDown_Driven")); + } + + if (!strcmp(morphName, "skirt_belly")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Skirt_UpDown_Driven")); + } + + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Butt_Physics_UpDown_Driven")); + } + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0.03f,0), + "Butt_Physics_LeftRight_Driven")); + } + } + + S32 numRemaps; + if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) + { + llendianswizzle(&numRemaps, sizeof(S32), 1); + for (S32 i = 0; i < numRemaps; i++) + { + S32 remapSrc; + S32 remapDst; + if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) + { + llerrs << "can't read source vertex in vertex remap data" << llendl; + break; + } + if (fread(&remapDst, sizeof(S32), 1, fp) != 1) + { + llerrs << "can't read destination vertex in vertex remap data" << llendl; + break; + } + llendianswizzle(&remapSrc, sizeof(S32), 1); + llendianswizzle(&remapDst, sizeof(S32), 1); + + mSharedVerts[remapSrc] = remapDst; + } + } + } + + status = TRUE; + } + else + { + llerrs << "invalid mesh file header: " << fileName << llendl; + status = FALSE; + } + + if (0 == mNumJointNames) + { + allocateJointNames(1); + } + + fclose( fp ); + + return status; +} + +//----------------------------------------------------------------------------- +// getSharedVert() +//----------------------------------------------------------------------------- +const S32 *LLPolyMeshSharedData::getSharedVert(S32 vert) +{ + if (mSharedVerts.count(vert) > 0) + { + return &mSharedVerts[vert]; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getUV() +//----------------------------------------------------------------------------- +const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index) +{ + // TODO: convert all index variables to S32 + llassert((S32)index < mNumVertices); + + return mTexCoords[index]; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh) +{ + LLMemType mt(LLMemType::MTYPE_AVATAR_MESH); + + llassert(shared_data); + + mSharedData = shared_data; + mReferenceMesh = reference_mesh; + mAvatarp = NULL; + mVertexData = NULL; + + mCurVertexCount = 0; + mFaceIndexCount = 0; + mFaceIndexOffset = 0; + mFaceVertexCount = 0; + mFaceVertexOffset = 0; + + if (shared_data->isLOD() && reference_mesh) + { + mCoords = reference_mesh->mCoords; + mNormals = reference_mesh->mNormals; + mScaledNormals = reference_mesh->mScaledNormals; + mBinormals = reference_mesh->mBinormals; + mScaledBinormals = reference_mesh->mScaledBinormals; + mTexCoords = reference_mesh->mTexCoords; + mClothingWeights = reference_mesh->mClothingWeights; + } + else + { + // Allocate memory without initializing every vector + // NOTE: This makes asusmptions about the size of LLVector[234] + S32 nverts = mSharedData->mNumVertices; + //make sure it's an even number of verts for alignment + nverts += nverts%2; + S32 nfloats = nverts * ( + 4 + //coords + 4 + //normals + 4 + //weights + 2 + //coords + 4 + //scaled normals + 4 + //binormals + 4); //scaled binormals + + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly + mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); + S32 offset = 0; + mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + initializeForMorph(); + } +} + + +//----------------------------------------------------------------------------- +// ~LLPolyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh::~LLPolyMesh() +{ + S32 i; + for (i = 0; i < mJointRenderData.count(); i++) + { + delete mJointRenderData[i]; + mJointRenderData[i] = NULL; + } + + ll_aligned_free_16(mVertexData); + +} + + +//----------------------------------------------------------------------------- +// LLPolyMesh::getMesh() +//----------------------------------------------------------------------------- +LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_mesh) +{ + //------------------------------------------------------------------------- + // search for an existing mesh by this name + //------------------------------------------------------------------------- + LLPolyMeshSharedData* meshSharedData = get_if_there(sGlobalSharedMeshList, name, (LLPolyMeshSharedData*)NULL); + if (meshSharedData) + { +// llinfos << "Polymesh " << name << " found in global mesh table." << llendl; + LLPolyMesh *poly_mesh = new LLPolyMesh(meshSharedData, reference_mesh); + return poly_mesh; + } + + //------------------------------------------------------------------------- + // if not found, create a new one, add it to the list + //------------------------------------------------------------------------- + std::string full_path; + full_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name); + + LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData(); + if (reference_mesh) + { + mesh_data->setupLOD(reference_mesh->getSharedData()); + } + if ( ! mesh_data->loadMesh( full_path ) ) + { + delete mesh_data; + return NULL; + } + + LLPolyMesh *poly_mesh = new LLPolyMesh(mesh_data, reference_mesh); + +// llinfos << "Polymesh " << name << " added to global mesh table." << llendl; + sGlobalSharedMeshList[name] = poly_mesh->mSharedData; + + return poly_mesh; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh::freeAllMeshes() +//----------------------------------------------------------------------------- +void LLPolyMesh::freeAllMeshes() +{ + // delete each item in the global lists + for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(), DeletePairedPointer()); + sGlobalSharedMeshList.clear(); +} + +LLPolyMeshSharedData *LLPolyMesh::getSharedData() const +{ + return mSharedData; +} + + +//-------------------------------------------------------------------- +// LLPolyMesh::dumpDiagInfo() +//-------------------------------------------------------------------- +void LLPolyMesh::dumpDiagInfo() +{ + // keep track of totals + U32 total_verts = 0; + U32 total_faces = 0; + U32 total_kb = 0; + + std::string buf; + + llinfos << "-----------------------------------------------------" << llendl; + llinfos << " Global PolyMesh Table (DEBUG only)" << llendl; + llinfos << " Verts Faces Mem(KB) Name" << llendl; + llinfos << "-----------------------------------------------------" << llendl; + + // print each loaded mesh, and it's memory usage + for(LLPolyMeshSharedDataTable::iterator iter = sGlobalSharedMeshList.begin(); + iter != sGlobalSharedMeshList.end(); ++iter) + { + const std::string& mesh_name = iter->first; + LLPolyMeshSharedData* mesh = iter->second; + + S32 num_verts = mesh->mNumVertices; + S32 num_faces = mesh->mNumFaces; + U32 num_kb = mesh->getNumKB(); + + buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name.c_str()); + llinfos << buf << llendl; + + total_verts += num_verts; + total_faces += num_faces; + total_kb += num_kb; + } + + llinfos << "-----------------------------------------------------" << llendl; + buf = llformat("%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); + llinfos << buf << llendl; + llinfos << "-----------------------------------------------------" << llendl; +} + +//----------------------------------------------------------------------------- +// getWritableCoords() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableCoords() +{ + return mCoords; +} + +//----------------------------------------------------------------------------- +// getWritableNormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableNormals() +{ + return mNormals; +} + +//----------------------------------------------------------------------------- +// getWritableBinormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableBinormals() +{ + return mBinormals; +} + + +//----------------------------------------------------------------------------- +// getWritableClothingWeights() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableClothingWeights() +{ + return mClothingWeights; +} + +//----------------------------------------------------------------------------- +// getWritableTexCoords() +//----------------------------------------------------------------------------- +LLVector2 *LLPolyMesh::getWritableTexCoords() +{ + return mTexCoords; +} + +//----------------------------------------------------------------------------- +// getScaledNormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getScaledNormals() +{ + return mScaledNormals; +} + +//----------------------------------------------------------------------------- +// getScaledBinormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getScaledBinormals() +{ + return mScaledBinormals; +} + + +//----------------------------------------------------------------------------- +// initializeForMorph() +//----------------------------------------------------------------------------- +void LLPolyMesh::initializeForMorph() +{ + LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + + for (U32 i = 0; i < mSharedData->mNumVertices; ++i) + { + mClothingWeights[i].clear(); + } +} + +//----------------------------------------------------------------------------- +// getMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData* LLPolyMesh::getMorphData(const std::string& morph_name) +{ + if (!mSharedData) + return NULL; + for (LLPolyMeshSharedData::morphdata_list_t::iterator iter = mSharedData->mMorphData.begin(); + iter != mSharedData->mMorphData.end(); ++iter) + { + LLPolyMorphData *morph_data = *iter; + if (morph_data->getName() == morph_name) + { + return morph_data; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// removeMorphData() +//----------------------------------------------------------------------------- +// // erasing but not deleting seems bad, but fortunately we don't actually use this... +// void LLPolyMesh::removeMorphData(LLPolyMorphData *morph_target) +// { +// if (!mSharedData) +// return; +// mSharedData->mMorphData.erase(morph_target); +// } + +//----------------------------------------------------------------------------- +// deleteAllMorphData() +//----------------------------------------------------------------------------- +// void LLPolyMesh::deleteAllMorphData() +// { +// if (!mSharedData) +// return; + +// for_each(mSharedData->mMorphData.begin(), mSharedData->mMorphData.end(), DeletePointer()); +// mSharedData->mMorphData.clear(); +// } + +//----------------------------------------------------------------------------- +// getWritableWeights() +//----------------------------------------------------------------------------- +F32* LLPolyMesh::getWritableWeights() const +{ + return mSharedData->mWeights; +} + +// End diff --git a/indra/llappearance/llpolymesh.h b/indra/llappearance/llpolymesh.h new file mode 100644 index 0000000000..ef1dfb1adb --- /dev/null +++ b/indra/llappearance/llpolymesh.h @@ -0,0 +1,369 @@ +/** + * @file llpolymesh.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYMESHINTERFACE_H +#define LL_LLPOLYMESHINTERFACE_H + +#include +#include +#include "llstl.h" + +#include "v3math.h" +#include "v2math.h" +#include "llquaternion.h" +#include "llpolymorph.h" +#include "lljoint.h" +//#include "lldarray.h" + +class LLSkinJoint; +class LLAvatarAppearance; +class LLWearable; + +//#define USE_STRIPS // Use tri-strips for rendering. + +//----------------------------------------------------------------------------- +// LLPolyFace +// A set of 4 vertex indices. +// An LLPolyFace can represent either a triangle or quad. +// If the last index is -1, it's a triangle. +//----------------------------------------------------------------------------- +typedef S32 LLPolyFace[3]; + +//struct PrimitiveGroup; + +//----------------------------------------------------------------------------- +// LLPolyMesh +// A polyhedra consisting of any number of triangles and quads. +// All instances contain a set of faces, and optionally may include +// faces grouped into named face sets. +//----------------------------------------------------------------------------- +class LLPolyMorphTarget; + +class LLPolyMeshSharedData +{ + friend class LLPolyMesh; +private: + // transform data + LLVector3 mPosition; + LLQuaternion mRotation; + LLVector3 mScale; + + // vertex data + S32 mNumVertices; + LLVector4a *mBaseCoords; + LLVector4a *mBaseNormals; + LLVector4a *mBaseBinormals; + LLVector2 *mTexCoords; + LLVector2 *mDetailTexCoords; + F32 *mWeights; + + BOOL mHasWeights; + BOOL mHasDetailTexCoords; + + // face data + S32 mNumFaces; + LLPolyFace *mFaces; + + // face set data + U32 mNumJointNames; + std::string* mJointNames; + + // morph targets + typedef std::set morphdata_list_t; + morphdata_list_t mMorphData; + + std::map mSharedVerts; + + LLPolyMeshSharedData* mReferenceData; + S32 mLastIndexOffset; + +public: + // Temporarily... + // Triangle indices + U32 mNumTriangleIndices; + U32 *mTriangleIndices; + +public: + LLPolyMeshSharedData(); + ~LLPolyMeshSharedData(); + +private: + void setupLOD(LLPolyMeshSharedData* reference_data); + + // Frees all mesh memory resources + void freeMeshData(); + + void setPosition( const LLVector3 &pos ) { mPosition = pos; } + void setRotation( const LLQuaternion &rot ) { mRotation = rot; } + void setScale( const LLVector3 &scale ) { mScale = scale; } + + BOOL allocateVertexData( U32 numVertices ); + + BOOL allocateFaceData( U32 numFaces ); + + BOOL allocateJointNames( U32 numJointNames ); + + // Retrieve the number of KB of memory used by this instance + U32 getNumKB(); + + // Load mesh data from file + BOOL loadMesh( const std::string& fileName ); + +public: + void genIndices(S32 offset); + + const LLVector2 &getUVs(U32 index); + + const S32 *getSharedVert(S32 vert); + + BOOL isLOD() { return (mReferenceData != NULL); } +}; + + +class LLJointRenderData +{ +public: + LLJointRenderData(const LLMatrix4* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {} + ~LLJointRenderData(){} + + const LLMatrix4* mWorldMatrix; + LLSkinJoint* mSkinJoint; +}; + + +class LLPolyMesh +{ +public: + + // Constructor + LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh); + + // Destructor + ~LLPolyMesh(); + + // Requests a mesh by name. + // If the mesh already exists in the global mesh table, it is returned, + // otherwise it is loaded from file, added to the table, and returned. + static LLPolyMesh *getMesh( const std::string &name, LLPolyMesh* reference_mesh = NULL); + + // Frees all loaded meshes. + // This should only be called once you know there are no outstanding + // references to these objects. Generally, upon exit of the application. + static void freeAllMeshes(); + + //-------------------------------------------------------------------- + // Transform Data Access + //-------------------------------------------------------------------- + // Get position + const LLVector3 &getPosition() { + llassert (mSharedData); + return mSharedData->mPosition; + } + + // Get rotation + const LLQuaternion &getRotation() { + llassert (mSharedData); + return mSharedData->mRotation; + } + + // Get scale + const LLVector3 &getScale() { + llassert (mSharedData); + return mSharedData->mScale; + } + + //-------------------------------------------------------------------- + // Vertex Data Access + //-------------------------------------------------------------------- + // Get number of vertices + U32 getNumVertices() { + llassert (mSharedData); + return mSharedData->mNumVertices; + } + + // Returns whether or not the mesh has detail texture coords + BOOL hasDetailTexCoords() { + llassert (mSharedData); + return mSharedData->mHasDetailTexCoords; + } + + // Returns whether or not the mesh has vertex weights + BOOL hasWeights() const{ + llassert (mSharedData); + return mSharedData->mHasWeights; + } + + // Get coords + const LLVector4a *getCoords() const{ + return mCoords; + } + + // non const version + LLVector4a *getWritableCoords(); + + // Get normals + const LLVector4a *getNormals() const{ + return mNormals; + } + + // Get normals + const LLVector4a *getBinormals() const{ + return mBinormals; + } + + // Get base mesh normals + const LLVector4a *getBaseNormals() const{ + llassert(mSharedData); + return mSharedData->mBaseNormals; + } + + // Get base mesh normals + const LLVector4a *getBaseBinormals() const{ + llassert(mSharedData); + return mSharedData->mBaseBinormals; + } + + // intermediate morphed normals and output normals + LLVector4a *getWritableNormals(); + LLVector4a *getScaledNormals(); + + LLVector4a *getWritableBinormals(); + LLVector4a *getScaledBinormals(); + + // Get texCoords + const LLVector2 *getTexCoords() const { + return mTexCoords; + } + + // non const version + LLVector2 *getWritableTexCoords(); + + // Get detailTexCoords + const LLVector2 *getDetailTexCoords() const { + llassert (mSharedData); + return mSharedData->mDetailTexCoords; + } + + // Get weights + const F32 *getWeights() const { + llassert (mSharedData); + return mSharedData->mWeights; + } + + F32 *getWritableWeights() const; + + LLVector4a *getWritableClothingWeights(); + + const LLVector4a *getClothingWeights() + { + return mClothingWeights; + } + + //-------------------------------------------------------------------- + // Face Data Access + //-------------------------------------------------------------------- + // Get number of faces + S32 getNumFaces() { + llassert (mSharedData); + return mSharedData->mNumFaces; + } + + // Get faces + LLPolyFace *getFaces() { + llassert (mSharedData); + return mSharedData->mFaces; + } + + U32 getNumJointNames() { + llassert (mSharedData); + return mSharedData->mNumJointNames; + } + + std::string *getJointNames() { + llassert (mSharedData); + return mSharedData->mJointNames; + } + + LLPolyMorphData* getMorphData(const std::string& morph_name); +// void removeMorphData(LLPolyMorphData *morph_target); +// void deleteAllMorphData(); + + LLPolyMeshSharedData *getSharedData() const; + LLPolyMesh *getReferenceMesh() { return mReferenceMesh ? mReferenceMesh : this; } + + // Get indices + U32* getIndices() { return mSharedData ? mSharedData->mTriangleIndices : NULL; } + + BOOL isLOD() { return mSharedData && mSharedData->isLOD(); } + + void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; } + LLAvatarAppearance* getAvatar() { return mAvatarp; } + + LLDynamicArray mJointRenderData; + + U32 mFaceVertexOffset; + U32 mFaceVertexCount; + U32 mFaceIndexOffset; + U32 mFaceIndexCount; + U32 mCurVertexCount; +private: + void initializeForMorph(); + + // Dumps diagnostic information about the global mesh table + static void dumpDiagInfo(); + +protected: + // mesh data shared across all instances of a given mesh + LLPolyMeshSharedData *mSharedData; + // Single array of floats for allocation / deletion + F32 *mVertexData; + // deformed vertices (resulting from application of morph targets) + LLVector4a *mCoords; + // deformed normals (resulting from application of morph targets) + LLVector4a *mScaledNormals; + // output normals (after normalization) + LLVector4a *mNormals; + // deformed binormals (resulting from application of morph targets) + LLVector4a *mScaledBinormals; + // output binormals (after normalization) + LLVector4a *mBinormals; + // weight values that mark verts as clothing/skin + LLVector4a *mClothingWeights; + // output texture coordinates + LLVector2 *mTexCoords; + + LLPolyMesh *mReferenceMesh; + + // global mesh list + typedef std::map LLPolyMeshSharedDataTable; + static LLPolyMeshSharedDataTable sGlobalSharedMeshList; + + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance* mAvatarp; +}; + +#endif // LL_LLPOLYMESHINTERFACE_H + diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp new file mode 100644 index 0000000000..aa680894ff --- /dev/null +++ b/indra/llappearance/llpolymorph.cpp @@ -0,0 +1,748 @@ +/** + * @file llpolymorph.cpp + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- + +#include "llpolymorph.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llwearable.h" +#include "llxmltree.h" +#include "llendianswizzle.h" +#include "llpolymesh.h" + +//#include "../tools/imdebug/imdebug.h" + +const F32 NORMAL_SOFTEN_FACTOR = 0.65f; + +//----------------------------------------------------------------------------- +// LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) + : mName(morph_name) +{ + mNumIndices = 0; + mCurrentIndex = 0; + mTotalDistortion = 0.f; + mAvgDistortion.clear(); + mMaxDistortion = 0.f; + mVertexIndices = NULL; + mCoords = NULL; + mNormals = NULL; + mBinormals = NULL; + mTexCoords = NULL; + + mMesh = NULL; +} + +LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : + mName(rhs.mName), + mNumIndices(rhs.mNumIndices), + mTotalDistortion(rhs.mTotalDistortion), + mAvgDistortion(rhs.mAvgDistortion), + mMaxDistortion(rhs.mMaxDistortion), + mVertexIndices(NULL), + mCoords(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL) +{ + const S32 numVertices = mNumIndices; + + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; + mTexCoords = new LLVector2[numVertices]; + mVertexIndices = new U32[numVertices]; + + for (S32 v=0; v < numVertices; v++) + { + mCoords[v] = rhs.mCoords[v]; + mNormals[v] = rhs.mNormals[v]; + mBinormals[v] = rhs.mBinormals[v]; + mTexCoords[v] = rhs.mTexCoords[v]; + mVertexIndices[v] = rhs.mVertexIndices[v]; + } +} + + +//----------------------------------------------------------------------------- +// ~LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::~LLPolyMorphData() +{ + delete [] mVertexIndices; + delete [] mCoords; + delete [] mNormals; + delete [] mBinormals; + delete [] mTexCoords; +} + +//----------------------------------------------------------------------------- +// loadBinary() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) +{ + S32 numVertices; + S32 numRead; + + numRead = fread(&numVertices, sizeof(S32), 1, fp); + llendianswizzle(&numVertices, sizeof(S32), 1); + if (numRead != 1) + { + llwarns << "Can't read number of morph target vertices" << llendl; + return FALSE; + } + + //------------------------------------------------------------------------- + // allocate vertices + //------------------------------------------------------------------------- + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; + mTexCoords = new LLVector2[numVertices]; + // Actually, we are allocating more space than we need for the skiplist + mVertexIndices = new U32[numVertices]; + mNumIndices = 0; + mTotalDistortion = 0.f; + mMaxDistortion = 0.f; + mAvgDistortion.clear(); + mMesh = mesh; + + //------------------------------------------------------------------------- + // read vertices + //------------------------------------------------------------------------- + for(S32 v = 0; v < numVertices; v++) + { + numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp); + llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); + if (numRead != 1) + { + llwarns << "Can't read morph target vertex number" << llendl; + return FALSE; + } + + if (mVertexIndices[v] > 10000) + { + llerrs << "Bad morph index: " << mVertexIndices[v] << llendl; + } + + + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); + if (numRead != 3) + { + llwarns << "Can't read morph target vertex coordinates" << llendl; + return FALSE; + } + + F32 magnitude = mCoords[v].getLength3().getF32(); + + mTotalDistortion += magnitude; + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); + + if (magnitude > mMaxDistortion) + { + mMaxDistortion = magnitude; + } + + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); + if (numRead != 3) + { + llwarns << "Can't read morph target normal" << llendl; + return FALSE; + } + + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); + if (numRead != 3) + { + llwarns << "Can't read morph target binormal" << llendl; + return FALSE; + } + + + numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); + llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); + if (numRead != 2) + { + llwarns << "Can't read morph target uv" << llendl; + return FALSE; + } + + mNumIndices++; + } + + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTargetInfo() +//----------------------------------------------------------------------------- +LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() + : mIsClothingMorph(FALSE) +{ +} + +BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return FALSE; + + // Get mixed-case name + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if( !node->getFastAttributeString( name_string, mMorphName ) ) + { + llwarns << "Avatar file: is missing name attribute" << llendl; + return FALSE; // Continue, ignoring this tag + } + + static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); + node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph); + + LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); + + if (NULL == paramNode) + { + llwarns << "Failed to getChildByName(\"param_morph\")" + << llendl; + return FALSE; + } + + for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); + child_node; + child_node = paramNode->getNextChild()) + { + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (child_node->hasName("volume_morph")) + { + std::string volume_name; + if (child_node->getFastAttributeString(name_string, volume_name)) + { + LLVector3 scale; + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + child_node->getFastAttributeVector3(scale_string, scale); + + LLVector3 pos; + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + child_node->getFastAttributeVector3(pos_string, pos); + + mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos)); + } + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) + : mMorphData(NULL), mMesh(poly_mesh), + mVertMask(NULL), + mLastSex(SEX_FEMALE), + mNumMorphMasksPending(0) +{ +} + +//----------------------------------------------------------------------------- +// ~LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::~LLPolyMorphTarget() +{ + if (mVertMask) + { + delete mVertMask; + } +} + +//----------------------------------------------------------------------------- +// setInfo() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return FALSE; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight(), FALSE ); + + LLAvatarAppearance* avatarp = mMesh->getAvatar(); + LLPolyMorphTargetInfo::volume_info_list_t::iterator iter; + for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++) + { + LLPolyVolumeMorphInfo *volume_info = &(*iter); + for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++) + { + if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName) + { + mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], + volume_info->mScale, + volume_info->mPos)); + break; + } + } + } + + std::string morph_param_name = getInfo()->mMorphName; + + mMorphData = mMesh->getMorphData(morph_param_name); + if (!mMorphData) + { + const std::string driven_tag = "_Driven"; + U32 pos = morph_param_name.find(driven_tag); + if (pos > 0) + { + morph_param_name = morph_param_name.substr(0,pos); + mMorphData = mMesh->getMorphData(morph_param_name); + } + } + if (!mMorphData) + { + llwarns << "No morph target named " << morph_param_name << " found in mesh." << llendl; + return FALSE; // Continue, ignoring this tag + } + return TRUE; +} + +/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const +{ + LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh); + *new_param = *this; + return new_param; +} + +#if 0 // obsolete +//----------------------------------------------------------------------------- +// parseData() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) +{ + LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; + + info->parseXml(node); + if (!setInfo(info)) + { + delete info; + return FALSE; + } + return TRUE; +} +#endif + +//----------------------------------------------------------------------------- +// getVertexDistortion() +//----------------------------------------------------------------------------- +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +{ + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); + + for(U32 index = 0; index < mMorphData->mNumIndices; index++) + { + if (mMorphData->mVertexIndices[index] == (U32)requested_index) + { + return mMorphData->mCoords[index]; + } + } + + return LLVector4a::getZero(); +} + +//----------------------------------------------------------------------------- +// getFirstDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex = 0; + if (mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getNextDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex++; + if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getTotalDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getTotalDistortion() +{ + if (mMorphData) + { + return mMorphData->mTotalDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// getAvgDistortion() +//----------------------------------------------------------------------------- +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() +{ + if (mMorphData) + { + return mMorphData->mAvgDistortion; + } + else + { + return LLVector4a::getZero(); + } +} + +//----------------------------------------------------------------------------- +// getMaxDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getMaxDistortion() +{ + if (mMorphData) + { + return mMorphData->mMaxDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_APPLY_MORPH_TARGET("Apply Morph"); + +void LLPolyMorphTarget::apply( ESex avatar_sex ) +{ + if (!mMorphData || mNumMorphMasksPending > 0) + { + return; + } + + LLFastTimer t(FTM_APPLY_MORPH_TARGET); + + mLastSex = avatar_sex; + + // Check for NaN condition (NaN is detected if a variable doesn't equal itself. + if (mCurWeight != mCurWeight) + { + mCurWeight = 0.0; + } + if (mLastWeight != mLastWeight) + { + mLastWeight = mCurWeight+.001; + } + + // perform differential update of morph + F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); + // store last weight + mLastWeight += delta_weight; + + if (delta_weight != 0.f) + { + llassert(!mMesh->isLOD()); + LLVector4a *coords = mMesh->getWritableCoords(); + + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); + + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); + + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) + { + S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; + + F32 maskWeight = 1.f; + if (maskWeightArray) + { + maskWeight = maskWeightArray[vert_index_morph]; + } + + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); + + if (getInfo()->mIsClothingMorph && clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; + } + + // calculate new normals based on half angles + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + norm.normalize3fast(); + normals[vert_index_mesh] = norm; + + // calculate new binormals + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; + } + + // now apply volume changes + for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ ) + { + LLPolyVolumeMorph* volume_morph = &(*iter); + LLVector3 scale_delta = volume_morph->mScale * delta_weight; + LLVector3 pos_delta = volume_morph->mPos * delta_weight; + + volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta); + volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta); + } + } + + if (mNext) + { + mNext->apply(avatar_sex); + } +} + +//----------------------------------------------------------------------------- +// applyMask() +//----------------------------------------------------------------------------- +void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) +{ + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + + if (!mVertMask) + { + mVertMask = new LLPolyVertexMask(mMorphData); + mNumMorphMasksPending--; + } + else + { + // remove effect of previous mask + F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + if (maskWeights) + { + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) + { + F32 lastMaskWeight = mLastWeight * maskWeights[vert]; + S32 out_vert = mMorphData->mVertexIndices[vert]; + + // remove effect of existing masked morph + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; + + if (clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); + } + } + } + } + + // set last weight to 0, since we've removed the effect of this morph + mLastWeight = 0.f; + + mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); + + apply(mLastSex); +} + + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) +{ + mWeights = new F32[morph_data->mNumIndices]; + mMorphData = morph_data; + mWeightsGenerated = FALSE; +} + +//----------------------------------------------------------------------------- +// ~LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::~LLPolyVertexMask() +{ + delete[] mWeights; +} + +//----------------------------------------------------------------------------- +// generateMask() +//----------------------------------------------------------------------------- +void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) +{ +// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) +// BOOL debugImg = FALSE; +// if (debugImg) +// { +// if (invert) +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData); +// } +// else +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData); +// } +// } + for (U32 index = 0; index < mMorphData->mNumIndices; index++) + { + S32 vertIndex = mMorphData->mVertexIndices[index]; + const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex); + LLVector2 uvCoords; + + if (sharedVertIndex) + { + uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex); + } + else + { + uvCoords = mMorphData->mMesh->getUVs(vertIndex); + } + U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); + U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); + + mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f; + + if (invert) + { + mWeights[index] = 1.f - mWeights[index]; + } + + // now apply step function + // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f; + + if (clothing_weights) + { + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; + } + } + mWeightsGenerated = TRUE; +} + +//----------------------------------------------------------------------------- +// getMaskForMorphIndex() +//----------------------------------------------------------------------------- +F32* LLPolyVertexMask::getMorphMaskWeights() +{ + if (!mWeightsGenerated) + { + return NULL; + } + + return mWeights; +} diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h new file mode 100644 index 0000000000..d6cf9e52ca --- /dev/null +++ b/indra/llappearance/llpolymorph.h @@ -0,0 +1,182 @@ +/** + * @file llpolymorph.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYMORPH_H +#define LL_LLPOLYMORPH_H + +#include +#include + +#include "llviewervisualparam.h" + +class LLAvatarJointCollisionVolume; +class LLPolyMeshSharedData; +class LLVector2; +class LLAvatarJointCollisionVolume; +class LLWearable; + +//----------------------------------------------------------------------------- +// LLPolyMorphData() +//----------------------------------------------------------------------------- +class LLPolyMorphData +{ +public: + LLPolyMorphData(const std::string& morph_name); + ~LLPolyMorphData(); + LLPolyMorphData(const LLPolyMorphData &rhs); + + BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); + const std::string& getName() { return mName; } + +public: + std::string mName; + + // morphology + U32 mNumIndices; + U32* mVertexIndices; + U32 mCurrentIndex; + LLVector4a* mCoords; + LLVector4a* mNormals; + LLVector4a* mBinormals; + LLVector2* mTexCoords; + + F32 mTotalDistortion; // vertex distortion summed over entire morph + F32 mMaxDistortion; // maximum single vertex distortion in a given morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LLPolyMeshSharedData* mMesh; +}; + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +class LLPolyVertexMask +{ +public: + LLPolyVertexMask(LLPolyMorphData* morph_data); + ~LLPolyVertexMask(); + + void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); + F32* getMorphMaskWeights(); + + +protected: + F32* mWeights; + LLPolyMorphData *mMorphData; + BOOL mWeightsGenerated; + +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget Data structs +//----------------------------------------------------------------------------- +struct LLPolyVolumeMorphInfo +{ + LLPolyVolumeMorphInfo(std::string &name, LLVector3 &scale, LLVector3 &pos) + : mName(name), mScale(scale), mPos(pos) {}; + + std::string mName; + LLVector3 mScale; + LLVector3 mPos; +}; + +struct LLPolyVolumeMorph +{ + LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) + : mVolume(volume), mScale(scale), mPos(pos) {}; + + LLAvatarJointCollisionVolume* mVolume; + LLVector3 mScale; + LLVector3 mPos; +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTargetInfo +// Shared information for LLPolyMorphTargets +//----------------------------------------------------------------------------- +class LLPolyMorphTargetInfo : public LLViewerVisualParamInfo +{ + friend class LLPolyMorphTarget; +public: + LLPolyMorphTargetInfo(); + /*virtual*/ ~LLPolyMorphTargetInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + +protected: + std::string mMorphName; + BOOL mIsClothingMorph; + typedef std::vector volume_info_list_t; + volume_info_list_t mVolumeInfoList; +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget +// A set of vertex data associated with morph target. +// These morph targets must be topologically consistent with a given Polymesh +// (share face sets) +//----------------------------------------------------------------------------- +class LLPolyMorphTarget : public LLViewerVisualParam +{ +public: + LLPolyMorphTarget(LLPolyMesh *poly_mesh); + ~LLPolyMorphTarget(); + + // Special: These functions are overridden by child classes + LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLPolyMorphTargetInfo *info); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex sex ); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); + /*virtual*/ F32 getMaxDistortion(); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + + void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); + void addPendingMorphMask() { mNumMorphMasksPending++; } + +protected: + LLPolyMorphData* mMorphData; + LLPolyMesh* mMesh; + LLPolyVertexMask * mVertMask; + ESex mLastSex; + // number of morph masks that haven't been generated, must be 0 before this morph is applied + BOOL mNumMorphMasksPending; + + typedef std::vector volume_list_t; + volume_list_t mVolumeMorphs; + +}; + +#endif // LL_LLPOLYMORPH_H diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp new file mode 100644 index 0000000000..4ba16691c2 --- /dev/null +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -0,0 +1,293 @@ +/** + * @file llpolyskeletaldistortion.cpp + * @brief Implementation of LLPolySkeletalDistortion classes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llpreprocessor.h" +#include "llerrorlegacy.h" +//#include "llcommon.h" +//#include "llmemory.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llpolymorph.h" +//#include "llviewercontrol.h" +//#include "llxmltree.h" +//#include "llvoavatar.h" +#include "llwearable.h" +//#include "lldir.h" +//#include "llvolume.h" +//#include "llendianswizzle.h" + +#include "llpolyskeletaldistortion.h" + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortionInfo() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() +{ +} + +BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return FALSE; + + LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); + + if (NULL == skeletalParam) + { + llwarns << "Failed to getChildByName(\"param_skeleton\")" + << llendl; + return FALSE; + } + + for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) + { + if (bone->hasName("bone")) + { + std::string name; + LLVector3 scale; + LLVector3 pos; + BOOL haspos = FALSE; + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!bone->getFastAttributeString(name_string, name)) + { + llwarns << "No bone name specified for skeletal param." << llendl; + continue; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!bone->getFastAttributeVector3(scale_string, scale)) + { + llwarns << "No scale specified for bone " << name << "." << llendl; + continue; + } + + // optional offset deformation (translation) + static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); + if (bone->getFastAttributeVector3(offset_string, pos)) + { + haspos = TRUE; + } + mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); + } + else + { + llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl; + continue; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp) +{ + mAvatar = avatarp; + mDefaultVec.splat(0.001f); +} + +//----------------------------------------------------------------------------- +// ~LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::~LLPolySkeletalDistortion() +{ +} + +BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return FALSE; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight(), FALSE ); + + LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; + for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) + { + LLPolySkeletalBoneInfo *bone_info = &(*iter); + LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); + if (!joint) + { + llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl; + continue; + } + + if (mJointScales.find(joint) != mJointScales.end()) + { + llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl; + } + + // store it + mJointScales[joint] = bone_info->mScaleDeformation; + + // apply to children that need to inherit it + for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); + if (child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info->mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } + } + + if (bone_info->mHasPositionDeformation) + { + if (mJointOffsets.find(joint) != mJointOffsets.end()) + { + llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl; + } + mJointOffsets[joint] = bone_info->mPositionDeformation; + } + } + return TRUE; +} + +/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const +{ + LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar); + *new_param = *this; + return new_param; +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); + +void LLPolySkeletalDistortion::apply( ESex avatar_sex ) +{ + LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); + + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); + + LLJoint* joint; + joint_vec_map_t::iterator iter; + + for (iter = mJointScales.begin(); + iter != mJointScales.end(); + iter++) + { + joint = iter->first; + LLVector3 newScale = joint->getScale(); + LLVector3 scaleDelta = iter->second; + newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); + joint->setScale(newScale); + } + + for (iter = mJointOffsets.begin(); + iter != mJointOffsets.end(); + iter++) + { + joint = iter->first; + LLVector3 newPosition = joint->getPosition(); + LLVector3 positionDelta = iter->second; + newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); + joint->setPosition(newPosition); + } + + if (mLastWeight != mCurWeight && !mIsAnimating) + { + mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); + } + mLastWeight = mCurWeight; +} + + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = src_data->mCoords[v]; + cloned_morph_data->mNormals[v] = src_data->mNormals[v]; + cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } + } + return cloned_morph_data; +} + +// End diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h new file mode 100644 index 0000000000..040cf841ea --- /dev/null +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -0,0 +1,119 @@ +/** + * @file llpolyskeletaldistortion.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYSKELETALDISTORTION_H +#define LL_LLPOLYSKELETALDISTORTION_H + +#include "llcommon.h" + +#include +#include +#include "llstl.h" + +#include "v3math.h" +#include "v2math.h" +#include "llquaternion.h" +//#include "llpolymorph.h" +#include "lljoint.h" +#include "llviewervisualparam.h" +//#include "lldarray.h" + +//class LLSkinJoint; +class LLAvatarAppearance; + +//#define USE_STRIPS // Use tri-strips for rendering. + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformationInfo +// Shared information for LLPolySkeletalDeformations +//----------------------------------------------------------------------------- +struct LLPolySkeletalBoneInfo +{ + LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos) + : mBoneName(name), + mScaleDeformation(scale), + mPositionDeformation(pos), + mHasPositionDeformation(haspos) {} + std::string mBoneName; + LLVector3 mScaleDeformation; + LLVector3 mPositionDeformation; + BOOL mHasPositionDeformation; +}; + +class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo +{ + friend class LLPolySkeletalDistortion; +public: + LLPolySkeletalDistortionInfo(); + /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; + + /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + +protected: + typedef std::vector bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformation +// A set of joint scale data for deforming the avatar mesh +//----------------------------------------------------------------------------- +class LLPolySkeletalDistortion : public LLViewerVisualParam +{ +public: + LLPolySkeletalDistortion(LLAvatarAppearance *avatarp); + ~LLPolySkeletalDistortion(); + + // Special: These functions are overridden by child classes + LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLPolySkeletalDistortionInfo *info); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex sex ); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 0.1f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ F32 getMaxDistortion() { return 0.1f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + +protected: + typedef std::map joint_vec_map_t; + joint_vec_map_t mJointScales; + joint_vec_map_t mJointOffsets; + LLVector4a mDefaultVec; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance *mAvatar; +}; + +#endif // LL_LLPOLYSKELETALDISTORTION_H + diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 21b1512e58..7942e815ae 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -443,8 +443,6 @@ set(viewer_SOURCE_FILES llplacesinventorybridge.cpp llplacesinventorypanel.cpp llpopupview.cpp - llpolymesh.cpp - llpolymorph.cpp llpostcard.cpp llpreview.cpp llpreviewanim.cpp @@ -1000,8 +998,6 @@ set(viewer_HEADER_FILES llpipelinelistener.h llplacesinventorybridge.h llplacesinventorypanel.h - llpolymesh.h - llpolymorph.h llpopupview.h llpostcard.h llpreview.h diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index e1ef0d5399..7f4d33753d 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1078,8 +1078,8 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) if (!isAgentAvatarValid()) return; - LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot.getWorldRotation(); - LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot.getWorldRotation(); + LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); + LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && (root_at * last_at_axis > 0.95f)) @@ -1432,7 +1432,7 @@ void LLAgentCamera::updateCamera() LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); LLVector3 diff = mCameraPositionAgent - head_pos; - diff = diff * ~gAgentAvatarp->mRoot.getWorldRotation(); + diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); LLJoint* torso_joint = gAgentAvatarp->mTorsop; LLJoint* chest_joint = gAgentAvatarp->mChestp; @@ -1456,7 +1456,7 @@ void LLAgentCamera::updateCamera() gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); - gAgentAvatarp->mRoot.updateWorldMatrixChildren(); + gAgentAvatarp->mRoot->updateWorldMatrixChildren(); for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ) @@ -1684,7 +1684,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) F32 camera_land_height; LLVector3d frame_center_global = !isAgentAvatarValid() ? gAgent.getPositionGlobal() : - gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition()); + gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); BOOL isConstrained = FALSE; LLVector3d head_offset; diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index fa0ad20fdb..ce67c6c65d 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1097,12 +1097,12 @@ BOOL LLPreviewAnimation::render() gGL.flush(); - LLVector3 target_pos = avatarp->mRoot.getWorldPosition(); + LLVector3 target_pos = avatarp->mRoot->getWorldPosition(); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * LLQuaternion(mCameraYaw, LLVector3::z_axis); - LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot; + LLQuaternion av_rot = avatarp->mRoot->getWorldRotation() * camera_rot; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera LLVector3::z_axis, // up diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 6b2492d927..887cd2f4b0 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -593,7 +593,7 @@ S8 LLImagePreviewAvatar::getType() const void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) { - mTargetJoint = mDummyAvatar->mRoot.findJoint(joint_name); + mTargetJoint = mDummyAvatar->mRoot->findJoint(joint_name); // clear out existing test mesh if (mTargetMesh) { @@ -612,9 +612,9 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const mDummyAvatar->updateVisualParams(); mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); } - mDummyAvatar->mRoot.setVisible(FALSE, TRUE); + mDummyAvatar->mRoot->setVisible(FALSE, TRUE); - mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name); + mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name); mTargetMesh->setTestTexture(mTextureName); mTargetMesh->setVisible(TRUE, FALSE); mCameraDistance = distance; @@ -631,7 +631,7 @@ void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name) { if (mDummyAvatar) { - LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name); + LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name); // clear out existing test mesh if (mesh) { diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index bc3b220dc0..9dde65ceb6 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -636,7 +636,7 @@ bool LLHUDEffectLookAt::calcTargetPosition() } else { - target_rot = target_av->mRoot.getWorldRotation(); + target_rot = target_av->mRoot->getWorldRotation(); } } else // target obj is not an avatar diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp deleted file mode 100644 index 70f3b5335e..0000000000 --- a/indra/newview/llpolymesh.cpp +++ /dev/null @@ -1,1297 +0,0 @@ -/** - * @file llpolymesh.cpp - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" - -#include "llfasttimer.h" -#include "llmemory.h" - -#include "llviewercontrol.h" -#include "llxmltree.h" -#include "llvoavatar.h" -#include "llwearable.h" -#include "lldir.h" -#include "llvolume.h" -#include "llendianswizzle.h" - -#include "llpolymesh.h" - -#define HEADER_ASCII "Linden Mesh 1.0" -#define HEADER_BINARY "Linden Binary Mesh 1.0" - -extern LLControlGroup gSavedSettings; // read only - -LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, - const std::string &name); -LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, - const LLVector3 &direction, - const std::string &name); -LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, - F32 scale, - const std::string &name); - -//----------------------------------------------------------------------------- -// Global table of loaded LLPolyMeshes -//----------------------------------------------------------------------------- -LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList; - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData() -//----------------------------------------------------------------------------- -LLPolyMeshSharedData::LLPolyMeshSharedData() -{ - mNumVertices = 0; - mBaseCoords = NULL; - mBaseNormals = NULL; - mBaseBinormals = NULL; - mTexCoords = NULL; - mDetailTexCoords = NULL; - mWeights = NULL; - mHasWeights = FALSE; - mHasDetailTexCoords = FALSE; - - mNumFaces = 0; - mFaces = NULL; - - mNumJointNames = 0; - mJointNames = NULL; - - mTriangleIndices = NULL; - mNumTriangleIndices = 0; - - mReferenceData = NULL; - - mLastIndexOffset = -1; -} - -//----------------------------------------------------------------------------- -// ~LLPolyMeshSharedData() -//----------------------------------------------------------------------------- -LLPolyMeshSharedData::~LLPolyMeshSharedData() -{ - freeMeshData(); - for_each(mMorphData.begin(), mMorphData.end(), DeletePointer()); - mMorphData.clear(); -} - -//----------------------------------------------------------------------------- -// setupLOD() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data) -{ - mReferenceData = reference_data; - - if (reference_data) - { - mBaseCoords = reference_data->mBaseCoords; - mBaseNormals = reference_data->mBaseNormals; - mBaseBinormals = reference_data->mBaseBinormals; - mTexCoords = reference_data->mTexCoords; - mDetailTexCoords = reference_data->mDetailTexCoords; - mWeights = reference_data->mWeights; - mHasWeights = reference_data->mHasWeights; - mHasDetailTexCoords = reference_data->mHasDetailTexCoords; - } -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::freeMeshData() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::freeMeshData() -{ - if (!mReferenceData) - { - mNumVertices = 0; - - ll_aligned_free_16(mBaseCoords); - mBaseCoords = NULL; - - ll_aligned_free_16(mBaseNormals); - mBaseNormals = NULL; - - ll_aligned_free_16(mBaseBinormals); - mBaseBinormals = NULL; - - ll_aligned_free_16(mTexCoords); - mTexCoords = NULL; - - ll_aligned_free_16(mDetailTexCoords); - mDetailTexCoords = NULL; - - ll_aligned_free_16(mWeights); - mWeights = NULL; - } - - mNumFaces = 0; - delete [] mFaces; - mFaces = NULL; - - mNumJointNames = 0; - delete [] mJointNames; - mJointNames = NULL; - - delete [] mTriangleIndices; - mTriangleIndices = NULL; - -// mVertFaceMap.deleteAllData(); -} - -// compate_int is used by the qsort function to sort the index array -int compare_int(const void *a, const void *b); - -//----------------------------------------------------------------------------- -// genIndices() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::genIndices(S32 index_offset) -{ - if (index_offset == mLastIndexOffset) - { - return; - } - - delete []mTriangleIndices; - mTriangleIndices = new U32[mNumTriangleIndices]; - - S32 cur_index = 0; - for (S32 i = 0; i < mNumFaces; i++) - { - mTriangleIndices[cur_index] = mFaces[i][0] + index_offset; - cur_index++; - mTriangleIndices[cur_index] = mFaces[i][1] + index_offset; - cur_index++; - mTriangleIndices[cur_index] = mFaces[i][2] + index_offset; - cur_index++; - } - - mLastIndexOffset = index_offset; -} - -//-------------------------------------------------------------------- -// LLPolyMeshSharedData::getNumKB() -//-------------------------------------------------------------------- -U32 LLPolyMeshSharedData::getNumKB() -{ - U32 num_kb = sizeof(LLPolyMesh); - - if (!isLOD()) - { - num_kb += mNumVertices * - ( sizeof(LLVector3) + // coords - sizeof(LLVector3) + // normals - sizeof(LLVector2) ); // texCoords - } - - if (mHasDetailTexCoords && !isLOD()) - { - num_kb += mNumVertices * sizeof(LLVector2); // detailTexCoords - } - - if (mHasWeights && !isLOD()) - { - num_kb += mNumVertices * sizeof(float); // weights - } - - num_kb += mNumFaces * sizeof(LLPolyFace); // faces - - num_kb /= 1024; - return num_kb; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateVertexData() -//----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) -{ - U32 i; - mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); - mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); - mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); - for (i = 0; i < numVertices; i++) - { - mBaseCoords[i].clear(); - mBaseNormals[i].clear(); - mBaseBinormals[i].clear(); - mTexCoords[i].clear(); - mWeights[i] = 0.f; - } - mNumVertices = numVertices; - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateFaceData() -//----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) -{ - mFaces = new LLPolyFace[ numFaces ]; - mNumFaces = numFaces; - mNumTriangleIndices = mNumFaces * 3; - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateJointNames() -//----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) -{ - mJointNames = new std::string[ numJointNames ]; - mNumJointNames = numJointNames; - return TRUE; -} - -//-------------------------------------------------------------------- -// LLPolyMeshSharedData::loadMesh() -//-------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) -{ - //------------------------------------------------------------------------- - // Open the file - //------------------------------------------------------------------------- - if(fileName.empty()) - { - llerrs << "Filename is Empty!" << llendl; - return FALSE; - } - LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ - if (!fp) - { - llerrs << "can't open: " << fileName << llendl; - return FALSE; - } - - //------------------------------------------------------------------------- - // Read a chunk - //------------------------------------------------------------------------- - char header[128]; /*Flawfinder: ignore*/ - if (fread(header, sizeof(char), 128, fp) != 128) - { - llwarns << "Short read" << llendl; - } - - //------------------------------------------------------------------------- - // Check for proper binary header - //------------------------------------------------------------------------- - BOOL status = FALSE; - if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ - { - lldebugs << "Loading " << fileName << llendl; - - //---------------------------------------------------------------- - // File Header (seek past it) - //---------------------------------------------------------------- - fseek(fp, 24, SEEK_SET); - - //---------------------------------------------------------------- - // HasWeights - //---------------------------------------------------------------- - U8 hasWeights; - size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); - if (numRead != 1) - { - llerrs << "can't read HasWeights flag from " << fileName << llendl; - return FALSE; - } - if (!isLOD()) - { - mHasWeights = (hasWeights==0) ? FALSE : TRUE; - } - - //---------------------------------------------------------------- - // HasDetailTexCoords - //---------------------------------------------------------------- - U8 hasDetailTexCoords; - numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); - if (numRead != 1) - { - llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // Position - //---------------------------------------------------------------- - LLVector3 position; - numRead = fread(position.mV, sizeof(float), 3, fp); - llendianswizzle(position.mV, sizeof(float), 3); - if (numRead != 3) - { - llerrs << "can't read Position from " << fileName << llendl; - return FALSE; - } - setPosition( position ); - - //---------------------------------------------------------------- - // Rotation - //---------------------------------------------------------------- - LLVector3 rotationAngles; - numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); - llendianswizzle(rotationAngles.mV, sizeof(float), 3); - if (numRead != 3) - { - llerrs << "can't read RotationAngles from " << fileName << llendl; - return FALSE; - } - - U8 rotationOrder; - numRead = fread(&rotationOrder, sizeof(U8), 1, fp); - - if (numRead != 1) - { - llerrs << "can't read RotationOrder from " << fileName << llendl; - return FALSE; - } - - rotationOrder = 0; - - setRotation( mayaQ( rotationAngles.mV[0], - rotationAngles.mV[1], - rotationAngles.mV[2], - (LLQuaternion::Order)rotationOrder ) ); - - //---------------------------------------------------------------- - // Scale - //---------------------------------------------------------------- - LLVector3 scale; - numRead = fread(scale.mV, sizeof(float), 3, fp); - llendianswizzle(scale.mV, sizeof(float), 3); - if (numRead != 3) - { - llerrs << "can't read Scale from " << fileName << llendl; - return FALSE; - } - setScale( scale ); - - //------------------------------------------------------------------------- - // Release any existing mesh geometry - //------------------------------------------------------------------------- - freeMeshData(); - - U16 numVertices = 0; - - //---------------------------------------------------------------- - // NumVertices - //---------------------------------------------------------------- - if (!isLOD()) - { - numRead = fread(&numVertices, sizeof(U16), 1, fp); - llendianswizzle(&numVertices, sizeof(U16), 1); - if (numRead != 1) - { - llerrs << "can't read NumVertices from " << fileName << llendl; - return FALSE; - } - - allocateVertexData( numVertices ); - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Coords - //---------------------------------------------------------------- - numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseCoords[i], sizeof(float), 3); - if (numRead != 3) - { - llerrs << "can't read Coordinates from " << fileName << llendl; - return FALSE; - } - } - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Normals - //---------------------------------------------------------------- - numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseNormals[i], sizeof(float), 3); - if (numRead != 3) - { - llerrs << " can't read Normals from " << fileName << llendl; - return FALSE; - } - } - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Binormals - //---------------------------------------------------------------- - numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); - if (numRead != 3) - { - llerrs << " can't read Binormals from " << fileName << llendl; - return FALSE; - } - } - - //---------------------------------------------------------------- - // TexCoords - //---------------------------------------------------------------- - numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); - llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); - if (numRead != numVertices) - { - llerrs << "can't read TexCoords from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // DetailTexCoords - //---------------------------------------------------------------- - if (mHasDetailTexCoords) - { - numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); - llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); - if (numRead != numVertices) - { - llerrs << "can't read DetailTexCoords from " << fileName << llendl; - return FALSE; - } - } - - //---------------------------------------------------------------- - // Weights - //---------------------------------------------------------------- - if (mHasWeights) - { - numRead = fread(mWeights, sizeof(float), numVertices, fp); - llendianswizzle(mWeights, sizeof(float), numVertices); - if (numRead != numVertices) - { - llerrs << "can't read Weights from " << fileName << llendl; - return FALSE; - } - } - } - - //---------------------------------------------------------------- - // NumFaces - //---------------------------------------------------------------- - U16 numFaces; - numRead = fread(&numFaces, sizeof(U16), 1, fp); - llendianswizzle(&numFaces, sizeof(U16), 1); - if (numRead != 1) - { - llerrs << "can't read NumFaces from " << fileName << llendl; - return FALSE; - } - allocateFaceData( numFaces ); - - - //---------------------------------------------------------------- - // Faces - //---------------------------------------------------------------- - U32 i; - U32 numTris = 0; - for (i = 0; i < numFaces; i++) - { - S16 face[3]; - numRead = fread(face, sizeof(U16), 3, fp); - llendianswizzle(face, sizeof(U16), 3); - if (numRead != 3) - { - llerrs << "can't read Face[" << i << "] from " << fileName << llendl; - return FALSE; - } - if (mReferenceData) - { - llassert(face[0] < mReferenceData->mNumVertices); - llassert(face[1] < mReferenceData->mNumVertices); - llassert(face[2] < mReferenceData->mNumVertices); - } - - if (isLOD()) - { - // store largest index in case of LODs - for (S32 j = 0; j < 3; j++) - { - if (face[j] > mNumVertices - 1) - { - mNumVertices = face[j] + 1; - } - } - } - mFaces[i][0] = face[0]; - mFaces[i][1] = face[1]; - mFaces[i][2] = face[2]; - -// S32 j; -// for(j = 0; j < 3; j++) -// { -// LLDynamicArray *face_list = mVertFaceMap.getIfThere(face[j]); -// if (!face_list) -// { -// face_list = new LLDynamicArray; -// mVertFaceMap.addData(face[j], face_list); -// } -// face_list->put(i); -// } - - numTris++; - } - - lldebugs << "verts: " << numVertices - << ", faces: " << numFaces - << ", tris: " << numTris - << llendl; - - //---------------------------------------------------------------- - // NumSkinJoints - //---------------------------------------------------------------- - if (!isLOD()) - { - U16 numSkinJoints = 0; - if ( mHasWeights ) - { - numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); - llendianswizzle(&numSkinJoints, sizeof(U16), 1); - if (numRead != 1) - { - llerrs << "can't read NumSkinJoints from " << fileName << llendl; - return FALSE; - } - allocateJointNames( numSkinJoints ); - } - - //---------------------------------------------------------------- - // SkinJoints - //---------------------------------------------------------------- - for (i=0; i < numSkinJoints; i++) - { - char jointName[64+1]; - numRead = fread(jointName, sizeof(jointName)-1, 1, fp); - jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination - if (numRead != 1) - { - llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl; - return FALSE; - } - - std::string *jn = &mJointNames[i]; - *jn = jointName; - } - - //------------------------------------------------------------------------- - // look for morph section - //------------------------------------------------------------------------- - char morphName[64+1]; - morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination - while(fread(&morphName, sizeof(char), 64, fp) == 64) - { - if (!strcmp(morphName, "End Morphs")) - { - // we reached the end of the morphs - break; - } - LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName)); - - BOOL result = morph_data->loadBinary(fp, this); - - if (!result) - { - delete morph_data; - continue; - } - - mMorphData.insert(morph_data); - - if (!strcmp(morphName, "Breast_Female_Cleavage")) - { - mMorphData.insert(clone_morph_param_cleavage(morph_data, - .75f, - "Breast_Physics_LeftRight_Driven")); - } - - if (!strcmp(morphName, "Breast_Female_Cleavage")) - { - mMorphData.insert(clone_morph_param_duplicate(morph_data, - "Breast_Physics_InOut_Driven")); - } - if (!strcmp(morphName, "Breast_Gravity")) - { - mMorphData.insert(clone_morph_param_duplicate(morph_data, - "Breast_Physics_UpDown_Driven")); - } - - if (!strcmp(morphName, "Big_Belly_Torso")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Torso_UpDown_Driven")); - } - - if (!strcmp(morphName, "Big_Belly_Legs")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Legs_UpDown_Driven")); - } - - if (!strcmp(morphName, "skirt_belly")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Skirt_UpDown_Driven")); - } - - if (!strcmp(morphName, "Small_Butt")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Butt_Physics_UpDown_Driven")); - } - if (!strcmp(morphName, "Small_Butt")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0.03f,0), - "Butt_Physics_LeftRight_Driven")); - } - } - - S32 numRemaps; - if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) - { - llendianswizzle(&numRemaps, sizeof(S32), 1); - for (S32 i = 0; i < numRemaps; i++) - { - S32 remapSrc; - S32 remapDst; - if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) - { - llerrs << "can't read source vertex in vertex remap data" << llendl; - break; - } - if (fread(&remapDst, sizeof(S32), 1, fp) != 1) - { - llerrs << "can't read destination vertex in vertex remap data" << llendl; - break; - } - llendianswizzle(&remapSrc, sizeof(S32), 1); - llendianswizzle(&remapDst, sizeof(S32), 1); - - mSharedVerts[remapSrc] = remapDst; - } - } - } - - status = TRUE; - } - else - { - llerrs << "invalid mesh file header: " << fileName << llendl; - status = FALSE; - } - - if (0 == mNumJointNames) - { - allocateJointNames(1); - } - - fclose( fp ); - - return status; -} - -//----------------------------------------------------------------------------- -// getSharedVert() -//----------------------------------------------------------------------------- -const S32 *LLPolyMeshSharedData::getSharedVert(S32 vert) -{ - if (mSharedVerts.count(vert) > 0) - { - return &mSharedVerts[vert]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getUV() -//----------------------------------------------------------------------------- -const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index) -{ - // TODO: convert all index variables to S32 - llassert((S32)index < mNumVertices); - - return mTexCoords[index]; -} - -//----------------------------------------------------------------------------- -// LLPolyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh) -{ - LLMemType mt(LLMemType::MTYPE_AVATAR_MESH); - - llassert(shared_data); - - mSharedData = shared_data; - mReferenceMesh = reference_mesh; - mAvatarp = NULL; - mVertexData = NULL; - - mCurVertexCount = 0; - mFaceIndexCount = 0; - mFaceIndexOffset = 0; - mFaceVertexCount = 0; - mFaceVertexOffset = 0; - - if (shared_data->isLOD() && reference_mesh) - { - mCoords = reference_mesh->mCoords; - mNormals = reference_mesh->mNormals; - mScaledNormals = reference_mesh->mScaledNormals; - mBinormals = reference_mesh->mBinormals; - mScaledBinormals = reference_mesh->mScaledBinormals; - mTexCoords = reference_mesh->mTexCoords; - mClothingWeights = reference_mesh->mClothingWeights; - } - else - { - // Allocate memory without initializing every vector - // NOTE: This makes asusmptions about the size of LLVector[234] - S32 nverts = mSharedData->mNumVertices; - //make sure it's an even number of verts for alignment - nverts += nverts%2; - S32 nfloats = nverts * ( - 4 + //coords - 4 + //normals - 4 + //weights - 2 + //coords - 4 + //scaled normals - 4 + //binormals - 4); //scaled binormals - - //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly - mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); - S32 offset = 0; - mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - initializeForMorph(); - } -} - - -//----------------------------------------------------------------------------- -// ~LLPolyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh::~LLPolyMesh() -{ - S32 i; - for (i = 0; i < mJointRenderData.count(); i++) - { - delete mJointRenderData[i]; - mJointRenderData[i] = NULL; - } - - ll_aligned_free_16(mVertexData); - -} - - -//----------------------------------------------------------------------------- -// LLPolyMesh::getMesh() -//----------------------------------------------------------------------------- -LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_mesh) -{ - //------------------------------------------------------------------------- - // search for an existing mesh by this name - //------------------------------------------------------------------------- - LLPolyMeshSharedData* meshSharedData = get_if_there(sGlobalSharedMeshList, name, (LLPolyMeshSharedData*)NULL); - if (meshSharedData) - { -// llinfos << "Polymesh " << name << " found in global mesh table." << llendl; - LLPolyMesh *poly_mesh = new LLPolyMesh(meshSharedData, reference_mesh); - return poly_mesh; - } - - //------------------------------------------------------------------------- - // if not found, create a new one, add it to the list - //------------------------------------------------------------------------- - std::string full_path; - full_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name); - - LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData(); - if (reference_mesh) - { - mesh_data->setupLOD(reference_mesh->getSharedData()); - } - if ( ! mesh_data->loadMesh( full_path ) ) - { - delete mesh_data; - return NULL; - } - - LLPolyMesh *poly_mesh = new LLPolyMesh(mesh_data, reference_mesh); - -// llinfos << "Polymesh " << name << " added to global mesh table." << llendl; - sGlobalSharedMeshList[name] = poly_mesh->mSharedData; - - return poly_mesh; -} - -//----------------------------------------------------------------------------- -// LLPolyMesh::freeAllMeshes() -//----------------------------------------------------------------------------- -void LLPolyMesh::freeAllMeshes() -{ - // delete each item in the global lists - for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(), DeletePairedPointer()); - sGlobalSharedMeshList.clear(); -} - -LLPolyMeshSharedData *LLPolyMesh::getSharedData() const -{ - return mSharedData; -} - - -//-------------------------------------------------------------------- -// LLPolyMesh::dumpDiagInfo() -//-------------------------------------------------------------------- -void LLPolyMesh::dumpDiagInfo() -{ - // keep track of totals - U32 total_verts = 0; - U32 total_faces = 0; - U32 total_kb = 0; - - std::string buf; - - llinfos << "-----------------------------------------------------" << llendl; - llinfos << " Global PolyMesh Table (DEBUG only)" << llendl; - llinfos << " Verts Faces Mem(KB) Name" << llendl; - llinfos << "-----------------------------------------------------" << llendl; - - // print each loaded mesh, and it's memory usage - for(LLPolyMeshSharedDataTable::iterator iter = sGlobalSharedMeshList.begin(); - iter != sGlobalSharedMeshList.end(); ++iter) - { - const std::string& mesh_name = iter->first; - LLPolyMeshSharedData* mesh = iter->second; - - S32 num_verts = mesh->mNumVertices; - S32 num_faces = mesh->mNumFaces; - U32 num_kb = mesh->getNumKB(); - - buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name.c_str()); - llinfos << buf << llendl; - - total_verts += num_verts; - total_faces += num_faces; - total_kb += num_kb; - } - - llinfos << "-----------------------------------------------------" << llendl; - buf = llformat("%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); - llinfos << buf << llendl; - llinfos << "-----------------------------------------------------" << llendl; -} - -//----------------------------------------------------------------------------- -// getWritableCoords() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableCoords() -{ - return mCoords; -} - -//----------------------------------------------------------------------------- -// getWritableNormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableNormals() -{ - return mNormals; -} - -//----------------------------------------------------------------------------- -// getWritableBinormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableBinormals() -{ - return mBinormals; -} - - -//----------------------------------------------------------------------------- -// getWritableClothingWeights() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableClothingWeights() -{ - return mClothingWeights; -} - -//----------------------------------------------------------------------------- -// getWritableTexCoords() -//----------------------------------------------------------------------------- -LLVector2 *LLPolyMesh::getWritableTexCoords() -{ - return mTexCoords; -} - -//----------------------------------------------------------------------------- -// getScaledNormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getScaledNormals() -{ - return mScaledNormals; -} - -//----------------------------------------------------------------------------- -// getScaledBinormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getScaledBinormals() -{ - return mScaledBinormals; -} - - -//----------------------------------------------------------------------------- -// initializeForMorph() -//----------------------------------------------------------------------------- -void LLPolyMesh::initializeForMorph() -{ - LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); - - for (U32 i = 0; i < mSharedData->mNumVertices; ++i) - { - mClothingWeights[i].clear(); - } -} - -//----------------------------------------------------------------------------- -// getMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData* LLPolyMesh::getMorphData(const std::string& morph_name) -{ - if (!mSharedData) - return NULL; - for (LLPolyMeshSharedData::morphdata_list_t::iterator iter = mSharedData->mMorphData.begin(); - iter != mSharedData->mMorphData.end(); ++iter) - { - LLPolyMorphData *morph_data = *iter; - if (morph_data->getName() == morph_name) - { - return morph_data; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// removeMorphData() -//----------------------------------------------------------------------------- -// // erasing but not deleting seems bad, but fortunately we don't actually use this... -// void LLPolyMesh::removeMorphData(LLPolyMorphData *morph_target) -// { -// if (!mSharedData) -// return; -// mSharedData->mMorphData.erase(morph_target); -// } - -//----------------------------------------------------------------------------- -// deleteAllMorphData() -//----------------------------------------------------------------------------- -// void LLPolyMesh::deleteAllMorphData() -// { -// if (!mSharedData) -// return; - -// for_each(mSharedData->mMorphData.begin(), mSharedData->mMorphData.end(), DeletePointer()); -// mSharedData->mMorphData.clear(); -// } - -//----------------------------------------------------------------------------- -// getWritableWeights() -//----------------------------------------------------------------------------- -F32* LLPolyMesh::getWritableWeights() const -{ - return mSharedData->mWeights; -} - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortionInfo() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() -{ -} - -BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; - - LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); - - if (NULL == skeletalParam) - { - llwarns << "Failed to getChildByName(\"param_skeleton\")" - << llendl; - return FALSE; - } - - for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) - { - if (bone->hasName("bone")) - { - std::string name; - LLVector3 scale; - LLVector3 pos; - BOOL haspos = FALSE; - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!bone->getFastAttributeString(name_string, name)) - { - llwarns << "No bone name specified for skeletal param." << llendl; - continue; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!bone->getFastAttributeVector3(scale_string, scale)) - { - llwarns << "No scale specified for bone " << name << "." << llendl; - continue; - } - - // optional offset deformation (translation) - static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); - if (bone->getFastAttributeVector3(offset_string, pos)) - { - haspos = TRUE; - } - mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); - } - else - { - llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl; - continue; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp) -{ - mAvatar = avatarp; - mDefaultVec.splat(0.001f); -} - -//----------------------------------------------------------------------------- -// ~LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::~LLPolySkeletalDistortion() -{ -} - -BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return FALSE; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight(), FALSE ); - - LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter; - for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++) - { - LLPolySkeletalBoneInfo *bone_info = &(*iter); - LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName); - if (!joint) - { - llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl; - continue; - } - - if (mJointScales.find(joint) != mJointScales.end()) - { - llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl; - } - - // store it - mJointScales[joint] = bone_info->mScaleDeformation; - - // apply to children that need to inherit it - for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); - iter != joint->mChildren.end(); ++iter) - { - LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); - if (child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info->mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } - } - - if (bone_info->mHasPositionDeformation) - { - if (mJointOffsets.find(joint) != mJointOffsets.end()) - { - llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl; - } - mJointOffsets[joint] = bone_info->mPositionDeformation; - } - } - return TRUE; -} - -/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const -{ - LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar); - *new_param = *this; - return new_param; -} - -//----------------------------------------------------------------------------- -// apply() -//----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); - -void LLPolySkeletalDistortion::apply( ESex avatar_sex ) -{ - LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); - - F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); - - LLJoint* joint; - joint_vec_map_t::iterator iter; - - for (iter = mJointScales.begin(); - iter != mJointScales.end(); - iter++) - { - joint = iter->first; - LLVector3 newScale = joint->getScale(); - LLVector3 scaleDelta = iter->second; - newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta); - joint->setScale(newScale); - } - - for (iter = mJointOffsets.begin(); - iter != mJointOffsets.end(); - iter++) - { - joint = iter->first; - LLVector3 newPosition = joint->getPosition(); - LLVector3 positionDelta = iter->second; - newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); - joint->setPosition(newPosition); - } - - if (mLastWeight != mCurWeight && !mIsAnimating) - { - mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); - } - mLastWeight = mCurWeight; -} - - -LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, - const LLVector3 &direction, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - LLVector4a dir; - dir.load3(direction.mV); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = dir; - cloned_morph_data->mNormals[v].clear(); - cloned_morph_data->mBinormals[v].clear(); - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, - F32 scale, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - - LLVector4a sc; - sc.splat(scale); - - LLVector4a nsc; - nsc.set(scale, -scale, scale, scale); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); - } - else - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); - } - } - return cloned_morph_data; -} - -// End diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h deleted file mode 100644 index ffb11a3f7e..0000000000 --- a/indra/newview/llpolymesh.h +++ /dev/null @@ -1,438 +0,0 @@ -/** - * @file llpolymesh.h - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPOLYMESH_H -#define LL_LLPOLYMESH_H - -#include -#include -#include "llstl.h" - -#include "v3math.h" -#include "v2math.h" -#include "llquaternion.h" -#include "llpolymorph.h" -#include "lljoint.h" -//#include "lldarray.h" - -class LLSkinJoint; -class LLVOAvatar; -class LLWearable; - -//#define USE_STRIPS // Use tri-strips for rendering. - -//----------------------------------------------------------------------------- -// LLPolyFace -// A set of 4 vertex indices. -// An LLPolyFace can represent either a triangle or quad. -// If the last index is -1, it's a triangle. -//----------------------------------------------------------------------------- -typedef S32 LLPolyFace[3]; - -//struct PrimitiveGroup; - -//----------------------------------------------------------------------------- -// LLPolyMesh -// A polyhedra consisting of any number of triangles and quads. -// All instances contain a set of faces, and optionally may include -// faces grouped into named face sets. -//----------------------------------------------------------------------------- -class LLPolyMorphTarget; - -class LLPolyMeshSharedData -{ - friend class LLPolyMesh; -private: - // transform data - LLVector3 mPosition; - LLQuaternion mRotation; - LLVector3 mScale; - - // vertex data - S32 mNumVertices; - LLVector4a *mBaseCoords; - LLVector4a *mBaseNormals; - LLVector4a *mBaseBinormals; - LLVector2 *mTexCoords; - LLVector2 *mDetailTexCoords; - F32 *mWeights; - - BOOL mHasWeights; - BOOL mHasDetailTexCoords; - - // face data - S32 mNumFaces; - LLPolyFace *mFaces; - - // face set data - U32 mNumJointNames; - std::string* mJointNames; - - // morph targets - typedef std::set morphdata_list_t; - morphdata_list_t mMorphData; - - std::map mSharedVerts; - - LLPolyMeshSharedData* mReferenceData; - S32 mLastIndexOffset; - -public: - // Temporarily... - // Triangle indices - U32 mNumTriangleIndices; - U32 *mTriangleIndices; - -public: - LLPolyMeshSharedData(); - ~LLPolyMeshSharedData(); - -private: - void setupLOD(LLPolyMeshSharedData* reference_data); - - // Frees all mesh memory resources - void freeMeshData(); - - void setPosition( const LLVector3 &pos ) { mPosition = pos; } - void setRotation( const LLQuaternion &rot ) { mRotation = rot; } - void setScale( const LLVector3 &scale ) { mScale = scale; } - - BOOL allocateVertexData( U32 numVertices ); - - BOOL allocateFaceData( U32 numFaces ); - - BOOL allocateJointNames( U32 numJointNames ); - - // Retrieve the number of KB of memory used by this instance - U32 getNumKB(); - - // Load mesh data from file - BOOL loadMesh( const std::string& fileName ); - -public: - void genIndices(S32 offset); - - const LLVector2 &getUVs(U32 index); - - const S32 *getSharedVert(S32 vert); - - BOOL isLOD() { return (mReferenceData != NULL); } -}; - - -class LLJointRenderData -{ -public: - LLJointRenderData(const LLMatrix4* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {} - ~LLJointRenderData(){} - - const LLMatrix4* mWorldMatrix; - LLSkinJoint* mSkinJoint; -}; - - -class LLPolyMesh -{ -public: - - // Constructor - LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh); - - // Destructor - ~LLPolyMesh(); - - // Requests a mesh by name. - // If the mesh already exists in the global mesh table, it is returned, - // otherwise it is loaded from file, added to the table, and returned. - static LLPolyMesh *getMesh( const std::string &name, LLPolyMesh* reference_mesh = NULL); - - // Frees all loaded meshes. - // This should only be called once you know there are no outstanding - // references to these objects. Generally, upon exit of the application. - static void freeAllMeshes(); - - //-------------------------------------------------------------------- - // Transform Data Access - //-------------------------------------------------------------------- - // Get position - const LLVector3 &getPosition() { - llassert (mSharedData); - return mSharedData->mPosition; - } - - // Get rotation - const LLQuaternion &getRotation() { - llassert (mSharedData); - return mSharedData->mRotation; - } - - // Get scale - const LLVector3 &getScale() { - llassert (mSharedData); - return mSharedData->mScale; - } - - //-------------------------------------------------------------------- - // Vertex Data Access - //-------------------------------------------------------------------- - // Get number of vertices - U32 getNumVertices() { - llassert (mSharedData); - return mSharedData->mNumVertices; - } - - // Returns whether or not the mesh has detail texture coords - BOOL hasDetailTexCoords() { - llassert (mSharedData); - return mSharedData->mHasDetailTexCoords; - } - - // Returns whether or not the mesh has vertex weights - BOOL hasWeights() const{ - llassert (mSharedData); - return mSharedData->mHasWeights; - } - - // Get coords - const LLVector4a *getCoords() const{ - return mCoords; - } - - // non const version - LLVector4a *getWritableCoords(); - - // Get normals - const LLVector4a *getNormals() const{ - return mNormals; - } - - // Get normals - const LLVector4a *getBinormals() const{ - return mBinormals; - } - - // Get base mesh normals - const LLVector4a *getBaseNormals() const{ - llassert(mSharedData); - return mSharedData->mBaseNormals; - } - - // Get base mesh normals - const LLVector4a *getBaseBinormals() const{ - llassert(mSharedData); - return mSharedData->mBaseBinormals; - } - - // intermediate morphed normals and output normals - LLVector4a *getWritableNormals(); - LLVector4a *getScaledNormals(); - - LLVector4a *getWritableBinormals(); - LLVector4a *getScaledBinormals(); - - // Get texCoords - const LLVector2 *getTexCoords() const { - return mTexCoords; - } - - // non const version - LLVector2 *getWritableTexCoords(); - - // Get detailTexCoords - const LLVector2 *getDetailTexCoords() const { - llassert (mSharedData); - return mSharedData->mDetailTexCoords; - } - - // Get weights - const F32 *getWeights() const { - llassert (mSharedData); - return mSharedData->mWeights; - } - - F32 *getWritableWeights() const; - - LLVector4a *getWritableClothingWeights(); - - const LLVector4a *getClothingWeights() - { - return mClothingWeights; - } - - //-------------------------------------------------------------------- - // Face Data Access - //-------------------------------------------------------------------- - // Get number of faces - S32 getNumFaces() { - llassert (mSharedData); - return mSharedData->mNumFaces; - } - - // Get faces - LLPolyFace *getFaces() { - llassert (mSharedData); - return mSharedData->mFaces; - } - - U32 getNumJointNames() { - llassert (mSharedData); - return mSharedData->mNumJointNames; - } - - std::string *getJointNames() { - llassert (mSharedData); - return mSharedData->mJointNames; - } - - LLPolyMorphData* getMorphData(const std::string& morph_name); -// void removeMorphData(LLPolyMorphData *morph_target); -// void deleteAllMorphData(); - - LLPolyMeshSharedData *getSharedData() const; - LLPolyMesh *getReferenceMesh() { return mReferenceMesh ? mReferenceMesh : this; } - - // Get indices - U32* getIndices() { return mSharedData ? mSharedData->mTriangleIndices : NULL; } - - BOOL isLOD() { return mSharedData && mSharedData->isLOD(); } - - void setAvatar(LLVOAvatar* avatarp) { mAvatarp = avatarp; } - LLVOAvatar* getAvatar() { return mAvatarp; } - - LLDynamicArray mJointRenderData; - - U32 mFaceVertexOffset; - U32 mFaceVertexCount; - U32 mFaceIndexOffset; - U32 mFaceIndexCount; - U32 mCurVertexCount; -private: - void initializeForMorph(); - - // Dumps diagnostic information about the global mesh table - static void dumpDiagInfo(); - -protected: - // mesh data shared across all instances of a given mesh - LLPolyMeshSharedData *mSharedData; - // Single array of floats for allocation / deletion - F32 *mVertexData; - // deformed vertices (resulting from application of morph targets) - LLVector4a *mCoords; - // deformed normals (resulting from application of morph targets) - LLVector4a *mScaledNormals; - // output normals (after normalization) - LLVector4a *mNormals; - // deformed binormals (resulting from application of morph targets) - LLVector4a *mScaledBinormals; - // output binormals (after normalization) - LLVector4a *mBinormals; - // weight values that mark verts as clothing/skin - LLVector4a *mClothingWeights; - // output texture coordinates - LLVector2 *mTexCoords; - - LLPolyMesh *mReferenceMesh; - - // global mesh list - typedef std::map LLPolyMeshSharedDataTable; - static LLPolyMeshSharedDataTable sGlobalSharedMeshList; - - // Backlink only; don't make this an LLPointer. - LLVOAvatar* mAvatarp; -}; - -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformationInfo -// Shared information for LLPolySkeletalDeformations -//----------------------------------------------------------------------------- -struct LLPolySkeletalBoneInfo -{ - LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos) - : mBoneName(name), - mScaleDeformation(scale), - mPositionDeformation(pos), - mHasPositionDeformation(haspos) {} - std::string mBoneName; - LLVector3 mScaleDeformation; - LLVector3 mPositionDeformation; - BOOL mHasPositionDeformation; -}; - -class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo -{ - friend class LLPolySkeletalDistortion; -public: - LLPolySkeletalDistortionInfo(); - /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; - - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - -protected: - typedef std::vector bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformation -// A set of joint scale data for deforming the avatar mesh -//----------------------------------------------------------------------------- -class LLPolySkeletalDistortion : public LLViewerVisualParam -{ -public: - LLPolySkeletalDistortion(LLVOAvatar *avatarp); - ~LLPolySkeletalDistortion(); - - // Special: These functions are overridden by child classes - LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLPolySkeletalDistortionInfo *info); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex sex ); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } - /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; - -protected: - typedef std::map joint_vec_map_t; - joint_vec_map_t mJointScales; - joint_vec_map_t mJointOffsets; - LLVector4a mDefaultVec; - // Backlink only; don't make this an LLPointer. - LLVOAvatar *mAvatar; -}; - -#endif // LL_LLPOLYMESH_H - diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index 46e23b7792..28d7755d4d 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -35,7 +35,7 @@ class LLPolyMeshSharedData; class LLVOAvatar; class LLVector2; -class LLViewerJointCollisionVolume; +class LLAvatarJointCollisionVolume; class LLWearable; //----------------------------------------------------------------------------- @@ -104,10 +104,10 @@ struct LLPolyVolumeMorphInfo struct LLPolyVolumeMorph { - LLPolyVolumeMorph(LLViewerJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) + LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) : mVolume(volume), mScale(scale), mPos(pos) {}; - LLViewerJointCollisionVolume* mVolume; + LLAvatarJointCollisionVolume* mVolume; LLVector3 mScale; LLVector3 mPos; }; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index c804898cc3..fadaaf4541 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4028,7 +4028,7 @@ void renderAgentTarget(LLVOAvatar* avatar) { renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); + renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6782e3ef8a..ab06b1f5aa 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1247,6 +1247,9 @@ bool idle_startup() LLPostProcess::initClass(); display_startup(); + LLAvatarAppearance::initClass(); + display_startup(); + LLViewerObject::initVOClasses(); display_startup(); diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index a907f102f8..bb45cf89fc 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -53,7 +53,7 @@ BOOL LLViewerJoint::sDisableLOD = FALSE; // Class Constructor //----------------------------------------------------------------------------- LLViewerJoint::LLViewerJoint() - : LLJoint() + : LLAvatarJoint() { init(); } @@ -64,7 +64,7 @@ LLViewerJoint::LLViewerJoint() // Class Constructor //----------------------------------------------------------------------------- LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) - : LLJoint(name, parent) + : LLAvatarJoint(name, parent) { init(); } @@ -90,31 +90,6 @@ LLViewerJoint::~LLViewerJoint() } -//-------------------------------------------------------------------- -// setValid() -//-------------------------------------------------------------------- -void LLViewerJoint::setValid( BOOL valid, BOOL recursive ) -{ - //---------------------------------------------------------------- - // set visibility for this joint - //---------------------------------------------------------------- - mValid = valid; - - //---------------------------------------------------------------- - // set visibility for children - //---------------------------------------------------------------- - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setValid(valid, TRUE); - } - } - -} - //-------------------------------------------------------------------- // renderSkeleton() // DEBUG (UNUSED) @@ -522,98 +497,6 @@ void LLViewerJoint::setMeshesToChildren() addChild((LLViewerJointMesh *) *iter); } } -//----------------------------------------------------------------------------- -// LLViewerJointCollisionVolume() -//----------------------------------------------------------------------------- - -LLViewerJointCollisionVolume::LLViewerJointCollisionVolume() -{ - mUpdateXform = FALSE; -} -LLViewerJointCollisionVolume::LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent) : LLViewerJoint(name, parent) -{ - -} - -void LLViewerJointCollisionVolume::renderCollision() -{ - updateWorldMatrix(); - - gGL.pushMatrix(); - gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); - - gGL.diffuseColor3f( 0.f, 0.f, 1.f ); - - gGL.begin(LLRender::LINES); - - LLVector3 v[] = - { - LLVector3(1,0,0), - LLVector3(-1,0,0), - LLVector3(0,1,0), - LLVector3(0,-1,0), - - LLVector3(0,0,-1), - LLVector3(0,0,1), - }; - - //sides - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[3].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[3].mV); - - - //top - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[4].mV); - - - //bottom - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[5].mV); - - gGL.end(); - - gGL.popMatrix(); -} - -LLVector3 LLViewerJointCollisionVolume::getVolumePos(LLVector3 &offset) -{ - mUpdateXform = TRUE; - - LLVector3 result = offset; - result.scaleVec(getScale()); - result.rotVec(getWorldRotation()); - result += getWorldPosition(); - - return result; -} // End diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 531c0f765c..37c80dafeb 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -30,7 +30,7 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include "lljoint.h" +#include "llavatarjoint.h" #include "lljointpickname.h" class LLFace; @@ -40,7 +40,7 @@ class LLViewerJointMesh; // class LLViewerJoint //----------------------------------------------------------------------------- class LLViewerJoint : - public LLJoint + public LLAvatarJoint { public: LLViewerJoint(); @@ -50,9 +50,6 @@ public: // Gets the validity of this joint BOOL getValid() { return mValid; } - // Sets the validity of this joint - virtual void setValid( BOOL valid, BOOL recursive=FALSE ); - // Primarily for debugging and character setup // Derived classes may add text/graphic output. // Draw skeleton graphic for debugging and character setup @@ -134,19 +131,6 @@ protected: S32 mMeshID; }; -class LLViewerJointCollisionVolume : public LLViewerJoint -{ -public: - LLViewerJointCollisionVolume(); - LLViewerJointCollisionVolume(const std::string &name, LLJoint *parent = NULL); - virtual ~LLViewerJointCollisionVolume() {}; - - virtual BOOL inheritScale() { return TRUE; } - - void renderCollision(); - LLVector3 getVolumePos(LLVector3 &offset); -}; - #endif // LL_LLVIEWERJOINT_H diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 3532fac1bc..8d479ab0bf 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -67,101 +67,20 @@ static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLViewerJointMesh::LLSkinJoint -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::LLSkinJoint() -{ - mJoint = NULL; -} - -//----------------------------------------------------------------------------- -// ~LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::~LLSkinJoint() -{ - mJoint = NULL; -} - - -//----------------------------------------------------------------------------- -// LLSkinJoint::setupSkinJoint() -//----------------------------------------------------------------------------- -BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint) -{ - // find the named joint - mJoint = joint; - if ( !mJoint ) - { - llinfos << "Can't find joint" << llendl; - } - - // compute the inverse root skin matrix - mRootToJointSkinOffset.clearVec(); - - LLVector3 rootSkinOffset; - while (joint) - { - rootSkinOffset += joint->getSkinOffset(); - joint = (LLViewerJoint*)joint->getParent(); - } - - mRootToJointSkinOffset = -rootSkinOffset; - mRootToParentJointSkinOffset = mRootToJointSkinOffset; - mRootToParentJointSkinOffset += mJoint->getSkinOffset(); - - return TRUE; -} - - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLViewerJointMesh //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -BOOL LLViewerJointMesh::sPipelineRender = FALSE; -EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; -U32 LLViewerJointMesh::sClothingMaskImageName = 0; -LLColor4 LLViewerJointMesh::sClothingInnerColor; //----------------------------------------------------------------------------- // LLViewerJointMesh() //----------------------------------------------------------------------------- LLViewerJointMesh::LLViewerJointMesh() : - mTexture( NULL ), - mLayerSet( NULL ), - mTestImageName( 0 ), - mFaceIndexCount(0), - mIsTransparent(FALSE) + LLAvatarJointMesh() { - - mColor[0] = 1.0f; - mColor[1] = 1.0f; - mColor[2] = 1.0f; - mColor[3] = 1.0f; - mShiny = 0.0f; - mCullBackFaces = TRUE; - - mMesh = NULL; - - mNumSkinJoints = 0; - mSkinJoints = NULL; - - mFace = NULL; - - mMeshID = 0; - mUpdateXform = FALSE; - - mValid = FALSE; } @@ -171,199 +90,6 @@ LLViewerJointMesh::LLViewerJointMesh() //----------------------------------------------------------------------------- LLViewerJointMesh::~LLViewerJointMesh() { - mMesh = NULL; - mTexture = NULL; - freeSkinData(); -} - - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::allocateSkinData() -//----------------------------------------------------------------------------- -BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints ) -{ - mSkinJoints = new LLSkinJoint[ numSkinJoints ]; - mNumSkinJoints = numSkinJoints; - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::freeSkinData() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::freeSkinData() -{ - mNumSkinJoints = 0; - delete [] mSkinJoints; - mSkinJoints = NULL; -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getColor() -//-------------------------------------------------------------------- -void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) -{ - *red = mColor[0]; - *green = mColor[1]; - *blue = mColor[2]; - *alpha = mColor[3]; -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setColor() -//-------------------------------------------------------------------- -void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) -{ - mColor[0] = red; - mColor[1] = green; - mColor[2] = blue; - mColor[3] = alpha; -} - - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getTexture() -//-------------------------------------------------------------------- -//LLViewerTexture *LLViewerJointMesh::getTexture() -//{ -// return mTexture; -//} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setTexture() -//-------------------------------------------------------------------- -void LLViewerJointMesh::setTexture( LLViewerTexture *texture ) -{ - mTexture = texture; - - // texture and dynamic_texture are mutually exclusive - if( texture ) - { - mLayerSet = NULL; - //texture->bindTexture(0); - //texture->setClamp(TRUE, TRUE); - } -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::setLayerSet() -// Sets the shape texture (takes precedence over normal texture) -//-------------------------------------------------------------------- -void LLViewerJointMesh::setLayerSet( LLViewerTexLayerSet* layer_set ) -{ - mLayerSet = layer_set; - - // texture and dynamic_texture are mutually exclusive - if( layer_set ) - { - mTexture = NULL; - } -} - - - -//-------------------------------------------------------------------- -// LLViewerJointMesh::getMesh() -//-------------------------------------------------------------------- -LLPolyMesh *LLViewerJointMesh::getMesh() -{ - return mMesh; -} - -//----------------------------------------------------------------------------- -// LLViewerJointMesh::setMesh() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::setMesh( LLPolyMesh *mesh ) -{ - // set the mesh pointer - mMesh = mesh; - - // release any existing skin joints - freeSkinData(); - - if ( mMesh == NULL ) - { - return; - } - - // acquire the transform from the mesh object - setPosition( mMesh->getPosition() ); - setRotation( mMesh->getRotation() ); - setScale( mMesh->getScale() ); - - // create skin joints if necessary - if ( mMesh->hasWeights() && !mMesh->isLOD()) - { - U32 numJointNames = mMesh->getNumJointNames(); - - allocateSkinData( numJointNames ); - std::string *jointNames = mMesh->getJointNames(); - - U32 jn; - for (jn = 0; jn < numJointNames; jn++) - { - //llinfos << "Setting up joint " << jointNames[jn] << llendl; - LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) ); - mSkinJoints[jn].setupSkinJoint( joint ); - } - } - - // setup joint array - if (!mMesh->isLOD()) - { - setupJoint((LLViewerJoint*)getRoot()); - } - -// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl; -} - -//----------------------------------------------------------------------------- -// setupJoint() -//----------------------------------------------------------------------------- -void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint) -{ -// llinfos << "Mesh: " << getName() << llendl; - -// S32 joint_count = 0; - U32 sj; - for (sj=0; sjmJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix()) - { - // ...then just add ourselves - LLViewerJoint* jointp = js.mJoint; - mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); -// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl; -// joint_count++; - } - // otherwise add our parent and ourselves - else - { - mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL)); -// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl; -// joint_count++; - mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); -// llinfos << "joint " << joint_count << current_joint->getName() << llendl; -// joint_count++; - } - } - - // depth-first traversal - for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); - iter != current_joint->mChildren.end(); ++iter) - { - LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); - setupJoint(child_joint); - } } const S32 NUM_AXES = 3; @@ -544,6 +270,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; + LLViewerTexLayerSet *layerset = dynamic_cast(mLayerSet); if (mTestImageName) { gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); @@ -558,11 +285,11 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } - else if( !is_dummy && mLayerSet ) + else if( !is_dummy && layerset ) { - if( mLayerSet->hasComposite() ) + if( layerset->hasComposite() ) { - gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getViewerComposite()); + gGL.getTexUnit(diffuse_channel)->bind(layerset->getViewerComposite()); } else { diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index ff6bed4f0f..039175830f 100755 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -29,6 +29,7 @@ #include "llviewerjoint.h" #include "llviewertexture.h" +#include "llavatarjointmesh.h" #include "llpolymesh.h" #include "v4color.h" @@ -37,56 +38,12 @@ class LLFace; class LLCharacter; class LLViewerTexLayerSet; -typedef enum e_avatar_render_pass -{ - AVATAR_RENDER_PASS_SINGLE, - AVATAR_RENDER_PASS_CLOTHING_INNER, - AVATAR_RENDER_PASS_CLOTHING_OUTER -} EAvatarRenderPass; - -class LLSkinJoint -{ -public: - LLSkinJoint(); - ~LLSkinJoint(); - BOOL setupSkinJoint( LLViewerJoint *joint); - - LLViewerJoint *mJoint; - LLVector3 mRootToJointSkinOffset; - LLVector3 mRootToParentJointSkinOffset; -}; - //----------------------------------------------------------------------------- // class LLViewerJointMesh //----------------------------------------------------------------------------- -class LLViewerJointMesh : public LLViewerJoint +class LLViewerJointMesh : public LLAvatarJointMesh { friend class LLVOAvatar; -protected: - LLColor4 mColor; // color value -// LLColor4 mSpecular; // specular color (always white for now) - F32 mShiny; // shiny value - LLPointer mTexture; // ptr to a global texture - LLViewerTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar - U32 mTestImageName; // handle to a temporary texture for previewing uploads - LLPolyMesh* mMesh; // ptr to a global polymesh - BOOL mCullBackFaces; // true by default - LLFace* mFace; // ptr to a face w/ AGP copy of mesh - - U32 mFaceIndexCount; - BOOL mIsTransparent; - - U32 mNumSkinJoints; - LLSkinJoint* mSkinJoints; - S32 mMeshID; - -public: - static BOOL sPipelineRender; - //RN: this is here for testing purposes - static U32 sClothingMaskImageName; - static EAvatarRenderPass sRenderPass; - static LLColor4 sClothingInnerColor; - public: // Constructor LLViewerJointMesh(); @@ -94,41 +51,9 @@ public: // Destructor virtual ~LLViewerJointMesh(); - // Gets the shape color - void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); - - // Sets the shape color - void setColor( F32 red, F32 green, F32 blue, F32 alpha ); - - // Sets the shininess - void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; - - // Sets the shape texture - void setTexture( LLViewerTexture *texture ); - - void setTestTexture( U32 name ) { mTestImageName = name; } - - // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) - void setLayerSet( LLViewerTexLayerSet* layer_set ); - - // Gets the poly mesh - LLPolyMesh *getMesh(); - - // Sets the poly mesh - void setMesh( LLPolyMesh *mesh ); - - // Sets up joint matrix data for rendering - void setupJoint(LLViewerJoint* current_joint); - // Render time method to upload batches of joint matrices void uploadJointMatrices(); - // Sets ID for picking - void setMeshID( S32 id ) {mMeshID = id;} - - // Gets ID for picking - S32 getMeshID() { return mMeshID; } - // overloaded from base class /*virtual*/ void drawBone(); /*virtual*/ BOOL isTransparent(); @@ -148,13 +73,6 @@ private: //copy mesh into given face's vertex buffer, applying current animation pose static void updateGeometry(LLFace* face, LLPolyMesh* mesh); - -private: - // Allocate skin data - BOOL allocateSkinData( U32 numSkinJoints ); - - // Free skin data - void freeSkinData(); }; #endif // LL_LLVIEWERJOINTMESH_H diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d5ca01931f..8fc5a3f277 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -382,7 +382,7 @@ public: if (isAgentAvatarValid()) { - tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition()); + tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); agent_root_center_text = llformat("AgentRootCenter %f %f %f", (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f6cac6d2d6..f0f469e959 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -139,7 +139,6 @@ const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df44 //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- -const std::string AVATAR_DEFAULT_CHAR = "avatar"; const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; const F32 SHADOW_OFFSET_AMT = 0.03f; @@ -220,58 +219,6 @@ struct LLTextureMaskData ** **/ -//------------------------------------------------------------------------ -// LLVOBoneInfo -// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. -//------------------------------------------------------------------------ -class LLVOAvatarBoneInfo -{ - friend class LLVOAvatar; - friend class LLVOAvatarSkeletonInfo; -public: - LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} - ~LLVOAvatarBoneInfo() - { - std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - -private: - std::string mName; - BOOL mIsJoint; - LLVector3 mPos; - LLVector3 mRot; - LLVector3 mScale; - LLVector3 mPivot; - typedef std::vector child_list_t; - child_list_t mChildList; -}; - -//------------------------------------------------------------------------ -// LLVOAvatarSkeletonInfo -// Overall avatar skeleton -//------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo -{ - friend class LLVOAvatar; -public: - LLVOAvatarSkeletonInfo() : - mNumBones(0), mNumCollisionVolumes(0) {} - ~LLVOAvatarSkeletonInfo() - { - std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - S32 getNumBones() const { return mNumBones; } - S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } - -private: - S32 mNumBones; - S32 mNumCollisionVolumes; - typedef std::vector bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - //----------------------------------------------------------------------------- // class LLBodyNoiseMotion //----------------------------------------------------------------------------- @@ -593,10 +540,6 @@ private: //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; -LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; -LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; U32 LLVOAvatar::sMaxVisible = 12; @@ -650,9 +593,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mAttachmentGeometryBytes(0), mAttachmentSurfaceArea(0.f), mTurning(FALSE), - mPelvisToFoot(0.f), mLastSkeletonSerialNum( 0 ), - mHeadOffset(), mIsSitting(FALSE), mTimeVisible(), mTyping(FALSE), @@ -707,13 +648,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mMeshTexturesDirty = FALSE; mHeadp = NULL; - mIsBuilt = FALSE; - - mNumJoints = 0; - mSkeleton = NULL; - - mNumCollisionVolumes = 0; - mCollisionVolumes = NULL; // set up animation variables mSpeed = 0.f; @@ -802,35 +736,9 @@ LLVOAvatar::~LLVOAvatar() lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; - mRoot.removeAllChildren(); - mJointMap.clear(); - - deleteAndClearArray(mSkeleton); - deleteAndClearArray(mCollisionVolumes); - - mNumJoints = 0; - std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); mAttachmentPoints.clear(); - deleteAndClear(mTexSkinColor); - deleteAndClear(mTexHairColor); - deleteAndClear(mTexEyeColor); - - std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); - mMeshes.clear(); - - for (std::vector::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); - ++jointIter) - { - LLViewerJoint* joint = (LLViewerJoint *) *jointIter; - std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); - joint->mMeshParts.clear(); - } - std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); - mMeshLOD.clear(); - mDead = TRUE; mAnimationSources.clear(); @@ -1127,109 +1035,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) //------------------------------------------------------------------------ void LLVOAvatar::initClass() { - std::string xmlFile; - - xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; - BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); - if (!success) - { - llerrs << "Problem reading avatar configuration file:" << xmlFile << llendl; - } - - // now sanity check xml file - LLXmlTreeNode* root = sXMLTree.getRoot(); - if (!root) - { - llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; - return; - } - - //------------------------------------------------------------------------- - // (root) - //------------------------------------------------------------------------- - if( !root->hasName( "linden_avatar" ) ) - { - llerrs << "Invalid avatar file header: " << xmlFile << llendl; - } - - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) - { - llerrs << "Invalid avatar file version: " << version << " in file: " << xmlFile << llendl; - } - - S32 wearable_def_version = 1; - static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); - root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); - LLWearable::setCurrentDefinitionVersion( wearable_def_version ); - - std::string mesh_file_name; - - LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); - if (!skeleton_node) - { - llerrs << "No skeleton in avatar configuration file: " << xmlFile << llendl; - return; - } - - std::string skeleton_file_name; - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) - { - llerrs << "No file name in skeleton node in avatar config file: " << xmlFile << llendl; - } - - std::string skeleton_path; - skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); - if (!parseSkeletonFile(skeleton_path)) - { - llerrs << "Error parsing skeleton file: " << skeleton_path << llendl; - } - - // Process XML data - - // avatar_skeleton.xml - if (sAvatarSkeletonInfo) - { //this can happen if a login attempt failed - delete sAvatarSkeletonInfo; - } - sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; - if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) - { - llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; - } - // parse avatar_lad.xml - if (sAvatarXmlInfo) - { //this can happen if a login attempt failed - deleteAndClear(sAvatarXmlInfo); - } - sAvatarXmlInfo = new LLVOAvatarXmlInfo; - if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlColorNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) - { - llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; - } - gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise"); gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot"); gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion"); @@ -1256,7 +1061,12 @@ void LLVOAvatar::initInstance(void) //------------------------------------------------------------------------- // initialize joint, mesh and shape members //------------------------------------------------------------------------- - mRoot.setName( "mRoot" ); + if (mRoot) + { + delete mRoot; + } + mRoot = new LLViewerJoint(); + mRoot->setName( "mRoot" ); for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); @@ -1314,7 +1124,7 @@ void LLVOAvatar::initInstance(void) // Skip it if there's no associated baked texture. if (baked_texture_index == BAKED_NUM_INDICES) continue; - for (std::vector::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); + for (std::vector::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); iter != mMeshLOD[mesh_index]->mMeshParts.end(); ++iter) { @@ -1707,160 +1517,6 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector return hit; } -//----------------------------------------------------------------------------- -// parseSkeletonFile() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) -{ - LLMemType mt(LLMemType::MTYPE_AVATAR); - - //------------------------------------------------------------------------- - // parse the file - //------------------------------------------------------------------------- - BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); - - if (!parsesuccess) - { - llerrs << "Can't parse skeleton file: " << filename << llendl; - return FALSE; - } - - // now sanity check xml file - LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); - if (!root) - { - llerrs << "No root node found in avatar skeleton file: " << filename << llendl; - return FALSE; - } - - if( !root->hasName( "linden_skeleton" ) ) - { - llerrs << "Invalid avatar skeleton file header: " << filename << llendl; - return FALSE; - } - - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) - { - llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; - return FALSE; - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) -{ - LLMemType mt(LLMemType::MTYPE_AVATAR); - - LLViewerJoint* joint = NULL; - - if (info->mIsJoint) - { - joint = (LLViewerJoint*)getCharacterJoint(joint_num); - if (!joint) - { - llwarns << "Too many bones" << llendl; - return FALSE; - } - joint->setName( info->mName ); - } - else // collision volume - { - if (volume_num >= (S32)mNumCollisionVolumes) - { - llwarns << "Too many bones" << llendl; - return FALSE; - } - joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); - joint->setName( info->mName ); - } - - // add to parent - if (parent) - { - parent->addChild( joint ); - } - - joint->setPosition(info->mPos); - joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], - info->mRot.mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info->mScale); - - joint->setDefaultFromCurrentXform(); - - if (info->mIsJoint) - { - joint->setSkinOffset( info->mPivot ); - joint_num++; - } - else // collision volume - { - volume_num++; - } - - // setup children - LLVOAvatarBoneInfo::child_list_t::const_iterator iter; - for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) - { - LLVOAvatarBoneInfo *child_info = *iter; - if (!setupBone(child_info, joint, volume_num, joint_num)) - { - return FALSE; - } - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// buildSkeleton() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) -{ - LLMemType mt(LLMemType::MTYPE_AVATAR); - - //------------------------------------------------------------------------- - // allocate joints - //------------------------------------------------------------------------- - if (!allocateCharacterJoints(info->mNumBones)) - { - llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; - return FALSE; - } - - //------------------------------------------------------------------------- - // allocate volumes - //------------------------------------------------------------------------- - if (info->mNumCollisionVolumes) - { - if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) - { - llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; - return FALSE; - } - } - - S32 current_joint_num = 0; - S32 current_volume_num = 0; - LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; - for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) - { - LLVOAvatarBoneInfo *info = *iter; - if (!setupBone(info, NULL, current_volume_num, current_joint_num)) - { - llerrs << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } - } - - return TRUE; -} - LLVOAvatar* LLVOAvatar::asAvatar() { return this; @@ -1892,27 +1548,13 @@ void LLVOAvatar::startDefaultMotions() // LLVOAvatar::buildCharacter() // Deferred initialization and rebuild of the avatar. //----------------------------------------------------------------------------- +// virtual void LLVOAvatar::buildCharacter() { - LLMemType mt(LLMemType::MTYPE_AVATAR); - - //------------------------------------------------------------------------- - // remove all references to our existing skeleton - // so we can rebuild it - //------------------------------------------------------------------------- - flushAllMotions(); - - //------------------------------------------------------------------------- - // remove all of mRoot's children - //------------------------------------------------------------------------- - mRoot.removeAllChildren(); - mJointMap.clear(); - mIsBuilt = FALSE; - //------------------------------------------------------------------------- // clear mesh data //------------------------------------------------------------------------- - for (std::vector::iterator jointIter = mMeshLOD.begin(); + for (std::vector::iterator jointIter = mMeshLOD.begin(); jointIter != mMeshLOD.end(); ++jointIter) { LLViewerJoint* joint = (LLViewerJoint*) *jointIter; @@ -1924,83 +1566,8 @@ void LLVOAvatar::buildCharacter() } } - //------------------------------------------------------------------------- - // (re)load our skeleton and meshes - //------------------------------------------------------------------------- - LLTimer timer; - - BOOL status = loadAvatar(); - stop_glerror(); - -// gPrintMessagesThisFrame = TRUE; - lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; - - if (!status) - { - if (isSelf()) - { - llerrs << "Unable to load user's avatar" << llendl; - } - else - { - llwarns << "Unable to load other's avatar" << llendl; - } - return; - } - - //------------------------------------------------------------------------- - // initialize "well known" joint pointers - //------------------------------------------------------------------------- - mPelvisp = (LLViewerJoint*)mRoot.findJoint("mPelvis"); - mTorsop = (LLViewerJoint*)mRoot.findJoint("mTorso"); - mChestp = (LLViewerJoint*)mRoot.findJoint("mChest"); - mNeckp = (LLViewerJoint*)mRoot.findJoint("mNeck"); - mHeadp = (LLViewerJoint*)mRoot.findJoint("mHead"); - mSkullp = (LLViewerJoint*)mRoot.findJoint("mSkull"); - mHipLeftp = (LLViewerJoint*)mRoot.findJoint("mHipLeft"); - mHipRightp = (LLViewerJoint*)mRoot.findJoint("mHipRight"); - mKneeLeftp = (LLViewerJoint*)mRoot.findJoint("mKneeLeft"); - mKneeRightp = (LLViewerJoint*)mRoot.findJoint("mKneeRight"); - mAnkleLeftp = (LLViewerJoint*)mRoot.findJoint("mAnkleLeft"); - mAnkleRightp = (LLViewerJoint*)mRoot.findJoint("mAnkleRight"); - mFootLeftp = (LLViewerJoint*)mRoot.findJoint("mFootLeft"); - mFootRightp = (LLViewerJoint*)mRoot.findJoint("mFootRight"); - mWristLeftp = (LLViewerJoint*)mRoot.findJoint("mWristLeft"); - mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight"); - mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); - mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); - - //------------------------------------------------------------------------- - // Make sure "well known" pointers exist - //------------------------------------------------------------------------- - if (!(mPelvisp && - mTorsop && - mChestp && - mNeckp && - mHeadp && - mSkullp && - mHipLeftp && - mHipRightp && - mKneeLeftp && - mKneeRightp && - mAnkleLeftp && - mAnkleRightp && - mFootLeftp && - mFootRightp && - mWristLeftp && - mWristRightp && - mEyeLeftp && - mEyeRightp)) - { - llerrs << "Failed to create avatar." << llendl; - return; - } + LLAvatarAppearance::buildCharacter(); - //------------------------------------------------------------------------- - // initialize the pelvis - //------------------------------------------------------------------------- - mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); - //------------------------------------------------------------------------- // set head offset from pelvis //------------------------------------------------------------------------- @@ -2033,9 +1600,6 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- processAnimationStateChanges(); - mIsBuilt = TRUE; - stop_glerror(); - mMeshValid = TRUE; } @@ -2055,7 +1619,7 @@ void LLVOAvatar::releaseMeshData() //llinfos << "Releasing" << llendl; // cleanup mesh data - for (std::vector::iterator iter = mMeshLOD.begin(); + for (std::vector::iterator iter = mMeshLOD.begin(); iter != mMeshLOD.end(); ++iter) { @@ -2149,7 +1713,11 @@ void LLVOAvatar::updateMeshData() last_v_num = num_vertices ; last_i_num = num_indices ; - mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + LLViewerJoint* part_mesh = getViewerJoint(part_index++); + if (part_mesh) + { + part_mesh->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + } } if(num_vertices < 1)//skip empty meshes { @@ -2223,7 +1791,11 @@ void LLVOAvatar::updateMeshData() rigid = true; } - mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); + LLViewerJoint* mesh = getViewerJoint(k); + if (mesh) + { + mesh->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); + } } stop_glerror(); @@ -2243,72 +1815,6 @@ void LLVOAvatar::updateMeshData() //------------------------------------------------------------------------ -//------------------------------------------------------------------------ -// The viewer can only suggest a good size for the agent, -// the simulator will keep it inside a reasonable range. -void LLVOAvatar::computeBodySize() -{ - LLVector3 pelvis_scale = mPelvisp->getScale(); - - // some of the joints have not been cached - LLVector3 skull = mSkullp->getPosition(); - LLVector3 skull_scale = mSkullp->getScale(); - - LLVector3 neck = mNeckp->getPosition(); - LLVector3 neck_scale = mNeckp->getScale(); - - LLVector3 chest = mChestp->getPosition(); - LLVector3 chest_scale = mChestp->getScale(); - - // the rest of the joints have been cached - LLVector3 head = mHeadp->getPosition(); - LLVector3 head_scale = mHeadp->getScale(); - - LLVector3 torso = mTorsop->getPosition(); - LLVector3 torso_scale = mTorsop->getScale(); - - LLVector3 hip = mHipLeftp->getPosition(); - LLVector3 hip_scale = mHipLeftp->getScale(); - - LLVector3 knee = mKneeLeftp->getPosition(); - LLVector3 knee_scale = mKneeLeftp->getScale(); - - LLVector3 ankle = mAnkleLeftp->getPosition(); - LLVector3 ankle_scale = mAnkleLeftp->getScale(); - - LLVector3 foot = mFootLeftp->getPosition(); - - mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - - knee.mV[VZ] * hip_scale.mV[VZ] - - ankle.mV[VZ] * knee_scale.mV[VZ] - - foot.mV[VZ] * ankle_scale.mV[VZ]; - - LLVector3 new_body_size; - new_body_size.mV[VZ] = mPelvisToFoot + - // the sqrt(2) correction below is an approximate - // correction to get to the top of the head - F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + - head.mV[VZ] * neck_scale.mV[VZ] + - neck.mV[VZ] * chest_scale.mV[VZ] + - chest.mV[VZ] * torso_scale.mV[VZ] + - torso.mV[VZ] * pelvis_scale.mV[VZ]; - - // TODO -- measure the real depth and width - new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; - new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; - - if (new_body_size != mBodySize) - { - mBodySize = new_body_size; - - if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF()) - { // notify simulator of change in size - // but not if we are in the middle of updating appearance - gAgent.sendAgentSetAppearance(); - } - } -} - //------------------------------------------------------------------------ // LLVOAvatar::processUpdateMessage() //------------------------------------------------------------------------ @@ -2478,7 +1984,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // animate the character // store off last frame's root position to be consistent with camera position - LLVector3 root_pos_last = mRoot.getWorldPosition(); + LLVector3 root_pos_last = mRoot->getWorldPosition(); BOOL detailed_update = updateCharacter(agent); static LLUICachedControl visualizers_in_calls("ShowVoiceVisualizersInCalls", false); @@ -2597,11 +2103,11 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) if ( mIsSitting ) { LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); - mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); + mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot->getWorldPosition() + headOffset ); } else { - LLVector3 tagPos = mRoot.getWorldPosition(); + LLVector3 tagPos = mRoot->getWorldPosition(); tagPos[VZ] -= mPelvisToFoot; tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); @@ -3338,7 +2844,7 @@ void LLVOAvatar::invalidateNameTags() // Compute name tag position during idle update LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) { - LLQuaternion root_rot = mRoot.getWorldRotation(); + LLQuaternion root_rot = mRoot->getWorldRotation(); LLVector3 pixel_right_vec; LLVector3 pixel_up_vec; LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); @@ -3352,7 +2858,7 @@ LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) local_camera_up.scaleVec(mBodySize * 0.5f); local_camera_at.scaleVec(mBodySize * 0.5f); - LLVector3 name_position = mRoot.getWorldPosition(); + LLVector3 name_position = mRoot->getWorldPosition(); name_position[VZ] -= mPelvisToFoot; name_position[VZ] += (mBodySize[VZ]* 0.55f); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); @@ -3417,13 +2923,13 @@ void LLVOAvatar::idleUpdateBelowWater() void LLVOAvatar::slamPosition() { gAgent.setPositionAgent(getPositionAgent()); - mRoot.setWorldPosition(getPositionAgent()); // teleport + mRoot->setWorldPosition(getPositionAgent()); // teleport setChanged(TRANSLATED); if (mDrawable.notNull()) { gPipeline.updateMoveNormalAsync(mDrawable); } - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); } bool LLVOAvatar::isVisuallyMuted() const @@ -3600,8 +3106,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) throttle = FALSE; // put the pelvis at slaved position/mRotation - mRoot.setWorldPosition( getPositionAgent() ); // first frame - mRoot.setWorldRotation( getRotation() ); + mRoot->setWorldPosition( getPositionAgent() ); // first frame + mRoot->setWorldRotation( getRotation() ); } //-------------------------------------------------------------------- @@ -3644,10 +3150,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); - if (newPosition != mRoot.getXform()->getWorldPosition()) + if (newPosition != mRoot->getXform()->getWorldPosition()) { - mRoot.touch(); - mRoot.setWorldPosition( newPosition ); // regular update + mRoot->touch(); + mRoot->setWorldPosition( newPosition ); // regular update } @@ -3708,7 +3214,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } - LLQuaternion root_rotation = mRoot.getWorldMatrix().quaternion(); + LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion(); F32 root_roll, root_pitch, root_yaw; root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); @@ -3717,7 +3223,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // and head turn. Once in motion, it must conform however. BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); - LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV ); + LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV ); static LLCachedControl s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow"); static LLCachedControl s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast"); @@ -3803,14 +3309,14 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); - mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) ); + mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); } } else if (mDrawable.notNull()) { - mRoot.setPosition(mDrawable->getPosition()); - mRoot.setRotation(mDrawable->getRotation()); + mRoot->setPosition(mDrawable->getPosition()); + mRoot->setRotation(mDrawable->getRotation()); } //------------------------------------------------------------------------- @@ -3910,7 +3416,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); if (!mDebugText.size() && mText.notNull()) { @@ -3934,7 +3440,7 @@ void LLVOAvatar::updateHeadOffset() { // since we only care about Z, just grab one of the eyes LLVector3 midEyePt = mEyeLeftp->getWorldPosition(); - midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot.getWorldPosition(); + midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot->getWorldPosition(); midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]); if (mDrawable.notNull()) @@ -3972,8 +3478,8 @@ void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, void LLVOAvatar::postPelvisSetRecalc( void ) { computeBodySize(); - mRoot.touch(); - mRoot.updateWorldMatrixChildren(); + mRoot->touch(); + mRoot->updateWorldMatrixChildren(); dirtyMesh(); updateHeadOffset(); } @@ -4207,19 +3713,44 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (mNeedsSkin) { //generate animated mesh - mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry(); - mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry(); + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + + if(upper_mesh) + { + upper_mesh->updateJointGeometry(); + } + if (lower_mesh) + { + lower_mesh->updateJointGeometry(); + } if( isWearingWearableType( LLWearableType::WT_SKIRT ) ) { - mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry(); + if(skirt_mesh) + { + skirt_mesh->updateJointGeometry(); + } } if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry(); - mMeshLOD[MESH_ID_HEAD]->updateJointGeometry(); - mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); + if(eyelash_mesh) + { + eyelash_mesh->updateJointGeometry(); + } + if(head_mesh) + { + head_mesh->updateJointGeometry(); + } + if(hair_mesh) + { + hair_mesh->updateJointGeometry(); + } } mNeedsSkin = FALSE; mLastSkinTime = gFrameTimeSeconds; @@ -4336,19 +3867,31 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy); + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + if (head_mesh) + { + num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); + } first_pass = FALSE; } } if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + if (upper_mesh) + { + num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + if (lower_mesh) + { + num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } } @@ -4381,7 +3924,11 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); - num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE); + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + if (skirt_mesh) + { + num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE); + } first_pass = FALSE; gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } @@ -4395,14 +3942,22 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) if (isTextureVisible(TEX_HEAD_BAKED)) { - num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + if (eyelash_mesh) + { + num_indices += eyelash_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } // Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair) // TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha) { - num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy); + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } first_pass = FALSE; } if (LLPipeline::sImpostorRender) @@ -4446,8 +4001,16 @@ U32 LLVOAvatar::renderRigid() if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy) { - num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy); - num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy); + LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); + LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); + if (eyeball_left) + { + num_indices += eyeball_left->render(mAdjustedPixelArea, TRUE, mIsDummy); + } + if(eyeball_right) + { + num_indices += eyeball_right->render(mAdjustedPixelArea, TRUE, mIsDummy); + } } if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) @@ -5139,7 +4702,7 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) if (iter == mJointMap.end() || iter->second == NULL) { //search for joint and cache found joint in lookup table - jointp = mRoot.findJoint(name); + jointp = mRoot->findJoint(name); mJointMap[name] = jointp; } else @@ -5168,7 +4731,7 @@ void LLVOAvatar::resetJointPositions( void ) //----------------------------------------------------------------------------- void LLVOAvatar::resetSpecificJointPosition( const std::string& name ) { - LLJoint* pJoint = mRoot.findJoint( name ); + LLJoint* pJoint = mRoot->findJoint( name ); if ( pJoint && pJoint->doesJointNeedToBeReset() ) { @@ -5356,23 +4919,6 @@ BOOL LLVOAvatar::allocateCharacterJoints( U32 num ) return TRUE; } -//----------------------------------------------------------------------------- -// allocateCollisionVolumes() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::allocateCollisionVolumes( U32 num ) -{ - deleteAndClearArray(mCollisionVolumes); - mNumCollisionVolumes = 0; - - mCollisionVolumes = new LLViewerJointCollisionVolume[num]; - if (!mCollisionVolumes) - { - return FALSE; - } - - mNumCollisionVolumes = num; - return TRUE; -} //----------------------------------------------------------------------------- @@ -5397,154 +4943,14 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion ) // Only agent avatars should handle the stop motion notifications. } -//----------------------------------------------------------------------------- -// loadAvatar() -//----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar"); - -BOOL LLVOAvatar::loadAvatar() -{ -// LLFastTimer t(FTM_LOAD_AVATAR); - - // avatar_skeleton.xml - if( !buildSkeleton(sAvatarSkeletonInfo) ) - { - llwarns << "avatar file: buildSkeleton() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : - if( !loadSkeletonNode() ) - { - llwarns << "avatar file: loadNodeSkeleton() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : - if( !loadMeshNodes() ) - { - llwarns << "avatar file: loadNodeMesh() failed" << llendl; - return FALSE; - } - - // avatar_lad.xml : - if( sAvatarXmlInfo->mTexSkinColorInfo ) - { - mTexSkinColor = new LLTexGlobalColor( this ); - if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) - { - llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << " name=\"skin_color\" not found" << llendl; - return FALSE; - } - if( sAvatarXmlInfo->mTexHairColorInfo ) - { - mTexHairColor = new LLTexGlobalColor( this ); - if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) - { - llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << " name=\"hair_color\" not found" << llendl; - return FALSE; - } - if( sAvatarXmlInfo->mTexEyeColorInfo ) - { - mTexEyeColor = new LLTexGlobalColor( this ); - if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) - { - llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; - return FALSE; - } - } - else - { - llwarns << " name=\"eye_color\" not found" << llendl; - return FALSE; - } - - // avatar_lad.xml : - if (sAvatarXmlInfo->mLayerInfoList.empty()) - { - llwarns << "avatar file: missing node" << llendl; - return FALSE; - } - - if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) - { - llwarns << "avatar file: missing node" << llendl; - return FALSE; - } - - // avatar_lad.xml : - for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin(); - iter != sAvatarXmlInfo->mMorphMaskInfoList.end(); - ++iter) - { - LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter; - - EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion); - if (baked != BAKED_NUM_INDICES) - { - LLVisualParam* morph_param; - const std::string *name = &info->mName; - morph_param = getVisualParam(name->c_str()); - if (morph_param) - { - BOOL invert = info->mInvert; - addMaskedMorph(baked, morph_param, invert, info->mLayer); - } - } - - } - - loadLayersets(); - - // avatar_lad.xml : - for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); - iter != sAvatarXmlInfo->mDriverInfoList.end(); - ++iter) - { - LLDriverParamInfo *info = *iter; - LLDriverParam* driver_param = new LLDriverParam( this ); - if (driver_param->setInfo(info)) - { - addVisualParam( driver_param ); - LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam; - if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false)) - { - llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl; - continue; - } - } - else - { - delete driver_param; - llwarns << "avatar file: driver_param->parseData() failed" << llendl; - return FALSE; - } - } - - - return TRUE; -} - //----------------------------------------------------------------------------- // loadSkeletonNode(): loads node from XML tree //----------------------------------------------------------------------------- +//virtual BOOL LLVOAvatar::loadSkeletonNode () { - mRoot.addChild( &mSkeleton[0] ); - - for (std::vector::iterator iter = mMeshLOD.begin(); + // make meshes children before calling parent version of the function + for (std::vector::iterator iter = mMeshLOD.begin(); iter != mMeshLOD.end(); ++iter) { @@ -5553,60 +4959,19 @@ BOOL LLVOAvatar::loadSkeletonNode () joint->setMeshesToChildren(); } - mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); - mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]); - mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]); - mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]); - mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]); - mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); - - LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull"); - if (skull) - { - skull->addChild(mMeshLOD[MESH_ID_HAIR] ); - } - - LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); - if (eyeL) + if (!LLAvatarAppearance::loadSkeletonNode()) { - eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); - } - - LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); - if (eyeR) - { - eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); + return FALSE; } - // SKELETAL DISTORTIONS - { - LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; - for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); - ++iter) - { - LLPolySkeletalDistortionInfo *info = *iter; - LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); - if (!param->setInfo(info)) - { - delete param; - return FALSE; - } - else - { - addVisualParam(param); - } - } - } - // ATTACHMENTS { - LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter; + LLAvatarXmlInfo::attachment_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); iter != sAvatarXmlInfo->mAttachmentInfoList.end(); ++iter) { - LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter; + LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; if (!isSelf() && info->mJointName == "mScreen") { //don't process screen joint for other avatars continue; @@ -5678,144 +5043,6 @@ BOOL LLVOAvatar::loadSkeletonNode () return TRUE; } -//----------------------------------------------------------------------------- -// loadMeshNodes(): loads nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::loadMeshNodes() -{ - for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); - meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); - ++meshinfo_iter) - { - const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter; - const std::string &type = info->mType; - S32 lod = info->mLOD; - - LLViewerJointMesh* mesh = NULL; - U8 mesh_id = 0; - BOOL found_mesh_id = FALSE; - - /* if (type == "hairMesh") - switch(lod) - case 0: - mesh = &mHairMesh0; */ - for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); - mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); - ++mesh_iter) - { - const EMeshIndex mesh_index = mesh_iter->first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_iter->second; - if (type.compare(mesh_dict->mName) == 0) - { - mesh_id = mesh_index; - found_mesh_id = TRUE; - break; - } - } - - if (found_mesh_id) - { - if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) - { - mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; - } - else - { - llwarns << "Avatar file: has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else - { - llwarns << "Ignoring unrecognized mesh type: " << type << llendl; - return FALSE; - } - - // llinfos << "Parsing mesh data for " << type << "..." << llendl; - - // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. - // Do not touch!!! - mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f ); - - LLPolyMesh *poly_mesh = NULL; - - if (!info->mReferenceMeshName.empty()) - { - polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); - if (polymesh_iter != mMeshes.end()) - { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); - poly_mesh->setAvatar(this); - } - else - { - // This should never happen - LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; - } - } - else - { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); - poly_mesh->setAvatar(this); - } - - if( !poly_mesh ) - { - llwarns << "Failed to load mesh of type " << type << llendl; - return FALSE; - } - - // Multimap insert - mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); - - mesh->setMesh( poly_mesh ); - mesh->setLOD( info->mMinPixelArea ); - - for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); - xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); - ++xmlinfo_iter) - { - const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); - LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); - if (!param->setInfo(info_pair->first)) - { - delete param; - return FALSE; - } - else - { - if (info_pair->second) - { - addSharedVisualParam(param); - } - else - { - addVisualParam(param); - } - } - } - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// loadLayerSets() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::loadLayersets() -{ - BOOL success = TRUE; - for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin(); - layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); - ++layerset_iter) - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - LLTexLayerSetInfo *layerset_info = *layerset_iter; - layerset_info->createVisualParams(this); - } - return success; -} - //----------------------------------------------------------------------------- // updateVisualParams() //----------------------------------------------------------------------------- @@ -5829,7 +5056,7 @@ void LLVOAvatar::updateVisualParams() { computeBodySize(); mLastSkeletonSerialNum = mSkeletonSerialNum; - mRoot.updateWorldMatrixChildren(); + mRoot->updateWorldMatrixChildren(); } dirtyMesh(); @@ -5919,7 +5146,12 @@ BOOL LLVOAvatar::updateJointLODs() } // now select meshes to render based on adjusted pixel area - BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + LLViewerJoint* root = dynamic_cast(mRoot); + BOOL res = FALSE; + if (root) + { + res = root->updateLOD(mAdjustedPixelArea, TRUE); + } if (res) { sNumLODChangesThisFrame++; @@ -6009,6 +5241,15 @@ void LLVOAvatar::dirtyMesh(S32 priority) { mDirtyMesh = llmax(mDirtyMesh, priority); } + +//----------------------------------------------------------------------------- +// getViewerJoint() +//----------------------------------------------------------------------------- +LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx) +{ + return dynamic_cast(mMeshLOD[idx]); +} + //----------------------------------------------------------------------------- // hideSkirt() //----------------------------------------------------------------------------- @@ -6322,9 +5563,9 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) // Notice that removing sitDown() from here causes avatars sitting on // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655. sitDown(TRUE); - mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject - mRoot.setPosition(getPosition()); - mRoot.updateWorldMatrixChildren(); + mRoot->getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject + mRoot->setPosition(getPosition()); + mRoot->updateWorldMatrixChildren(); stopMotion(ANIM_AGENT_BODY_NOISE); @@ -6370,10 +5611,10 @@ void LLVOAvatar::getOffObject() sitDown(FALSE); - mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject - mRoot.setPosition(cur_position_world); - mRoot.setRotation(cur_rotation_world); - mRoot.getXform()->update(); + mRoot->getXform()->setParent(NULL); // LLVOAvatar::getOffObject + mRoot->setPosition(cur_position_world); + mRoot->setRotation(cur_rotation_world); + mRoot->getXform()->update(); startMotion(ANIM_AGENT_BODY_NOISE); @@ -7752,501 +6993,20 @@ void LLVOAvatar::startAppearanceAnimation() } } -// virtual -void LLVOAvatar::removeMissingBakedTextures() -{ -} - -//----------------------------------------------------------------------------- -// LLVOAvatarXmlInfo -//----------------------------------------------------------------------------- - -LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() - : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) -{ -} - -LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() -{ - std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); - std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); - std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); - deleteAndClear(mTexSkinColorInfo); - deleteAndClear(mTexHairColorInfo); - deleteAndClear(mTexEyeColorInfo); - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); - std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); - std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); -} - -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ - if (node->hasName("bone")) - { - mIsJoint = TRUE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - llwarns << "Bone without name" << llendl; - return FALSE; - } - } - else if (node->hasName("collision_volume")) - { - mIsJoint = FALSE; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - mName = "Collision Volume"; - } - } - else - { - llwarns << "Invalid node " << node->getName() << llendl; - return FALSE; - } - - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - if (!node->getFastAttributeVector3(pos_string, mPos)) - { - llwarns << "Bone without position" << llendl; - return FALSE; - } - - static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); - if (!node->getFastAttributeVector3(rot_string, mRot)) - { - llwarns << "Bone without rotation" << llendl; - return FALSE; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!node->getFastAttributeVector3(scale_string, mScale)) - { - llwarns << "Bone without scale" << llendl; - return FALSE; - } - - if (mIsJoint) - { - static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); - if (!node->getFastAttributeVector3(pivot_string, mPivot)) - { - llwarns << "Bone without pivot" << llendl; - return FALSE; - } - } - - // parse children - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; - if (!child_info->parseXml(child)) - { - delete child_info; - return FALSE; - } - mChildList.push_back(child_info); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ - static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); - if (!node->getFastAttributeS32(num_bones_string, mNumBones)) - { - llwarns << "Couldn't find number of bones." << llendl; - return FALSE; - } - - static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); - node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; - if (!info->parseXml(child)) - { - delete info; - llwarns << "Error parsing bone in skeleton file" << llendl; - return FALSE; - } - mBoneInfoList.push_back(info); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// parseXmlSkeletonNode(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) -{ - LLXmlTreeNode* node = root->getChildByName( "skeleton" ); - if( !node ) - { - llwarns << "avatar file: missing " << llendl; - return FALSE; - } - - LLXmlTreeNode* child; - - // SKELETON DISTORTIONS - for (child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_skeleton")) - { - if (child->getChildByName("param_morph")) - { - llwarns << "Can't specify morph param in skeleton definition." << llendl; - } - else - { - llwarns << "Unknown param type." << llendl; - } - continue; - } - - LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; - if (!info->parseXml(child)) - { - delete info; - return FALSE; - } - - mSkeletalDistortionInfoList.push_back(info); - } - - // ATTACHMENT POINTS - for (child = node->getChildByName( "attachment_point" ); - child; - child = node->getNextNamedChild()) - { - LLVOAvatarAttachmentInfo* info = new LLVOAvatarAttachmentInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!child->getFastAttributeString(name_string, info->mName)) - { - llwarns << "No name supplied for attachment point." << llendl; - delete info; - continue; - } - - static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); - if (!child->getFastAttributeString(joint_string, info->mJointName)) - { - llwarns << "No bone declared in attachment point " << info->mName << llendl; - delete info; - continue; - } - - static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); - if (child->getFastAttributeVector3(position_string, info->mPosition)) - { - info->mHasPosition = TRUE; - } - - static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); - if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) - { - info->mHasRotation = TRUE; - } - static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); - if (child->getFastAttributeS32(group_string, info->mGroup)) - { - if (info->mGroup == -1) - info->mGroup = -1111; // -1 = none parsed, < -1 = bad value - } - - static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); - if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) - { - llwarns << "No id supplied for attachment point " << info->mName << llendl; - delete info; - continue; - } - - static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); - child->getFastAttributeS32(slot_string, info->mPieMenuSlice); - - static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); - child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); - - static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); - child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); - - mAttachmentInfoList.push_back(info); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// parseXmlMeshNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); - node; - node = root->getNextNamedChild()) - { - LLVOAvatarMeshInfo *info = new LLVOAvatarMeshInfo; - - // attribute: type - static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); - if( !node->getFastAttributeString( type_string, info->mType ) ) - { - llwarns << "Avatar file: is missing type attribute. Ignoring element. " << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); - if (!node->getFastAttributeS32( lod_string, info->mLOD )) - { - llwarns << "Avatar file: is missing lod attribute. Ignoring element. " << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) - { - llwarns << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << llendl; - delete info; - return FALSE; // Ignore this element - } - - static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); - node->getFastAttributeString( reference_string, info->mReferenceMeshName ); - - // attribute: min_pixel_area - static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); - static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); - if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) - { - F32 min_pixel_area = 0.1f; - if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) - { - // this is square root of pixel area (sensible to use linear space in defining lods) - min_pixel_area = min_pixel_area * min_pixel_area; - } - info->mMinPixelArea = min_pixel_area; - } - - // Parse visual params for this node only if we haven't already - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_morph")) - { - if (child->getChildByName("param_skeleton")) - { - llwarns << "Can't specify skeleton param in a mesh definition." << llendl; - } - else - { - llwarns << "Unknown param type." << llendl; - } - continue; - } - - LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); - if (!morphinfo->parseXml(child)) - { - delete morphinfo; - delete info; - return -1; - } - BOOL shared = FALSE; - static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); - child->getFastAttributeBOOL(shared_string, shared); - - info->mPolyMorphTargetInfoList.push_back(LLVOAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); - } - - mMeshInfoList.push_back(info); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// parseXmlColorNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); - color_node; - color_node = root->getNextNamedChild()) - { - std::string global_color_name; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (color_node->getFastAttributeString( name_string, global_color_name ) ) - { - if( global_color_name == "skin_color" ) - { - if (mTexSkinColorInfo) - { - llwarns << "avatar file: multiple instances of skin_color" << llendl; - return FALSE; - } - mTexSkinColorInfo = new LLTexGlobalColorInfo; - if( !mTexSkinColorInfo->parseXml( color_node ) ) - { - deleteAndClear(mTexSkinColorInfo); - llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl; - return FALSE; - } - } - else if( global_color_name == "hair_color" ) - { - if (mTexHairColorInfo) - { - llwarns << "avatar file: multiple instances of hair_color" << llendl; - return FALSE; - } - mTexHairColorInfo = new LLTexGlobalColorInfo; - if( !mTexHairColorInfo->parseXml( color_node ) ) - { - deleteAndClear(mTexHairColorInfo); - llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl; - return FALSE; - } - } - else if( global_color_name == "eye_color" ) - { - if (mTexEyeColorInfo) - { - llwarns << "avatar file: multiple instances of eye_color" << llendl; - return FALSE; - } - mTexEyeColorInfo = new LLTexGlobalColorInfo; - if( !mTexEyeColorInfo->parseXml( color_node ) ) - { - llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl; - return FALSE; - } - } - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// parseXmlLayerNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +//virtual +void LLVOAvatar::bodySizeChanged() { - for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); - layer_node; - layer_node = root->getNextNamedChild()) - { - LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); - if( layer_info->parseXml( layer_node ) ) - { - mLayerInfoList.push_back(layer_info); - } - else - { - delete layer_info; - llwarns << "avatar file: layer_set->parseXml() failed" << llendl; - return FALSE; - } + if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF()) + { // notify simulator of change in size + // but not if we are in the middle of updating appearance + gAgent.sendAgentSetAppearance(); } - return TRUE; } -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) -{ - LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); - if( driver ) - { - for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); - grand_child; - grand_child = driver->getNextNamedChild()) - { - if( grand_child->getChildByName( "param_driver" ) ) - { - LLDriverParamInfo* driver_info = new LLDriverParamInfo(); - if( driver_info->parseXml( grand_child ) ) - { - mDriverInfoList.push_back(driver_info); - } - else - { - delete driver_info; - llwarns << "avatar file: driver_param->parseXml() failed" << llendl; - return FALSE; - } - } - } - } - return TRUE; -} -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) -{ - LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); - if( !masks ) - { - return FALSE; - } - - for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); - grand_child; - grand_child = masks->getNextNamedChild()) - { - LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); - if (!grand_child->getFastAttributeString(name_string, info->mName)) - { - llwarns << "No name supplied for morph mask." << llendl; - delete info; - continue; - } - - static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); - if (!grand_child->getFastAttributeString(region_string, info->mRegion)) - { - llwarns << "No region supplied for morph mask." << llendl; - delete info; - continue; - } - - static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); - if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) - { - llwarns << "No layer supplied for morph mask." << llendl; - delete info; - continue; - } - - // optional parameter. don't throw a warning if not present. - static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); - grand_child->getFastAttributeBOOL(invert_string, info->mInvert); - - mMorphMaskInfoList.push_back(info); - } - - return TRUE; +// virtual +void LLVOAvatar::removeMissingBakedTextures() +{ } //virtual diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index dd8663f4dc..bda09b044d 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -69,8 +69,7 @@ class LLVoiceVisualizer; class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +class LLViewerJoint; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -85,8 +84,6 @@ class LLVOAvatar : public: friend class LLVOAvatarSelf; -protected: - struct LLVOAvatarXmlInfo; /******************************************************************************** ** ** @@ -111,9 +108,6 @@ public: virtual void initInstance(); // Called after construction to initialize the class. protected: virtual ~LLVOAvatar(); - BOOL loadSkeletonNode(); - BOOL loadMeshNodes(); - virtual BOOL loadLayersets(); /** Initialization ** ** @@ -190,7 +184,7 @@ public: void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); - virtual LLJoint* getRootJoint() { return &mRoot; } + virtual LLJoint* getRootJoint() { return mRoot; } void resetJointPositions( void ); void resetJointPositionsToDefault( void ); @@ -224,7 +218,6 @@ public: public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent /*virtual*/BOOL isUsingBakedTextures() const { return mUseServerBakes; } // e.g. false if in appearance edit mode - bool isBuilt() const { return mIsBuilt; } private: //aligned members LL_ALIGN_16(LLVector4a mImpostorExtents[2]); @@ -343,7 +336,6 @@ protected: /** State ** ** *******************************************************************************/ - /******************************************************************************** ** ** ** SKELETON @@ -351,74 +343,22 @@ protected: public: void updateHeadOffset(); - F32 getPelvisToFoot() const { return mPelvisToFoot; } void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; bool hasPelvisOffset( void ) { return mHasPelvisOffset; } void postPelvisSetRecalc( void ); void setPelvisOffset( F32 pelvixFixupAmount ); + /*virtual*/ BOOL loadSkeletonNode(); + /*virtual*/ void buildCharacter(); + bool mHasPelvisOffset; LLVector3 mPelvisOffset; F32 mLastPelvisToFoot; F32 mPelvisFixup; F32 mLastPelvisFixup; - LLVector3 mHeadOffset; // current head position - LLViewerJoint mRoot; - - typedef std::map joint_map_t; - joint_map_t mJointMap; - -protected: - static BOOL parseSkeletonFile(const std::string& filename); - void buildCharacter(); - virtual BOOL loadAvatar(); - - BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); - BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); -private: - BOOL mIsBuilt; // state of deferred character building - S32 mNumJoints; - LLViewerJoint* mSkeleton; - - //-------------------------------------------------------------------- - // Pelvis height adjustment members. - //-------------------------------------------------------------------- -public: - LLVector3 mBodySize; S32 mLastSkeletonSerialNum; -private: - F32 mPelvisToFoot; - //-------------------------------------------------------------------- - // Cached pointers to well known joints - //-------------------------------------------------------------------- -public: - LLViewerJoint* mPelvisp; - LLViewerJoint* mTorsop; - LLViewerJoint* mChestp; - LLViewerJoint* mNeckp; - LLViewerJoint* mHeadp; - LLViewerJoint* mSkullp; - LLViewerJoint* mEyeLeftp; - LLViewerJoint* mEyeRightp; - LLViewerJoint* mHipLeftp; - LLViewerJoint* mHipRightp; - LLViewerJoint* mKneeLeftp; - LLViewerJoint* mKneeRightp; - LLViewerJoint* mAnkleLeftp; - LLViewerJoint* mAnkleRightp; - LLViewerJoint* mFootLeftp; - LLViewerJoint* mFootRightp; - LLViewerJoint* mWristLeftp; - LLViewerJoint* mWristRightp; - - //-------------------------------------------------------------------- - // XML parse tree - //-------------------------------------------------------------------- -private: - static LLXmlTree sXMLTree; // avatar config file - static LLXmlTree sSkeletonXMLTree; // avatar skeleton file /** Skeleton ** ** @@ -640,8 +580,6 @@ public: private: static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; - static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; - static LLVOAvatarXmlInfo* sAvatarXmlInfo; //-------------------------------------------------------------------- // Messaging @@ -671,13 +609,10 @@ protected: virtual void restoreMeshData(); private: virtual void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + LLViewerJoint* getViewerJoint(S32 idx); S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD BOOL mMeshTexturesDirty; - typedef std::multimap polymesh_map_t; - polymesh_map_t mMeshes; - std::vector mMeshLOD; - //-------------------------------------------------------------------- // Destroy invisible mesh //-------------------------------------------------------------------- @@ -698,6 +633,7 @@ public: void processAvatarAppearance(LLMessageSystem* mesgsys); void hideSkirt(); void startAppearanceAnimation(); + /*virtual*/ void bodySizeChanged(); //-------------------------------------------------------------------- // Appearance morphing @@ -839,15 +775,6 @@ private: BOOL mTurning; // controls hysteresis on avatar rotation F32 mSpeed; // misc. animation repeated state - //-------------------------------------------------------------------- - // Collision volumes - //-------------------------------------------------------------------- -public: - S32 mNumCollisionVolumes; - LLViewerJointCollisionVolume* mCollisionVolumes; -protected: - BOOL allocateCollisionVolumes(U32 num); - //-------------------------------------------------------------------- // Dimensions //-------------------------------------------------------------------- @@ -858,7 +785,6 @@ public: void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm); void slamPosition(); // Slam position to transmitted position (for teleport); protected: - void computeBodySize(); //-------------------------------------------------------------------- // Material being stepped on @@ -1025,90 +951,6 @@ protected: protected: // Shared with LLVOAvatarSelf - struct LLVOAvatarXmlInfo - { - LLVOAvatarXmlInfo(); - ~LLVOAvatarXmlInfo(); - - BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); - BOOL parseXmlMeshNodes(LLXmlTreeNode* root); - BOOL parseXmlColorNodes(LLXmlTreeNode* root); - BOOL parseXmlLayerNodes(LLXmlTreeNode* root); - BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - BOOL parseXmlMorphNodes(LLXmlTreeNode* root); - - struct LLVOAvatarMeshInfo - { - typedef std::pair morph_info_pair_t; - typedef std::vector morph_info_list_t; - - LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} - ~LLVOAvatarMeshInfo() - { - morph_info_list_t::iterator iter; - for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) - { - delete iter->first; - } - mPolyMorphTargetInfoList.clear(); - } - - std::string mType; - S32 mLOD; - std::string mMeshFileName; - std::string mReferenceMeshName; - F32 mMinPixelArea; - morph_info_list_t mPolyMorphTargetInfoList; - }; - typedef std::vector mesh_info_list_t; - mesh_info_list_t mMeshInfoList; - - typedef std::vector skeletal_distortion_info_list_t; - skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - - struct LLVOAvatarAttachmentInfo - { - LLVOAvatarAttachmentInfo() - : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), - mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} - std::string mName; - std::string mJointName; - LLVector3 mPosition; - LLVector3 mRotationEuler; - S32 mGroup; - S32 mAttachmentID; - S32 mPieMenuSlice; - BOOL mVisibleFirstPerson; - BOOL mIsHUDAttachment; - BOOL mHasPosition; - BOOL mHasRotation; - }; - typedef std::vector attachment_info_list_t; - attachment_info_list_t mAttachmentInfoList; - - LLTexGlobalColorInfo *mTexSkinColorInfo; - LLTexGlobalColorInfo *mTexHairColorInfo; - LLTexGlobalColorInfo *mTexEyeColorInfo; - - typedef std::vector layer_info_list_t; - layer_info_list_t mLayerInfoList; - - typedef std::vector driver_info_list_t; - driver_info_list_t mDriverInfoList; - - struct LLVOAvatarMorphInfo - { - LLVOAvatarMorphInfo() - : mInvert(FALSE) {} - std::string mName; - std::string mRegion; - std::string mLayer; - BOOL mInvert; - }; - - typedef std::vector morph_info_list_t; - morph_info_list_t mMorphMaskInfoList; - }; /** Support classes ** ** diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index fc52347041..f832a126bd 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -255,7 +255,7 @@ BOOL LLVOAvatarSelf::loadAvatarSelf() return success; } -BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info) +BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLAvatarSkeletonInfo *info) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -589,7 +589,7 @@ LLVOAvatarSelf::~LLVOAvatarSelf() BOOL LLVOAvatarSelf::loadLayersets() { BOOL success = TRUE; - for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); + for (LLAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); iter != sAvatarXmlInfo->mLayerInfoList.end(); ++iter) { @@ -952,7 +952,7 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) void LLVOAvatarSelf::idleUpdateTractorBeam() { // This is only done for yourself (maybe it should be in the agent?) - if (!needsRenderBeam() || !mIsBuilt) + if (!needsRenderBeam() || !isBuilt()) { mBeam = NULL; } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 75c2743ab0..bdc1ccf133 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -67,7 +67,7 @@ public: protected: /*virtual*/ BOOL loadAvatar(); BOOL loadAvatarSelf(); - BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info); + BOOL buildSkeletonSelf(const LLAvatarSkeletonInfo *info); BOOL buildMenus(); /*virtual*/ BOOL loadLayersets(); -- cgit v1.2.3 From cf7eb79fa7eadd6d76890d2a3f9da905de8f4691 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 8 Sep 2012 04:39:11 +0000 Subject: Removed most llappearance -> llui dependencies (LLTrans remains). Moved LLInventoryIcon::EIconName into LLInventoryType. Moved LLInventoryIcon back to newview. Moved LLUI gl_* functions into llrender. --- indra/appearance_utility/CMakeLists.txt | 3 + indra/appearance_utility/appearance_utility.cpp | 4 + indra/llappearance/CMakeLists.txt | 2 - indra/llappearance/llinventoryicon.cpp | 183 --- indra/llappearance/llinventoryicon.h | 102 -- indra/llappearance/lltexlayer.cpp | 2 +- indra/llappearance/lltexlayer.h | 2 +- indra/llappearance/lltexlayerparams.cpp | 2 +- indra/llappearance/llviewervisualparam.cpp | 1 - indra/llappearance/llwearabletype.cpp | 46 +- indra/llappearance/llwearabletype.h | 4 +- indra/llinventory/llinventorytype.h | 47 + indra/llrender/CMakeLists.txt | 4 + indra/llrender/llrender2dutils.cpp | 1621 +++++++++++++++++++++++ indra/llrender/llrender2dutils.h | 164 +++ indra/llrender/lluiimage.cpp | 199 +++ indra/llrender/lluiimage.h | 124 ++ indra/llui/CMakeLists.txt | 2 - indra/llui/llcombobox.cpp | 2 +- indra/llui/lllineeditor.cpp | 6 +- indra/llui/lllocalcliprect.cpp | 8 +- indra/llui/lltextbase.cpp | 4 +- indra/llui/lltexteditor.cpp | 2 +- indra/llui/llui.cpp | 1579 +--------------------- indra/llui/llui.h | 131 +- indra/llui/lluiimage.cpp | 199 --- indra/llui/lluiimage.h | 124 -- indra/llui/tests/llurlentry_test.cpp | 2 +- indra/llui/tests/llurlmatch_test.cpp | 2 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llappviewer.cpp | 2 +- indra/newview/llfloaterbuycontents.cpp | 1 + indra/newview/llglsandbox.cpp | 8 +- indra/newview/llinventorybridge.cpp | 3 +- indra/newview/llinventoryicon.cpp | 183 +++ indra/newview/llinventoryicon.h | 56 + indra/newview/llinventorylistitem.cpp | 1 + indra/newview/llmediactrl.cpp | 18 +- indra/newview/llpanelgroupnotices.cpp | 1 + indra/newview/llpanelobjectinventory.cpp | 1 + indra/newview/lltoastgroupnotifypanel.cpp | 1 + indra/newview/llviewerdisplay.cpp | 10 +- indra/newview/llviewerwindow.cpp | 12 +- indra/newview/llwearableitemslist.cpp | 1 + indra/newview/llworldmapview.cpp | 2 +- 45 files changed, 2510 insertions(+), 2363 deletions(-) delete mode 100644 indra/llappearance/llinventoryicon.cpp delete mode 100644 indra/llappearance/llinventoryicon.h create mode 100644 indra/llrender/llrender2dutils.cpp create mode 100644 indra/llrender/llrender2dutils.h create mode 100644 indra/llrender/lluiimage.cpp create mode 100644 indra/llrender/lluiimage.h delete mode 100644 indra/llui/lluiimage.cpp delete mode 100644 indra/llui/lluiimage.h create mode 100644 indra/newview/llinventoryicon.cpp create mode 100644 indra/newview/llinventoryicon.h diff --git a/indra/appearance_utility/CMakeLists.txt b/indra/appearance_utility/CMakeLists.txt index c38f811b44..d860dae4df 100644 --- a/indra/appearance_utility/CMakeLists.txt +++ b/indra/appearance_utility/CMakeLists.txt @@ -9,6 +9,7 @@ include(OpenSSL) include(UI) include(LLAppearance) include(LLCommon) +include(LLInventory) include(LLVFS) include(LLXML) include(LLUI) @@ -19,6 +20,7 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS} + ${LLINVENTORY_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ${CARES_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} @@ -44,6 +46,7 @@ target_link_libraries(appearance-utility-bin ${CRYPTO_LIBRARIES} ${UI_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ${LLINVENTORY_LIBRARIES} ${LLXML_LIBRARIES} ${LLUI_LIBRARIES} ${LLVFS_LIBRARIES} diff --git a/indra/appearance_utility/appearance_utility.cpp b/indra/appearance_utility/appearance_utility.cpp index 130bca84a8..c7f8703e28 100644 --- a/indra/appearance_utility/appearance_utility.cpp +++ b/indra/appearance_utility/appearance_utility.cpp @@ -38,6 +38,8 @@ #include "llsdserialize.h" #include "llsdutil.h" +//#include "llwearabledata.h" + enum EResult { RV_SUCCESS = 0, @@ -150,6 +152,8 @@ EResult process_tbd(LLSD& input, std::ostream& output, LLSD& error_llsd) { EResult rv = RV_SUCCESS; + //LLWearableData wearable_data; + LLSD result; result["success"] = true; result["input"] = input; diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 41da898457..717efb2f8b 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -43,7 +43,6 @@ include_directories( set(llappearance_SOURCE_FILES llavatarappearance.cpp lldriverparam.cpp - llinventoryicon.cpp lllocaltextureobject.cpp lltexglobalcolor.cpp lltexlayer.cpp @@ -61,7 +60,6 @@ set(llappearance_HEADER_FILES llavatarappearance.h lldriverparam.h - llinventoryicon.h lljointpickname.h lllocaltextureobject.h lltexglobalcolor.h diff --git a/indra/llappearance/llinventoryicon.cpp b/indra/llappearance/llinventoryicon.cpp deleted file mode 100644 index 371f60353b..0000000000 --- a/indra/llappearance/llinventoryicon.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file llinventoryicon.cpp - * @brief Implementation of the inventory icon. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llinventoryicon.h" - -#include "lldictionary.h" -#include "llinventorydefines.h" -#include "llui.h" -#include "llwearabletype.h" - -struct IconEntry : public LLDictionaryEntry -{ - IconEntry(const std::string &item_name) - : - LLDictionaryEntry(item_name) - {} -}; - -class LLIconDictionary : public LLSingleton, - public LLDictionary -{ -public: - LLIconDictionary(); -}; - -LLIconDictionary::LLIconDictionary() -{ - addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); - addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); - addEntry(LLInventoryIcon::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT, new IconEntry("Inv_Object")); - addEntry(LLInventoryIcon::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); - addEntry(LLInventoryIcon::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); - - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); - addEntry(LLInventoryIcon::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); - addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); - addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); - - addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); - - addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); - addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); - addEntry(LLInventoryIcon::ICONNAME_MESH, new IconEntry("Inv_Mesh")); - - addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); - - addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); -} - -LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 misc_flag, - BOOL item_is_multi) -{ - const std::string& icon_name = getIconName(asset_type, inventory_type, misc_flag, item_is_multi); - return LLUI::getUIImage(icon_name); -} - -LLUIImagePtr LLInventoryIcon::getIcon(EIconName idx) -{ - return LLUI::getUIImage(getIconName(idx)); -} - -const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 misc_flag, - BOOL item_is_multi) -{ - EIconName idx = ICONNAME_OBJECT; - if (item_is_multi) - { - idx = ICONNAME_OBJECT_MULTI; - return getIconName(idx); - } - - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? ICONNAME_SNAPSHOT : ICONNAME_TEXTURE; - break; - case LLAssetType::AT_SOUND: - idx = ICONNAME_SOUND; - break; - case LLAssetType::AT_CALLINGCARD: - idx = (misc_flag != 0) ? ICONNAME_CALLINGCARD_ONLINE : ICONNAME_CALLINGCARD_OFFLINE; - break; - case LLAssetType::AT_LANDMARK: - idx = (misc_flag != 0) ? ICONNAME_LANDMARK_VISITED : ICONNAME_LANDMARK; - break; - case LLAssetType::AT_SCRIPT: - case LLAssetType::AT_LSL_TEXT: - case LLAssetType::AT_LSL_BYTECODE: - idx = ICONNAME_SCRIPT; - break; - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - idx = assignWearableIcon(misc_flag); - break; - case LLAssetType::AT_NOTECARD: - idx = ICONNAME_NOTECARD; - break; - case LLAssetType::AT_ANIMATION: - idx = ICONNAME_ANIMATION; - break; - case LLAssetType::AT_GESTURE: - idx = ICONNAME_GESTURE; - break; - case LLAssetType::AT_LINK: - idx = ICONNAME_LINKITEM; - break; - case LLAssetType::AT_LINK_FOLDER: - idx = ICONNAME_LINKFOLDER; - break; - case LLAssetType::AT_OBJECT: - idx = ICONNAME_OBJECT; - break; - case LLAssetType::AT_MESH: - idx = ICONNAME_MESH; - default: - break; - } - - return getIconName(idx); -} - - -const std::string& LLInventoryIcon::getIconName(EIconName idx) -{ - const IconEntry *entry = LLIconDictionary::instance().lookup(idx); - return entry->mName; -} - -LLInventoryIcon::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) -{ - const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); - return LLWearableType::getIconName(wearable_type); -} diff --git a/indra/llappearance/llinventoryicon.h b/indra/llappearance/llinventoryicon.h deleted file mode 100644 index c7e2998a20..0000000000 --- a/indra/llappearance/llinventoryicon.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file llinventoryfunctions.h - * @brief Miscellaneous inventory-related functions and classes - * class definition - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLINVENTORYICON_H -#define LL_LLINVENTORYICON_H - -#include "llassettype.h" -#include "llinventorytype.h" -#include "lluiimage.h" - -class LLInventoryIcon -{ -public: - enum EIconName - { - ICONNAME_TEXTURE, - ICONNAME_SOUND, - ICONNAME_CALLINGCARD_ONLINE, - ICONNAME_CALLINGCARD_OFFLINE, - ICONNAME_LANDMARK, - ICONNAME_LANDMARK_VISITED, - ICONNAME_SCRIPT, - ICONNAME_CLOTHING, - ICONNAME_OBJECT, - ICONNAME_OBJECT_MULTI, - ICONNAME_NOTECARD, - ICONNAME_BODYPART, - ICONNAME_SNAPSHOT, - - ICONNAME_BODYPART_SHAPE, - ICONNAME_BODYPART_SKIN, - ICONNAME_BODYPART_HAIR, - ICONNAME_BODYPART_EYES, - ICONNAME_CLOTHING_SHIRT, - ICONNAME_CLOTHING_PANTS, - ICONNAME_CLOTHING_SHOES, - ICONNAME_CLOTHING_SOCKS, - ICONNAME_CLOTHING_JACKET, - ICONNAME_CLOTHING_GLOVES, - ICONNAME_CLOTHING_UNDERSHIRT, - ICONNAME_CLOTHING_UNDERPANTS, - ICONNAME_CLOTHING_SKIRT, - ICONNAME_CLOTHING_ALPHA, - ICONNAME_CLOTHING_TATTOO, - - ICONNAME_ANIMATION, - ICONNAME_GESTURE, - - ICONNAME_CLOTHING_PHYSICS, - - ICONNAME_LINKITEM, - ICONNAME_LINKFOLDER, - ICONNAME_MESH, - - ICONNAME_INVALID, - ICONNAME_COUNT, - ICONNAME_NONE = -1 - }; - - static const std::string& getIconName(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - U32 misc_flag = 0, // different meanings depending on item type - BOOL item_is_multi = FALSE); - static const std::string& getIconName(EIconName idx); - - static LLUIImagePtr getIcon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, - U32 misc_flag = 0, // different meanings depending on item type - BOOL item_is_multi = FALSE); - static LLUIImagePtr getIcon(EIconName idx); - -protected: - static EIconName assignWearableIcon(U32 misc_flag); -}; -#endif // LL_LLINVENTORYICON_H - - - diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 9b70f737a0..1325267dc2 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -38,7 +38,7 @@ #include "llvfs.h" #include "lltexlayerparams.h" #include "lltexturemanagerbridge.h" -#include "llui.h" +#include "llrender2dutils.h" #include "llwearable.h" #include "llwearabledata.h" #include "llvertexbuffer.h" diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index e6c2ece64a..0d7fad349c 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -28,8 +28,8 @@ #define LL_LLTEXLAYER_H #include +#include "llglslshader.h" #include "llgltexture.h" -//#include "llframetimer.h" #include "llavatarappearancedefines.h" #include "lltexlayerparams.h" diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 06001c6b15..82c92b5a5e 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -33,8 +33,8 @@ #include "llquantize.h" #include "lltexlayer.h" #include "lltexturemanagerbridge.h" +#include "llrender2dutils.h" #include "llwearable.h" -#include "llui.h" //----------------------------------------------------------------------------- // LLTexLayerParam diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index a6792d0974..cc81bcf118 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -31,7 +31,6 @@ #include "llviewervisualparam.h" #include "llxmltree.h" -#include "llui.h" #include "llwearable.h" //----------------------------------------------------------------------------- diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index c72a0965fe..3a8e1b8be3 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -26,15 +26,15 @@ #include "linden_common.h" #include "llwearabletype.h" -#include "llinventoryicon.h" -#include "lltrans.h" +#include "llinventorytype.h" +#include "llui/lltrans.h" struct WearableEntry : public LLDictionaryEntry { WearableEntry(const std::string &name, const std::string& default_new_name, LLAssetType::EType assetType, - LLInventoryIcon::EIconName iconName, + LLInventoryType::EIconName iconName, BOOL disable_camera_switch = FALSE, BOOL allow_multiwear = TRUE) : LLDictionaryEntry(name), @@ -50,7 +50,7 @@ struct WearableEntry : public LLDictionaryEntry const LLAssetType::EType mAssetType; const std::string mLabel; const std::string mDefaultNewName; //keep mLabel for backward compatibility - LLInventoryIcon::EIconName mIconName; + LLInventoryType::EIconName mIconName; BOOL mDisableCameraSwitch; BOOL mAllowMultiwear; }; @@ -64,26 +64,26 @@ public: LLWearableDictionary::LLWearableDictionary() { - addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); - addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); + addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); + addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); - addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); } // static @@ -131,7 +131,7 @@ LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) } // static -LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType type) +LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type) { const LLWearableDictionary *dict = LLWearableDictionary::getInstance(); const WearableEntry *entry = dict->lookup(type); diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index d633b4807e..78008c27ea 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -29,7 +29,7 @@ #include "llassettype.h" #include "lldictionary.h" -#include "llinventoryicon.h" +#include "llinventorytype.h" #include "llsingleton.h" class LLWearableType @@ -64,7 +64,7 @@ public: static const std::string& getTypeLabel(EType type); static LLAssetType::EType getAssetType(EType type); static EType typeNameToType(const std::string& type_name); - static LLInventoryIcon::EIconName getIconName(EType type); + static LLInventoryType::EIconName getIconName(EType type); static BOOL getDisableCameraSwitch(EType type); static BOOL getAllowMultiwear(EType type); diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 4d1e0db040..078b773932 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -68,6 +68,53 @@ public: IT_NONE = -1 }; + enum EIconName + { + ICONNAME_TEXTURE, + ICONNAME_SOUND, + ICONNAME_CALLINGCARD_ONLINE, + ICONNAME_CALLINGCARD_OFFLINE, + ICONNAME_LANDMARK, + ICONNAME_LANDMARK_VISITED, + ICONNAME_SCRIPT, + ICONNAME_CLOTHING, + ICONNAME_OBJECT, + ICONNAME_OBJECT_MULTI, + ICONNAME_NOTECARD, + ICONNAME_BODYPART, + ICONNAME_SNAPSHOT, + + ICONNAME_BODYPART_SHAPE, + ICONNAME_BODYPART_SKIN, + ICONNAME_BODYPART_HAIR, + ICONNAME_BODYPART_EYES, + ICONNAME_CLOTHING_SHIRT, + ICONNAME_CLOTHING_PANTS, + ICONNAME_CLOTHING_SHOES, + ICONNAME_CLOTHING_SOCKS, + ICONNAME_CLOTHING_JACKET, + ICONNAME_CLOTHING_GLOVES, + ICONNAME_CLOTHING_UNDERSHIRT, + ICONNAME_CLOTHING_UNDERPANTS, + ICONNAME_CLOTHING_SKIRT, + ICONNAME_CLOTHING_ALPHA, + ICONNAME_CLOTHING_TATTOO, + + ICONNAME_ANIMATION, + ICONNAME_GESTURE, + + ICONNAME_CLOTHING_PHYSICS, + + ICONNAME_LINKITEM, + ICONNAME_LINKFOLDER, + ICONNAME_MESH, + + ICONNAME_INVALID, + ICONNAME_COUNT, + ICONNAME_NONE = -1 + }; + + // machine transation between type and strings static EType lookup(const std::string& name); static const std::string &lookup(EType type); diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 4609401ccf..3418ce2dfa 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -37,10 +37,12 @@ set(llrender_SOURCE_FILES llgltexture.cpp llimagegl.cpp llpostprocess.cpp + llrender2dutils.cpp llrendernavprim.cpp llrendersphere.cpp llshadermgr.cpp lltexture.cpp + lluiimage.cpp llvertexbuffer.cpp ) @@ -62,10 +64,12 @@ set(llrender_HEADER_FILES llimagegl.h llpostprocess.h llrender.h + llrender2dutils.h llrendernavprim.h llrendersphere.h llshadermgr.h lltexture.h + lluiimage.h llvertexbuffer.h ) diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp new file mode 100644 index 0000000000..b2679176be --- /dev/null +++ b/indra/llrender/llrender2dutils.cpp @@ -0,0 +1,1621 @@ +/** + * @file llrender2dutils.cpp + * @brief GL function implementations for immediate-mode gl drawing. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// Linden library includes +#include "v2math.h" +#include "m3math.h" +#include "v4color.h" +#include "llfontgl.h" +#include "llrender.h" +#include "llrect.h" +#include "llgl.h" +#include "lltexture.h" + +// Project includes +#include "llrender2dutils.h" +#include "lluiimage.h" + + +// +// Globals +// +const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); +/*static*/ LLVector2 LLRender2D::sGLScaleFactor(1.f, 1.f); +/*static*/ LLImageProviderInterface* LLRender2D::sImageProvider = NULL; + +// +// Functions +// + +BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) +{ + if (x < left || right < x) return FALSE; + if (y < bottom || top < y) return FALSE; + return TRUE; +} + + +// Puts GL into 2D drawing mode by turning off lighting, setting to an +// orthographic projection, etc. +void gl_state_for_2d(S32 width, S32 height) +{ + stop_glerror(); + F32 window_width = (F32) width;//gViewerWindow->getWindowWidth(); + F32 window_height = (F32) height;//gViewerWindow->getWindowHeight(); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadIdentity(); + gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadIdentity(); + stop_glerror(); +} + + +void gl_draw_x(const LLRect& rect, const LLColor4& color) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv( color.mV ); + + gGL.begin( LLRender::LINES ); + gGL.vertex2i( rect.mLeft, rect.mTop ); + gGL.vertex2i( rect.mRight, rect.mBottom ); + gGL.vertex2i( rect.mLeft, rect.mBottom ); + gGL.vertex2i( rect.mRight, rect.mTop ); + gGL.end(); +} + + +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled) +{ + gGL.color4fv(color.mV); + gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled); +} + +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled) +{ + gGL.pushUIMatrix(); + left += LLFontGL::sCurOrigin.mX; + right += LLFontGL::sCurOrigin.mX; + bottom += LLFontGL::sCurOrigin.mY; + top += LLFontGL::sCurOrigin.mY; + + gGL.loadUIIdentity(); + gl_rect_2d(llfloor((F32)left * LLRender2D::sGLScaleFactor.mV[VX]) - pixel_offset, + llfloor((F32)top * LLRender2D::sGLScaleFactor.mV[VY]) + pixel_offset, + llfloor((F32)right * LLRender2D::sGLScaleFactor.mV[VX]) + pixel_offset, + llfloor((F32)bottom * LLRender2D::sGLScaleFactor.mV[VY]) - pixel_offset, + filled); + gGL.popUIMatrix(); +} + + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) +{ + stop_glerror(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Counterclockwise quad will face the viewer + if( filled ) + { + gGL.begin( LLRender::QUADS ); + gGL.vertex2i(left, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + gGL.end(); + } + else + { + if( gGLManager.mATIOffsetVerticalLines ) + { + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + gGL.begin( LLRender::LINES ); + + // Verticals + gGL.vertex2i(left + 1, top); + gGL.vertex2i(left + 1, bottom); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + + // Horizontals + top--; + right--; + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + + gGL.vertex2i(left, top); + gGL.vertex2i(right, top); + gGL.end(); + } + else + { + top--; + right--; + gGL.begin( LLRender::LINE_STRIP ); + gGL.vertex2i(left, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + gGL.vertex2i(left, top); + gGL.end(); + } + } + stop_glerror(); +} + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled ) +{ + gGL.color4fv( color.mV ); + gl_rect_2d( left, top, right, bottom, filled ); +} + + +void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled ) +{ + gGL.color4fv( color.mV ); + gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); +} + +// Given a rectangle on the screen, draws a drop shadow _outside_ +// the right and bottom edges of it. Along the right it has width "lines" +// and along the bottom it has height "lines". +void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines) +{ + stop_glerror(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // HACK: Overlap with the rectangle by a single pixel. + right--; + bottom++; + lines++; + + LLColor4 end_color = start_color; + end_color.mV[VALPHA] = 0.f; + + gGL.begin(LLRender::QUADS); + + // Right edge, CCW faces screen + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top-lines); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right+lines, bottom); + gGL.vertex2i(right+lines, top-lines); + + // Bottom edge, CCW faces screen + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(right, bottom-lines); + + // bottom left Corner + gGL.color4fv(start_color.mV); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left, bottom); + // make the bottom left corner not sharp + gGL.vertex2i(left+1, bottom-lines+1); + gGL.vertex2i(left+lines, bottom-lines); + + // bottom right corner + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right, bottom-lines); + // make the rightmost corner not sharp + gGL.vertex2i(right+lines-1, bottom-lines+1); + gGL.vertex2i(right+lines, bottom); + + // top right corner + gGL.color4fv(start_color.mV); + gGL.vertex2i( right, top-lines ); + gGL.color4fv(end_color.mV); + gGL.vertex2i( right+lines, top-lines ); + // make the corner not sharp + gGL.vertex2i( right+lines-1, top-1 ); + gGL.vertex2i( right, top ); + + gGL.end(); + stop_glerror(); +} + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) +{ + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) + { + x1++; + x2++; + y1++; + y2++; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.begin(LLRender::LINES); + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.end(); +} + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) +{ + // Work around bug in ATI driver: vertical lines are offset by (-1,-1) + if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) + { + x1++; + x2++; + y1++; + y2++; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv( color.mV ); + + gGL.begin(LLRender::LINES); + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.end(); +} + +void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.color4fv(color.mV); + + if (filled) + { + gGL.begin(LLRender::TRIANGLES); + } + else + { + gGL.begin(LLRender::LINE_LOOP); + } + gGL.vertex2i(x1, y1); + gGL.vertex2i(x2, y2); + gGL.vertex2i(x3, y3); + gGL.end(); +} + +void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + length = llmin((S32)(max_frac*(right - left)), length); + length = llmin((S32)(max_frac*(top - bottom)), length); + gGL.begin(LLRender::LINES); + gGL.vertex2i(left, top); + gGL.vertex2i(left + length, top); + + gGL.vertex2i(left, top); + gGL.vertex2i(left, top - length); + + gGL.vertex2i(left, bottom); + gGL.vertex2i(left + length, bottom); + + gGL.vertex2i(left, bottom); + gGL.vertex2i(left, bottom + length); + + gGL.vertex2i(right, top); + gGL.vertex2i(right - length, top); + + gGL.vertex2i(right, top); + gGL.vertex2i(right, top - length); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right - length, bottom); + + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, bottom + length); + gGL.end(); +} + + +void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect ) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); +} + +void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); +} + +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + // scale screen size of borders down + F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); + F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); + + LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); + gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); +} + +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) +{ + stop_glerror(); + + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + // add in offset of current image to current UI translation + const LLVector3 ui_scale = gGL.getUIScale(); + const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); + + F32 uv_width = uv_outer_rect.getWidth(); + F32 uv_height = uv_outer_rect.getHeight(); + + // shrink scaling region to be proportional to clipped image region + LLRectf uv_center_rect( + uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), + uv_outer_rect.mBottom + (center_rect.mTop * uv_height), + uv_outer_rect.mLeft + (center_rect.mRight * uv_width), + uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); + + F32 image_width = image->getWidth(0); + F32 image_height = image->getHeight(0); + + S32 image_natural_width = llround(image_width * uv_width); + S32 image_natural_height = llround(image_height * uv_height); + + LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, + uv_center_rect.mTop * image_height, + uv_center_rect.mRight * image_width, + uv_center_rect.mBottom * image_height); + + { // scale fixed region of image to drawn region + draw_center_rect.mRight += width - image_natural_width; + draw_center_rect.mTop += height - image_natural_height; + + F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); + F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); + + F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); + F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); + + F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + + draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); + draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); + draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); + draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); + } + + LLRectf draw_outer_rect(ui_translation.mV[VX], + ui_translation.mV[VY] + height * ui_scale.mV[VY], + ui_translation.mV[VX] + width * ui_scale.mV[VX], + ui_translation.mV[VY]); + + LLGLSUIDefault gls_ui; + + if (solid_color) + { + if (LLGLSLShader::sNoFixedFunction) + { + gSolidColorProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + } + } + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + const S32 NUM_VERTICES = 9 * 4; // 9 quads + LLVector2 uv[NUM_VERTICES]; + LLVector3 pos[NUM_VERTICES]; + + S32 index = 0; + + gGL.begin(LLRender::QUADS); + { + // draw bottom left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + // draw bottom middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + // draw bottom right + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + // draw left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + // draw middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + // draw right + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + // draw top left + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // draw top middle + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + // draw top right + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); + + if (solid_color) + { + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } + } +} + +void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); +} + +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +{ + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + + LLGLSUIDefault gls_ui; + + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + if (degrees == 0.f) + { + const S32 NUM_VERTICES = 4; // 9 quads + LLVector2 uv[NUM_VERTICES]; + LLVector3 pos[NUM_VERTICES]; + + gGL.begin(LLRender::QUADS); + { + LLVector3 ui_scale = gGL.getUIScale(); + LLVector3 ui_translation = gGL.getUITranslation(); + ui_translation.mV[VX] += x; + ui_translation.mV[VY] += y; + ui_translation.scaleVec(ui_scale); + S32 index = 0; + S32 scaled_width = llround(width * ui_scale.mV[VX]); + S32 scaled_height = llround(height * ui_scale.mV[VY]); + + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); + pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); + pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); + index++; + + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); + } + else + { + gGL.pushUIMatrix(); + gGL.translateUI((F32)x, (F32)y, 0.f); + + F32 offset_x = F32(width/2); + F32 offset_y = F32(height/2); + + gGL.translateUI(offset_x, offset_y, 0.f); + + LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); + + gGL.getTexUnit(0)->bind(image, true); + + gGL.color4fv(color.mV); + + gGL.begin(LLRender::QUADS); + { + LLVector3 v; + + v = LLVector3(offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(-offset_x, offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(-offset_x, -offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); + gGL.vertex2f(v.mV[0], v.mV[1] ); + + v = LLVector3(offset_x, -offset_y, 0.f) * quat; + gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); + gGL.vertex2f(v.mV[0], v.mV[1] ); + } + gGL.end(); + gGL.popUIMatrix(); + } +} + + +void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) +{ + phase = fmod(phase, 1.f); + + S32 shift = S32(phase * 4.f) % 4; + + // Stippled line + LLGLEnable stipple(GL_LINE_STIPPLE); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); + + gGL.flush(); + glLineWidth(2.5f); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(2, 0x3333 << shift); + } + + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv( start.mV ); + gGL.vertex3fv( end.mV ); + } + gGL.end(); + + LLRender2D::setLineWidth(1.f); +} + +void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle) +{ + if (end_angle < start_angle) + { + end_angle += F_TWO_PI; + } + + gGL.pushUIMatrix(); + { + gGL.translateUI(center_x, center_y, 0.f); + + // Inexact, but reasonably fast. + F32 delta = (end_angle - start_angle) / steps; + F32 sin_delta = sin( delta ); + F32 cos_delta = cos( delta ); + F32 x = cosf(start_angle) * radius; + F32 y = sinf(start_angle) * radius; + + if (filled) + { + gGL.begin(LLRender::TRIANGLE_FAN); + gGL.vertex2f(0.f, 0.f); + // make sure circle is complete + steps += 1; + } + else + { + gGL.begin(LLRender::LINE_STRIP); + } + + while( steps-- ) + { + // Successive rotations + gGL.vertex2f( x, y ); + F32 x_new = x * cos_delta - y * sin_delta; + y = x * sin_delta + y * cos_delta; + x = x_new; + } + gGL.end(); + } + gGL.popUIMatrix(); +} + +void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled) +{ + gGL.pushUIMatrix(); + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.translateUI(center_x, center_y, 0.f); + + // Inexact, but reasonably fast. + F32 delta = F_TWO_PI / steps; + F32 sin_delta = sin( delta ); + F32 cos_delta = cos( delta ); + F32 x = radius; + F32 y = 0.f; + + if (filled) + { + gGL.begin(LLRender::TRIANGLE_FAN); + gGL.vertex2f(0.f, 0.f); + // make sure circle is complete + steps += 1; + } + else + { + gGL.begin(LLRender::LINE_LOOP); + } + + while( steps-- ) + { + // Successive rotations + gGL.vertex2f( x, y ); + F32 x_new = x * cos_delta - y * sin_delta; + y = x * sin_delta + y * cos_delta; + x = x_new; + } + gGL.end(); + } + gGL.popUIMatrix(); +} + +// Renders a ring with sides (tube shape) +void gl_deep_circle( F32 radius, F32 depth, S32 steps ) +{ + F32 x = radius; + F32 y = 0.f; + F32 angle_delta = F_TWO_PI / (F32)steps; + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + S32 step = steps + 1; // An extra step to close the circle. + while( step-- ) + { + gGL.vertex3f( x, y, depth ); + gGL.vertex3f( x, y, 0.f ); + + F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta); + y = x * sinf(angle_delta) + y * cosf(angle_delta); + x = x_new; + } + } + gGL.end(); +} + +void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ) +{ + gGL.pushUIMatrix(); + { + gGL.translateUI(0.f, 0.f, -width / 2); + if( render_center ) + { + gGL.color4fv(center_color.mV); + gGL.diffuseColor4fv(center_color.mV); + gl_deep_circle( radius, width, steps ); + } + else + { + gGL.diffuseColor4fv(side_color.mV); + gl_washer_2d(radius, radius - width, steps, side_color, side_color); + gGL.translateUI(0.f, 0.f, width); + gl_washer_2d(radius - width, radius, steps, side_color, side_color); + } + } + gGL.popUIMatrix(); +} + +// Draw gray and white checkerboard with black border +void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) +{ + if (!LLGLSLShader::sNoFixedFunction) + { + // Initialize the first time this is called. + const S32 PIXELS = 32; + static GLubyte checkerboard[PIXELS * PIXELS]; + static BOOL first = TRUE; + if( first ) + { + for( S32 i = 0; i < PIXELS; i++ ) + { + for( S32 j = 0; j < PIXELS; j++ ) + { + checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; + } + } + first = FALSE; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // ...white squares + gGL.color4f( 1.f, 1.f, 1.f, alpha ); + gl_rect_2d(rect); + + // ...gray squares + gGL.color4f( .7f, .7f, .7f, alpha ); + gGL.flush(); + + glPolygonStipple( checkerboard ); + + LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); + gl_rect_2d(rect); + } + else + { //polygon stipple is deprecated, use "Checker" texture + LLPointer img = LLRender2D::getUIImage("Checker"); + gGL.getTexUnit(0)->bind(img->getImage()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + + LLColor4 color(1.f, 1.f, 1.f, alpha); + LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); + + gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), + img->getImage(), color, uv_rect); + } + + gGL.flush(); +} + + +// Draws the area between two concentric circles, like +// a doughnut or washer. +void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) +{ + const F32 DELTA = F_TWO_PI / steps; + const F32 SIN_DELTA = sin( DELTA ); + const F32 COS_DELTA = cos( DELTA ); + + F32 x1 = outer_radius; + F32 y1 = 0.f; + F32 x2 = inner_radius; + F32 y2 = 0.f; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + steps += 1; // An extra step to close the circle. + while( steps-- ) + { + gGL.color4fv(outer_color.mV); + gGL.vertex2f( x1, y1 ); + gGL.color4fv(inner_color.mV); + gGL.vertex2f( x2, y2 ); + + F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; + y1 = x1 * SIN_DELTA + y1 * COS_DELTA; + x1 = x1_new; + + F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; + y2 = x2 * SIN_DELTA + y2 * COS_DELTA; + x2 = x2_new; + } + } + gGL.end(); +} + +// Draws the area between two concentric circles, like +// a doughnut or washer. +void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) +{ + const F32 DELTA = (end_radians - start_radians) / steps; + const F32 SIN_DELTA = sin( DELTA ); + const F32 COS_DELTA = cos( DELTA ); + + F32 x1 = outer_radius * cos( start_radians ); + F32 y1 = outer_radius * sin( start_radians ); + F32 x2 = inner_radius * cos( start_radians ); + F32 y2 = inner_radius * sin( start_radians ); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.begin( LLRender::TRIANGLE_STRIP ); + { + steps += 1; // An extra step to close the circle. + while( steps-- ) + { + gGL.color4fv(outer_color.mV); + gGL.vertex2f( x1, y1 ); + gGL.color4fv(inner_color.mV); + gGL.vertex2f( x2, y2 ); + + F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; + y1 = x1 * SIN_DELTA + y1 * COS_DELTA; + x1 = x1_new; + + F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; + y2 = x2 * SIN_DELTA + y2 * COS_DELTA; + x2 = x2_new; + } + } + gGL.end(); +} + +void gl_rect_2d_simple_tex( S32 width, S32 height ) +{ + gGL.begin( LLRender::QUADS ); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(width, height); + + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2i(0, height); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); + + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(width, 0); + + gGL.end(); +} + +void gl_rect_2d_simple( S32 width, S32 height ) +{ + gGL.begin( LLRender::QUADS ); + gGL.vertex2i(width, height); + gGL.vertex2i(0, height); + gGL.vertex2i(0, 0); + gGL.vertex2i(width, 0); + gGL.end(); +} + +void gl_segmented_rect_2d_tex(const S32 left, + const S32 top, + const S32 right, + const S32 bottom, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const U32 edges) +{ + S32 width = llabs(right - left); + S32 height = llabs(top - bottom); + + gGL.pushUIMatrix(); + + gGL.translateUI((F32)left, (F32)bottom, 0.f); + LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); + + if (border_uv_scale.mV[VX] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; + } + if (border_uv_scale.mV[VY] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; + } + + F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); + LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 width_vec((F32)width, 0.f); + LLVector2 height_vec(0.f, (F32)height); + + gGL.begin(LLRender::QUADS); + { + // draw bottom left + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(0.f, 0.f); + + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + // draw bottom middle + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + // draw bottom right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2fv(width_vec.mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + // draw left + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + // draw middle + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + // draw right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + // draw top left + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2fv((height_vec).mV); + + // draw top middle + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + + // draw top right + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2fv((width_vec + height_vec).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + } + gGL.end(); + + gGL.popUIMatrix(); +} + +//FIXME: rewrite to use scissor? +void gl_segmented_rect_2d_fragment_tex(const S32 left, + const S32 top, + const S32 right, + const S32 bottom, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const F32 start_fragment, + const F32 end_fragment, + const U32 edges) +{ + S32 width = llabs(right - left); + S32 height = llabs(top - bottom); + + gGL.pushUIMatrix(); + + gGL.translateUI((F32)left, (F32)bottom, 0.f); + LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); + + if (border_uv_scale.mV[VX] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; + } + if (border_uv_scale.mV[VY] > 0.5f) + { + border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; + } + + F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); + LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; + LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; + LLVector2 width_vec((F32)width, 0.f); + LLVector2 height_vec(0.f, (F32)height); + + F32 middle_start = border_scale / (F32)width; + F32 middle_end = 1.f - middle_start; + + F32 u_min; + F32 u_max; + LLVector2 x_min; + LLVector2 x_max; + + gGL.begin(LLRender::QUADS); + { + if (start_fragment < middle_start) + { + u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; + u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; + x_min = (start_fragment / middle_start) * border_width_left; + x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; + + // draw bottom left + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_max.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw left + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top left + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(u_min, 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + + if (end_fragment > middle_start || start_fragment < middle_end) + { + x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; + x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; + + // draw bottom middle + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((x_max).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw middle + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top middle + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + + if (end_fragment > middle_end) + { + u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; + u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; + x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); + x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); + + // draw bottom right + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv((x_min).mV); + + gGL.texCoord2f(u_max, 0.f); + gGL.vertex2fv(x_max.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + // draw right + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + // draw top right + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + + gGL.texCoord2f(u_min, 1.f); + gGL.vertex2fv((x_min + height_vec).mV); + } + } + gGL.end(); + + gGL.popUIMatrix(); +} + +void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, + const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, + const U32 edges) +{ + LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; + LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; + + LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; + LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; + + + gGL.begin(LLRender::QUADS); + { + // draw bottom left + gGL.texCoord2f(0.f, 0.f); + gGL.vertex3f(0.f, 0.f, 0.f); + + gGL.texCoord2f(border_scale.mV[VX], 0.f); + gGL.vertex3fv(left_border_width.mV); + + gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + bottom_border_height).mV); + + gGL.texCoord2f(0.f, border_scale.mV[VY]); + gGL.vertex3fv(bottom_border_height.mV); + + // draw bottom middle + gGL.texCoord2f(border_scale.mV[VX], 0.f); + gGL.vertex3fv(left_border_width.mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); + gGL.vertex3fv((width_vec - right_border_width).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + + gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + bottom_border_height).mV); + + // draw bottom right + gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); + gGL.vertex3fv((width_vec - right_border_width).mV); + + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3fv(width_vec.mV); + + gGL.texCoord2f(1.f, border_scale.mV[VY]); + gGL.vertex3fv((width_vec + bottom_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + + // draw left + gGL.texCoord2f(0.f, border_scale.mV[VY]); + gGL.vertex3fv(bottom_border_height.mV); + + gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + bottom_border_height).mV); + + gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); + gGL.vertex3fv((height_vec - top_border_height).mV); + + // draw middle + gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + bottom_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + + // draw right + gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + + gGL.texCoord2f(1.f, border_scale.mV[VY]); + gGL.vertex3fv((width_vec + bottom_border_height).mV); + + gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + + // draw top left + gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); + gGL.vertex3fv((height_vec - top_border_height).mV); + + gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(border_scale.mV[VX], 1.f); + gGL.vertex3fv((left_border_width + height_vec).mV); + + gGL.texCoord2f(0.f, 1.f); + gGL.vertex3fv((height_vec).mV); + + // draw top middle + gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); + gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + + gGL.texCoord2f(border_scale.mV[VX], 1.f); + gGL.vertex3fv((left_border_width + height_vec).mV); + + // draw top right + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + + gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); + gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex3fv((width_vec + height_vec).mV); + + gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); + gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + } + gGL.end(); + +} + +void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) +{ + gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); +} + +// static +void LLRender2D::initClass(LLImageProviderInterface* image_provider, + const LLVector2* scale_factor) +{ + sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; + sImageProvider = image_provider; +} + +// static +void LLRender2D::cleanupClass() +{ + if(sImageProvider) + { + sImageProvider->cleanUp(); + } +} + + +//static +void LLRender2D::translate(F32 x, F32 y, F32 z) +{ + gGL.translateUI(x,y,z); + LLFontGL::sCurOrigin.mX += (S32) x; + LLFontGL::sCurOrigin.mY += (S32) y; + LLFontGL::sCurDepth += z; +} + +//static +void LLRender2D::pushMatrix() +{ + gGL.pushUIMatrix(); + LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); +} + +//static +void LLRender2D::popMatrix() +{ + gGL.popUIMatrix(); + LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; + LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; + LLFontGL::sOriginStack.pop_back(); +} + +//static +void LLRender2D::loadIdentity() +{ + gGL.loadUIIdentity(); + LLFontGL::sCurOrigin.mX = 0; + LLFontGL::sCurOrigin.mY = 0; + LLFontGL::sCurDepth = 0.f; +} + +//static +void LLRender2D::setScaleFactor(const LLVector2 &scale_factor) +{ + sGLScaleFactor = scale_factor; +} + +//static +void LLRender2D::setLineWidth(F32 width) +{ + gGL.flush(); + glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); +} + +//static +LLPointer LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority) +{ + if (sImageProvider) + { + return sImageProvider->getUIImageByID(image_id, priority); + } + else + { + return NULL; + } +} + +//static +LLPointer LLRender2D::getUIImage(const std::string& name, S32 priority) +{ + if (!name.empty() && sImageProvider) + return sImageProvider->getUIImage(name, priority); + else + return NULL; +} + diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h new file mode 100644 index 0000000000..4ea2d06d99 --- /dev/null +++ b/indra/llrender/llrender2dutils.h @@ -0,0 +1,164 @@ +/** + * @file llrender2dutils.h + * @brief GL function declarations for immediate-mode gl drawing. + * + * $LicenseInfo:firstyear=2012&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$ + */ + +// All immediate-mode gl drawing should happen here. + + +#ifndef LL_RENDER2DUTILS_H +#define LL_RENDER2DUTILS_H + +#include "llpointer.h" // LLPointer<> +#include "llrect.h" +#include "llglslshader.h" + +class LLColor4; +class LLVector3; +class LLVector2; +class LLUIImage; +class LLUUID; + +extern const LLColor4 UI_VERTEX_COLOR; + +BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom); +void gl_state_for_2d(S32 width, S32 height); + +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2); +void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ); +void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled); +void gl_rect_2d_simple( S32 width, S32 height ); + +void gl_draw_x(const LLRect& rect, const LLColor4& color); + +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE ); +void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE ); +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE ); +void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE ); +void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE ); +void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE ); +void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f); + +void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines); + +void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled); +void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle); +void gl_deep_circle( F32 radius, F32 depth ); +void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ); +void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac); +void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); +void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); + +void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); + +void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); + +void gl_rect_2d_simple_tex( S32 width, S32 height ); + +// segmented rectangles + +/* + TL |______TOP_________| TR + /| |\ + _/_|__________________|_\_ + L| | MIDDLE | |R + _|_|__________________|_|_ + \ | BOTTOM | / + BL\|__________________|/ BR + | | +*/ + +typedef enum e_rounded_edge +{ + ROUNDED_RECT_LEFT = 0x1, + ROUNDED_RECT_TOP = 0x2, + ROUNDED_RECT_RIGHT = 0x4, + ROUNDED_RECT_BOTTOM = 0x8, + ROUNDED_RECT_ALL = 0xf +}ERoundedEdge; + + +void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); + +inline void gl_rect_2d( const LLRect& rect, BOOL filled ) +{ + gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); +} + +inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled) +{ + gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); +} + +class LLImageProviderInterface; + +class LLRender2D +{ + LOG_CLASS(LLRender2D); +public: + static void initClass(LLImageProviderInterface* image_provider, + const LLVector2* scale_factor); + static void cleanupClass(); + + static void pushMatrix(); + static void popMatrix(); + static void loadIdentity(); + static void translate(F32 x, F32 y, F32 z = 0.0f); + + static void setLineWidth(F32 width); + static void setScaleFactor(const LLVector2& scale_factor); + + static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0); + static LLPointer getUIImage(const std::string& name, S32 priority = 0); + + static LLVector2 sGLScaleFactor; +private: + static LLImageProviderInterface* sImageProvider; +}; + +class LLImageProviderInterface +{ +protected: + LLImageProviderInterface() {}; + virtual ~LLImageProviderInterface() {}; +public: + virtual LLPointer getUIImage(const std::string& name, S32 priority) = 0; + virtual LLPointer getUIImageByID(const LLUUID& id, S32 priority) = 0; + virtual void cleanUp() = 0; +}; + + +extern LLGLSLShader gSolidColorProgram; +extern LLGLSLShader gUIProgram; + +#endif // LL_RENDER2DUTILS_H + diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp new file mode 100644 index 0000000000..a632e7ed2f --- /dev/null +++ b/indra/llrender/lluiimage.cpp @@ -0,0 +1,199 @@ +/** + * @file lluiimage.cpp + * @brief UI implementation + * + * $LicenseInfo:firstyear=2007&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$ + */ + +// Utilities functions the user interface needs + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +// Project includes +#include "lluiimage.h" +#include "llrender2dutils.h" + +LLUIImage::LLUIImage(const std::string& name, LLPointer image) +: mName(name), + mImage(image), + mScaleRegion(0.f, 1.f, 1.f, 0.f), + mClipRegion(0.f, 1.f, 1.f, 0.f), + mUniformScaling(TRUE), + mNoClip(TRUE), + mImageLoaded(NULL) +{ +} + +LLUIImage::~LLUIImage() +{ + delete mImageLoaded; +} + +void LLUIImage::setClipRegion(const LLRectf& region) +{ + mClipRegion = region; + mNoClip = mClipRegion.mLeft == 0.f + && mClipRegion.mRight == 1.f + && mClipRegion.mBottom == 0.f + && mClipRegion.mTop == 1.f; +} + +void LLUIImage::setScaleRegion(const LLRectf& region) +{ + mScaleRegion = region; + mUniformScaling = mScaleRegion.mLeft == 0.f + && mScaleRegion.mRight == 1.f + && mScaleRegion.mBottom == 0.f + && mScaleRegion.mTop == 1.f; +} + +//TODO: move drawing implementation inside class +void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const +{ + gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion); +} + +void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + if (mUniformScaling) + { + gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); + } + else + { + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + FALSE, + mClipRegion, + mScaleRegion); + } +} + +void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + TRUE, + mClipRegion, + mScaleRegion); +} + +void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const +{ + LLRect border_rect; + border_rect.setOriginAndSize(x, y, width, height); + border_rect.stretch(border_width, border_width); + drawSolid(border_rect, color); +} + +S32 LLUIImage::getWidth() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); +} + +S32 LLUIImage::getHeight() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); +} + +S32 LLUIImage::getTextureWidth() const +{ + return mImage->getWidth(0); +} + +S32 LLUIImage::getTextureHeight() const +{ + return mImage->getHeight(0); +} + +boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) +{ + if (!mImageLoaded) + { + mImageLoaded = new image_loaded_signal_t(); + } + return mImageLoaded->connect(cb); +} + + +void LLUIImage::onImageLoaded() +{ + if (mImageLoaded) + { + (*mImageLoaded)(); + } +} + + +namespace LLInitParam +{ + void ParamValue >::updateValueFromBlock() + { + // The keyword "none" is specifically requesting a null image + // do not default to current value. Used to overwrite template images. + if (name() == "none") + { + updateValue(NULL); + return; + } + + LLUIImage* imagep = LLRender2D::getUIImage(name()); + if (imagep) + { + updateValue(imagep); + } + } + + void ParamValue >::updateBlockFromValue(bool make_block_authoritative) + { + if (getValue() == NULL) + { + name.set("none", make_block_authoritative); + } + else + { + name.set(getValue()->getName(), make_block_authoritative); + } + } + + + bool ParamCompare::equals( + LLUIImage* const &a, + LLUIImage* const &b) + { + // force all LLUIImages for XML UI export to be "non-default" + if (!a && !b) + return false; + else + return (a == b); + } +} + diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h new file mode 100644 index 0000000000..f07e8fa746 --- /dev/null +++ b/indra/llrender/lluiimage.h @@ -0,0 +1,124 @@ +/** + * @file lluiimage.h + * @brief wrapper for images used in the UI that handles smart scaling, etc. + * + * $LicenseInfo:firstyear=2007&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_LLUIIMAGE_H +#define LL_LLUIIMAGE_H + +#include "v4color.h" +#include "llpointer.h" +#include "llrefcount.h" +#include "llrefcount.h" +#include "llrect.h" +#include +#include +#include "llinitparam.h" +#include "lltexture.h" + +extern const LLColor4 UI_VERTEX_COLOR; + +class LLUIImage : public LLRefCount +{ +public: + typedef boost::signals2::signal image_loaded_signal_t; + + LLUIImage(const std::string& name, LLPointer image); + virtual ~LLUIImage(); + + void setClipRegion(const LLRectf& region); + void setScaleRegion(const LLRectf& region); + + LLPointer getImage() { return mImage; } + const LLPointer& getImage() const { return mImage; } + + void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + + void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; + void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); } + + void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; + void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } + void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } + + const std::string& getName() const { return mName; } + + virtual S32 getWidth() const; + virtual S32 getHeight() const; + + // returns dimensions of underlying textures, which might not be equal to ui image portion + S32 getTextureWidth() const; + S32 getTextureHeight() const; + + boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb ); + + void onImageLoaded(); + +protected: + image_loaded_signal_t* mImageLoaded; + + std::string mName; + LLRectf mScaleRegion; + LLRectf mClipRegion; + LLPointer mImage; + BOOL mUniformScaling; + BOOL mNoClip; +}; + +namespace LLInitParam +{ + template<> + class ParamValue > + : public CustomParamValue + { + typedef boost::add_reference::type>::type T_const_ref; + typedef CustomParamValue super_t; + public: + Optional name; + + ParamValue(LLUIImage* const& image) + : super_t(image) + { + updateBlockFromValue(false); + addSynonym(name, "name"); + } + + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; + + // Need custom comparison function for our test app, which only loads + // LLUIImage* as NULL. + template<> + struct ParamCompare + { + static bool equals(LLUIImage* const &a, LLUIImage* const &b); + }; +} + +typedef LLPointer LLUIImagePtr; +#endif diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index d92b6aa1c0..4d4b8edc37 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -109,7 +109,6 @@ set(llui_SOURCE_FILES lluicolortable.cpp lluictrl.cpp lluictrlfactory.cpp - lluiimage.cpp lluistring.cpp llundo.cpp llurlaction.cpp @@ -219,7 +218,6 @@ set(llui_HEADER_FILES lluifwd.h llui.h lluicolor.h - lluiimage.h lluistring.h llundo.h llurlaction.h diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 806d2ef3f6..16e79b211d 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -551,7 +551,7 @@ void LLComboBox::showList() LLCoordWindow window_size; getWindow()->getSize(&window_size); //HACK: shouldn't have to know about scale here - mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); + mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 ); // Make sure that we can see the whole list LLRect root_view_local; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 48d49af588..d1e67a7d6b 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2022,8 +2022,8 @@ void LLLineEditor::draw() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } @@ -2570,7 +2570,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length) S32 LLLineEditor::getPreeditFontSize() const { - return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace) diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index 6841301219..f3a526faeb 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion() LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; - x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); - y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); - w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; - h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; + x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); + y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); + w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; + h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; glScissor( x,y,w,h ); stop_glerror(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3815eec447..abe74c3f20 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -513,8 +513,8 @@ void LLTextBase::drawCursor() LLRect screen_pos = calcScreenRect(); LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) ); - ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]); - ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]); + ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]); + ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]); getWindow()->setLanguageTextInput( ime_pos ); } } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 144b6960a1..1b22f87823 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2843,7 +2843,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length) S32 LLTextEditor::getPreeditFontSize() const { - return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); + return llround((F32)mDefaultFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]); } BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 87bf518aa1..d5fdd1d064 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -39,6 +39,7 @@ #include "llrect.h" #include "lldir.h" #include "llgl.h" +#include "llsd.h" // Project includes #include "llcommandmanager.h" @@ -69,15 +70,12 @@ // // Globals // -const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f); // Language for UI construction std::map gTranslation; std::list gUntranslated; /*static*/ LLUI::settings_map_t LLUI::sSettingGroups; -/*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL; /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL; -/*static*/ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f); /*static*/ LLWindow* LLUI::sWindow = NULL; /*static*/ LLView* LLUI::sRootView = NULL; /*static*/ BOOL LLUI::sDirty = FALSE; @@ -137,1492 +135,13 @@ void make_ui_sound(const char* namep) } } -BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom) -{ - if (x < left || right < x) return FALSE; - if (y < bottom || top < y) return FALSE; - return TRUE; -} - - -// Puts GL into 2D drawing mode by turning off lighting, setting to an -// orthographic projection, etc. -void gl_state_for_2d(S32 width, S32 height) -{ - stop_glerror(); - F32 window_width = (F32) width;//gViewerWindow->getWindowWidth(); - F32 window_height = (F32) height;//gViewerWindow->getWindowHeight(); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadIdentity(); - gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadIdentity(); - stop_glerror(); -} - - -void gl_draw_x(const LLRect& rect, const LLColor4& color) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin( LLRender::LINES ); - gGL.vertex2i( rect.mLeft, rect.mTop ); - gGL.vertex2i( rect.mRight, rect.mBottom ); - gGL.vertex2i( rect.mLeft, rect.mBottom ); - gGL.vertex2i( rect.mRight, rect.mTop ); - gGL.end(); -} - - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled) -{ - gGL.color4fv(color.mV); - gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled); -} - -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled) -{ - gGL.pushUIMatrix(); - left += LLFontGL::sCurOrigin.mX; - right += LLFontGL::sCurOrigin.mX; - bottom += LLFontGL::sCurOrigin.mY; - top += LLFontGL::sCurOrigin.mY; - - gGL.loadUIIdentity(); - gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset, - llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset, - llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset, - llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset, - filled); - gGL.popUIMatrix(); -} - - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Counterclockwise quad will face the viewer - if( filled ) - { - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - if( gGLManager.mATIOffsetVerticalLines ) - { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - gGL.begin( LLRender::LINES ); - - // Verticals - gGL.vertex2i(left + 1, top); - gGL.vertex2i(left + 1, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - - // Horizontals - top--; - right--; - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - - gGL.vertex2i(left, top); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - top--; - right--; - gGL.begin( LLRender::LINE_STRIP ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.vertex2i(left, top); - gGL.end(); - } - } - stop_glerror(); -} - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( left, top, right, bottom, filled ); -} - - -void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled ) -{ - gGL.color4fv( color.mV ); - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -// Given a rectangle on the screen, draws a drop shadow _outside_ -// the right and bottom edges of it. Along the right it has width "lines" -// and along the bottom it has height "lines". -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines) -{ - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // HACK: Overlap with the rectangle by a single pixel. - right--; - bottom++; - lines++; - - LLColor4 end_color = start_color; - end_color.mV[VALPHA] = 0.f; - - gGL.begin(LLRender::QUADS); - - // Right edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right+lines, bottom); - gGL.vertex2i(right+lines, top-lines); - - // Bottom edge, CCW faces screen - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); - - // bottom left Corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); - // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); - - // bottom right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); - // make the rightmost corner not sharp - gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); - - // top right corner - gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); - gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); - // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); - - gGL.end(); - stop_glerror(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) -{ - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv( color.mV ); - - gGL.begin(LLRender::LINES); - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.end(); -} - -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4fv(color.mV); - - if (filled) - { - gGL.begin(LLRender::TRIANGLES); - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - gGL.vertex2i(x1, y1); - gGL.vertex2i(x2, y2); - gGL.vertex2i(x3, y3); - gGL.end(); -} - -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - length = llmin((S32)(max_frac*(right - left)), length); - length = llmin((S32)(max_frac*(top - bottom)), length); - gGL.begin(LLRender::LINES); - gGL.vertex2i(left, top); - gGL.vertex2i(left + length, top); - - gGL.vertex2i(left, top); - gGL.vertex2i(left, top - length); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left + length, bottom); - - gGL.vertex2i(left, bottom); - gGL.vertex2i(left, bottom + length); - - gGL.vertex2i(right, top); - gGL.vertex2i(right - length, top); - - gGL.vertex2i(right, top); - gGL.vertex2i(right, top - length); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right - length, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, bottom + length); - gGL.end(); -} - - -void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect ) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // scale screen size of borders down - F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0); - F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); - - LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); - gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); -} - -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) -{ - stop_glerror(); - - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - // add in offset of current image to current UI translation - const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - - F32 uv_width = uv_outer_rect.getWidth(); - F32 uv_height = uv_outer_rect.getHeight(); - - // shrink scaling region to be proportional to clipped image region - LLRectf uv_center_rect( - uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), - uv_outer_rect.mBottom + (center_rect.mTop * uv_height), - uv_outer_rect.mLeft + (center_rect.mRight * uv_width), - uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); - - S32 image_natural_width = llround(image_width * uv_width); - S32 image_natural_height = llround(image_height * uv_height); - - LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, - uv_center_rect.mTop * image_height, - uv_center_rect.mRight * image_width, - uv_center_rect.mBottom * image_height); - - { // scale fixed region of image to drawn region - draw_center_rect.mRight += width - image_natural_width; - draw_center_rect.mTop += height - image_natural_height; - - F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); - F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); - - F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); - F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); - - F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); - - draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); - draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); - draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); - draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); - } - - LLRectf draw_outer_rect(ui_translation.mV[VX], - ui_translation.mV[VY] + height * ui_scale.mV[VY], - ui_translation.mV[VX] + width * ui_scale.mV[VX], - ui_translation.mV[VY]); - - LLGLSUIDefault gls_ui; - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gSolidColorProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - } - } - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - const S32 NUM_VERTICES = 9 * 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - S32 index = 0; - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - // draw bottom right - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - // draw left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - // draw right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - // draw top left - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top middle - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); - index++; - - // draw top right - uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - - if (solid_color) - { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - } -} - -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); -} - -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - LLGLSUIDefault gls_ui; - - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - if (degrees == 0.f) - { - const S32 NUM_VERTICES = 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - gGL.begin(LLRender::QUADS); - { - LLVector3 ui_scale = gGL.getUIScale(); - LLVector3 ui_translation = gGL.getUITranslation(); - ui_translation.mV[VX] += x; - ui_translation.mV[VY] += y; - ui_translation.scaleVec(ui_scale); - S32 index = 0; - S32 scaled_width = llround(width * ui_scale.mV[VX]); - S32 scaled_height = llround(height * ui_scale.mV[VY]); - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - } - else - { - gGL.pushUIMatrix(); - gGL.translateUI((F32)x, (F32)y, 0.f); - - F32 offset_x = F32(width/2); - F32 offset_y = F32(height/2); - - gGL.translateUI(offset_x, offset_y, 0.f); - - LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - gGL.begin(LLRender::QUADS); - { - LLVector3 v; - - v = LLVector3(offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - } - gGL.end(); - gGL.popUIMatrix(); - } -} - - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) -{ - phase = fmod(phase, 1.f); - - S32 shift = S32(phase * 4.f) % 4; - - // Stippled line - LLGLEnable stipple(GL_LINE_STIPPLE); - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]); - - gGL.flush(); - glLineWidth(2.5f); - - if (!LLGLSLShader::sNoFixedFunction) - { - glLineStipple(2, 0x3333 << shift); - } - - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv( start.mV ); - gGL.vertex3fv( end.mV ); - } - gGL.end(); - - LLUI::setLineWidth(1.f); -} - -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle) -{ - if (end_angle < start_angle) - { - end_angle += F_TWO_PI; - } - - gGL.pushUIMatrix(); - { - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = (end_angle - start_angle) / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = cosf(start_angle) * radius; - F32 y = sinf(start_angle) * radius; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_STRIP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled) -{ - gGL.pushUIMatrix(); - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.translateUI(center_x, center_y, 0.f); - - // Inexact, but reasonably fast. - F32 delta = F_TWO_PI / steps; - F32 sin_delta = sin( delta ); - F32 cos_delta = cos( delta ); - F32 x = radius; - F32 y = 0.f; - - if (filled) - { - gGL.begin(LLRender::TRIANGLE_FAN); - gGL.vertex2f(0.f, 0.f); - // make sure circle is complete - steps += 1; - } - else - { - gGL.begin(LLRender::LINE_LOOP); - } - - while( steps-- ) - { - // Successive rotations - gGL.vertex2f( x, y ); - F32 x_new = x * cos_delta - y * sin_delta; - y = x * sin_delta + y * cos_delta; - x = x_new; - } - gGL.end(); - } - gGL.popUIMatrix(); -} - -// Renders a ring with sides (tube shape) -void gl_deep_circle( F32 radius, F32 depth, S32 steps ) -{ - F32 x = radius; - F32 y = 0.f; - F32 angle_delta = F_TWO_PI / (F32)steps; - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - S32 step = steps + 1; // An extra step to close the circle. - while( step-- ) - { - gGL.vertex3f( x, y, depth ); - gGL.vertex3f( x, y, 0.f ); - - F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta); - y = x * sinf(angle_delta) + y * cosf(angle_delta); - x = x_new; - } - } - gGL.end(); -} - -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ) -{ - gGL.pushUIMatrix(); - { - gGL.translateUI(0.f, 0.f, -width / 2); - if( render_center ) - { - gGL.color4fv(center_color.mV); - gGL.diffuseColor4fv(center_color.mV); - gl_deep_circle( radius, width, steps ); - } - else - { - gGL.diffuseColor4fv(side_color.mV); - gl_washer_2d(radius, radius - width, steps, side_color, side_color); - gGL.translateUI(0.f, 0.f, width); - gl_washer_2d(radius - width, radius, steps, side_color, side_color); - } - } - gGL.popUIMatrix(); -} - -// Draw gray and white checkerboard with black border -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) -{ - if (!LLGLSLShader::sNoFixedFunction) - { - // Initialize the first time this is called. - const S32 PIXELS = 32; - static GLubyte checkerboard[PIXELS * PIXELS]; - static BOOL first = TRUE; - if( first ) - { - for( S32 i = 0; i < PIXELS; i++ ) - { - for( S32 j = 0; j < PIXELS; j++ ) - { - checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; - } - } - first = FALSE; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // ...white squares - gGL.color4f( 1.f, 1.f, 1.f, alpha ); - gl_rect_2d(rect); - - // ...gray squares - gGL.color4f( .7f, .7f, .7f, alpha ); - gGL.flush(); - - glPolygonStipple( checkerboard ); - - LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); - gl_rect_2d(rect); - } - else - { //polygon stipple is deprecated, use "Checker" texture - LLPointer img = LLUI::getUIImage("Checker"); - gGL.getTexUnit(0)->bind(img->getImage()); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - - LLColor4 color(1.f, 1.f, 1.f, alpha); - LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); - - gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), - img->getImage(), color, uv_rect); - } - - gGL.flush(); -} - - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = F_TWO_PI / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius; - F32 y1 = 0.f; - F32 x2 = inner_radius; - F32 y2 = 0.f; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -// Draws the area between two concentric circles, like -// a doughnut or washer. -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color) -{ - const F32 DELTA = (end_radians - start_radians) / steps; - const F32 SIN_DELTA = sin( DELTA ); - const F32 COS_DELTA = cos( DELTA ); - - F32 x1 = outer_radius * cos( start_radians ); - F32 y1 = outer_radius * sin( start_radians ); - F32 x2 = inner_radius * cos( start_radians ); - F32 y2 = inner_radius * sin( start_radians ); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin( LLRender::TRIANGLE_STRIP ); - { - steps += 1; // An extra step to close the circle. - while( steps-- ) - { - gGL.color4fv(outer_color.mV); - gGL.vertex2f( x1, y1 ); - gGL.color4fv(inner_color.mV); - gGL.vertex2f( x2, y2 ); - - F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; - y1 = x1 * SIN_DELTA + y1 * COS_DELTA; - x1 = x1_new; - - F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; - y2 = x2 * SIN_DELTA + y2 * COS_DELTA; - x2 = x2_new; - } - } - gGL.end(); -} - -void gl_rect_2d_simple_tex( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(width, height); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(0, height); - - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(0, 0); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(width, 0); - - gGL.end(); -} - -void gl_rect_2d_simple( S32 width, S32 height ) -{ - gGL.begin( LLRender::QUADS ); - gGL.vertex2i(width, height); - gGL.vertex2i(0, height); - gGL.vertex2i(0, 0); - gGL.vertex2i(width, 0); - gGL.end(); -} - -void gl_segmented_rect_2d_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const U32 edges) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2f(0.f, 0.f); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(border_width_left.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - // draw bottom right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((width_vec - border_width_right).mV); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2fv(width_vec.mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); - gGL.vertex2fv(border_height_bottom.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - // draw right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); - - gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + border_height_bottom).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((border_width_left + height_vec).mV); - - // draw top right - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2fv((width_vec + height_vec).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); - } - gGL.end(); - - gGL.popUIMatrix(); -} - -//FIXME: rewrite to use scissor? -void gl_segmented_rect_2d_fragment_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const F32 start_fragment, - const F32 end_fragment, - const U32 edges) -{ - S32 width = llabs(right - left); - S32 height = llabs(top - bottom); - - gGL.pushUIMatrix(); - - gGL.translateUI((F32)left, (F32)bottom, 0.f); - LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height); - - if (border_uv_scale.mV[VX] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VX]; - } - if (border_uv_scale.mV[VY] > 0.5f) - { - border_uv_scale *= 0.5f / border_uv_scale.mV[VY]; - } - - F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f); - LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero; - LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero; - LLVector2 width_vec((F32)width, 0.f); - LLVector2 height_vec(0.f, (F32)height); - - F32 middle_start = border_scale / (F32)width; - F32 middle_end = 1.f - middle_start; - - F32 u_min; - F32 u_max; - LLVector2 x_min; - LLVector2 x_max; - - gGL.begin(LLRender::QUADS); - { - if (start_fragment < middle_start) - { - u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; - u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; - x_min = (start_fragment / middle_start) * border_width_left; - x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; - - // draw bottom left - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw left - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top left - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_start || start_fragment < middle_end) - { - x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec; - x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec; - - // draw bottom middle - gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv(x_min.mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); - gGL.vertex2fv((x_max).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw middle - gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top middle - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - - if (end_fragment > middle_end) - { - u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; - u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; - x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); - x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); - - // draw bottom right - gGL.texCoord2f(u_min, 0.f); - gGL.vertex2fv((x_min).mV); - - gGL.texCoord2f(u_max, 0.f); - gGL.vertex2fv(x_max.mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - // draw right - gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + border_height_bottom).mV); - - gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + border_height_bottom).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - // draw top right - gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); - gGL.vertex2fv((x_max + height_vec - border_height_top).mV); - - gGL.texCoord2f(u_max, 1.f); - gGL.vertex2fv((x_max + height_vec).mV); - - gGL.texCoord2f(u_min, 1.f); - gGL.vertex2fv((x_min + height_vec).mV); - } - } - gGL.end(); - - gGL.popUIMatrix(); -} - -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, - const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, - const U32 edges) -{ - LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; - LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - - LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; - LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - - - gGL.begin(LLRender::QUADS); - { - // draw bottom left - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(0.f, 0.f, 0.f); - - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); - - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); - - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); - - // draw bottom middle - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); - - // draw bottom right - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); - - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3fv(width_vec.mV); - - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - // draw left - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); - - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); - - // draw middle - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); - - // draw right - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); - - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); - - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); - - // draw top left - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); - - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3fv((height_vec).mV); - - // draw top middle - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); - - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); - - // draw top right - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); - - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); - - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3fv((width_vec + height_vec).mV); - - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); - } - gGL.end(); - -} - -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ - gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -} - void LLUI::initClass(const settings_map_t& settings, LLImageProviderInterface* image_provider, LLUIAudioCallback audio_callback, const LLVector2* scale_factor, const std::string& language) { + LLRender2D::initClass(image_provider, scale_factor); sSettingGroups = settings; if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) || @@ -1632,9 +151,7 @@ void LLUI::initClass(const settings_map_t& settings, llerrs << "Failure to initialize configuration groups" << llendl; } - sImageProvider = image_provider; sAudioCallback = audio_callback; - sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor; sWindow = NULL; // set later in startup LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow"); @@ -1668,10 +185,7 @@ void LLUI::initClass(const settings_map_t& settings, void LLUI::cleanupClass() { - if(sImageProvider) - { - sImageProvider->cleanUp(); -} + LLRender2D::cleanupClass(); } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) @@ -1695,60 +209,12 @@ void LLUI::dirtyRect(LLRect rect) } } - -//static -void LLUI::translate(F32 x, F32 y, F32 z) -{ - gGL.translateUI(x,y,z); - LLFontGL::sCurOrigin.mX += (S32) x; - LLFontGL::sCurOrigin.mY += (S32) y; - LLFontGL::sCurDepth += z; -} - -//static -void LLUI::pushMatrix() -{ - gGL.pushUIMatrix(); - LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth)); -} - -//static -void LLUI::popMatrix() -{ - gGL.popUIMatrix(); - LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; - LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second; - LLFontGL::sOriginStack.pop_back(); -} - -//static -void LLUI::loadIdentity() -{ - gGL.loadUIIdentity(); - LLFontGL::sCurOrigin.mX = 0; - LLFontGL::sCurOrigin.mY = 0; - LLFontGL::sCurDepth = 0.f; -} - -//static -void LLUI::setScaleFactor(const LLVector2 &scale_factor) -{ - sGLScaleFactor = scale_factor; -} - -//static -void LLUI::setLineWidth(F32 width) -{ - gGL.flush(); - glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f)); -} - //static void LLUI::setMousePositionScreen(S32 x, S32 y) { S32 screen_x, screen_y; - screen_x = llround((F32)x * sGLScaleFactor.mV[VX]); - screen_y = llround((F32)y * sGLScaleFactor.mV[VY]); + screen_x = llround((F32)x * getScaleFactor().mV[VX]); + screen_y = llround((F32)y * getScaleFactor().mV[VY]); LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } @@ -1759,8 +225,8 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) LLCoordWindow cursor_pos_window; getWindow()->getCursorPosition(&cursor_pos_window); LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); - *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]); - *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]); + *x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); + *y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]); } //static @@ -1925,21 +391,21 @@ LLVector2 LLUI::getWindowSize() LLCoordWindow window_rect; sWindow->getSize(&window_rect); - return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]); + return LLVector2(window_rect.mX / getScaleFactor().mV[VX], window_rect.mY / getScaleFactor().mV[VY]); } //static void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y) { - *gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]); - *gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]); + *gl_x = llround((F32)screen_x * getScaleFactor().mV[VX]); + *gl_y = llround((F32)screen_y * getScaleFactor().mV[VY]); } //static void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y) { - *screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]); - *screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]); + *screen_x = llround((F32)gl_x / getScaleFactor().mV[VX]); + *screen_y = llround((F32)gl_y / getScaleFactor().mV[VY]); } //static @@ -1956,27 +422,6 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen) glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom); } -//static -LLPointer LLUI::getUIImageByID(const LLUUID& image_id, S32 priority) -{ - if (sImageProvider) - { - return sImageProvider->getUIImageByID(image_id, priority); - } - else - { - return NULL; - } -} - -//static -LLPointer LLUI::getUIImage(const std::string& name, S32 priority) -{ - if (!name.empty() && sImageProvider) - return sImageProvider->getUIImage(name, priority); - else - return NULL; -} LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 28e84fa444..a38ae9a560 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -1,6 +1,6 @@ /** * @file llui.h - * @brief GL function declarations and other general static UI services. + * @brief General static UI services. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,122 +24,37 @@ * $/LicenseInfo$ */ -// All immediate-mode gl drawing should happen here. #ifndef LL_LLUI_H #define LL_LLUI_H -#include "llpointer.h" // LLPointer<> #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" -#include "llglslshader.h" +#include "v2math.h" #include "llinitparam.h" #include "llregistry.h" +#include "llrender2dutils.h" +#include "llpointer.h" #include "lluicolor.h" #include "lluicolortable.h" +#include "lluiimage.h" #include #include "lllazyvalue.h" #include "llframetimer.h" #include -// LLUIFactory -#include "llsd.h" - // for initparam specialization #include "llfontgl.h" -class LLColor4; -class LLVector3; -class LLVector2; -class LLUIImage; class LLUUID; class LLWindow; class LLView; class LLHelp; -// UI colors -extern const LLColor4 UI_VERTEX_COLOR; void make_ui_sound(const char* name); -BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom); -void gl_state_for_2d(S32 width, S32 height); - -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2); -void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ); -void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled); -void gl_rect_2d_simple( S32 width, S32 height ); - -void gl_draw_x(const LLRect& rect, const LLColor4& color); - -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE ); -void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE ); -void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE ); -void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f); - -void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines); - -void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled); -void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle); -void gl_deep_circle( F32 radius, F32 depth ); -void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center ); -void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac); -void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); -void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); - -void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); - -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); - -void gl_rect_2d_simple_tex( S32 width, S32 height ); - -// segmented rectangles - -/* - TL |______TOP_________| TR - /| |\ - _/_|__________________|_\_ - L| | MIDDLE | |R - _|_|__________________|_|_ - \ | BOTTOM | / - BL\|__________________|/ BR - | | -*/ - -typedef enum e_rounded_edge -{ - ROUNDED_RECT_LEFT = 0x1, - ROUNDED_RECT_TOP = 0x2, - ROUNDED_RECT_RIGHT = 0x4, - ROUNDED_RECT_BOTTOM = 0x8, - ROUNDED_RECT_ALL = 0xf -}ERoundedEdge; - - -void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); - -inline void gl_rect_2d( const LLRect& rect, BOOL filled ) -{ - gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled ); -} - -inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled) -{ - gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled ); -} - class LLImageProviderInterface; typedef void (*LLUIAudioCallback)(const LLUUID& uuid); @@ -280,10 +195,10 @@ public: static void cleanupClass(); static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& ); - static void pushMatrix(); - static void popMatrix(); - static void loadIdentity(); - static void translate(F32 x, F32 y, F32 z = 0.0f); + static void pushMatrix() { LLRender2D::pushMatrix(); } + static void popMatrix() { LLRender2D::popMatrix(); } + static void loadIdentity() { LLRender2D::loadIdentity(); } + static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); } static LLRect sDirtyRect; static BOOL sDirty; @@ -333,10 +248,13 @@ public: static void getMousePositionScreen(S32 *x, S32 *y); static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y); static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y); - static void setScaleFactor(const LLVector2& scale_factor); - static void setLineWidth(F32 width); - static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0); - static LLPointer getUIImage(const std::string& name, S32 priority = 0); + static LLVector2& getScaleFactor() { return LLRender2D::sGLScaleFactor; } + static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::setScaleFactor(scale_factor); } + static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); } + static LLPointer getUIImageByID(const LLUUID& image_id, S32 priority = 0) + { return LLRender2D::getUIImageByID(image_id, priority); } + static LLPointer getUIImage(const std::string& name, S32 priority = 0) + { return LLRender2D::getUIImage(name, priority); } static LLVector2 getWindowSize(); static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y); static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y); @@ -365,12 +283,10 @@ public: // static settings_map_t sSettingGroups; static LLUIAudioCallback sAudioCallback; - static LLVector2 sGLScaleFactor; static LLWindow* sWindow; static LLView* sRootView; static LLHelp* sHelpImpl; private: - static LLImageProviderInterface* sImageProvider; static std::vector sXUIPaths; static LLFrameTimer sMouseIdleTimer; static add_popup_t sAddPopupFunc; @@ -381,18 +297,6 @@ private: // Moved LLLocalClipRect to lllocalcliprect.h -//RN: maybe this needs to moved elsewhere? -class LLImageProviderInterface -{ -protected: - LLImageProviderInterface() {}; - virtual ~LLImageProviderInterface() {}; -public: - virtual LLPointer getUIImage(const std::string& name, S32 priority) = 0; - virtual LLPointer getUIImageByID(const LLUUID& id, S32 priority) = 0; - virtual void cleanUp() = 0; -}; - class LLCallbackRegistry { public: @@ -603,7 +507,4 @@ namespace LLInitParam }; } -extern LLGLSLShader gSolidColorProgram; -extern LLGLSLShader gUIProgram; - #endif diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp deleted file mode 100644 index 1d9ce29ba9..0000000000 --- a/indra/llui/lluiimage.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file lluiimage.cpp - * @brief UI implementation - * - * $LicenseInfo:firstyear=2007&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$ - */ - -// Utilities functions the user interface needs - -//#include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -// Project includes -#include "lluiimage.h" -#include "llui.h" - -LLUIImage::LLUIImage(const std::string& name, LLPointer image) -: mName(name), - mImage(image), - mScaleRegion(0.f, 1.f, 1.f, 0.f), - mClipRegion(0.f, 1.f, 1.f, 0.f), - mUniformScaling(TRUE), - mNoClip(TRUE), - mImageLoaded(NULL) -{ -} - -LLUIImage::~LLUIImage() -{ - delete mImageLoaded; -} - -void LLUIImage::setClipRegion(const LLRectf& region) -{ - mClipRegion = region; - mNoClip = mClipRegion.mLeft == 0.f - && mClipRegion.mRight == 1.f - && mClipRegion.mBottom == 0.f - && mClipRegion.mTop == 1.f; -} - -void LLUIImage::setScaleRegion(const LLRectf& region) -{ - mScaleRegion = region; - mUniformScaling = mScaleRegion.mLeft == 0.f - && mScaleRegion.mRight == 1.f - && mScaleRegion.mBottom == 0.f - && mScaleRegion.mTop == 1.f; -} - -//TODO: move drawing implementation inside class -void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const -{ - gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion); -} - -void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const -{ - if (mUniformScaling) - { - gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); - } - else - { - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - FALSE, - mClipRegion, - mScaleRegion); - } -} - -void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const -{ - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - TRUE, - mClipRegion, - mScaleRegion); -} - -void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const -{ - LLRect border_rect; - border_rect.setOriginAndSize(x, y, width, height); - border_rect.stretch(border_width, border_width); - drawSolid(border_rect, color); -} - -S32 LLUIImage::getWidth() const -{ - // return clipped dimensions of actual image area - return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); -} - -S32 LLUIImage::getHeight() const -{ - // return clipped dimensions of actual image area - return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); -} - -S32 LLUIImage::getTextureWidth() const -{ - return mImage->getWidth(0); -} - -S32 LLUIImage::getTextureHeight() const -{ - return mImage->getHeight(0); -} - -boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) -{ - if (!mImageLoaded) - { - mImageLoaded = new image_loaded_signal_t(); - } - return mImageLoaded->connect(cb); -} - - -void LLUIImage::onImageLoaded() -{ - if (mImageLoaded) - { - (*mImageLoaded)(); - } -} - - -namespace LLInitParam -{ - void ParamValue >::updateValueFromBlock() - { - // The keyword "none" is specifically requesting a null image - // do not default to current value. Used to overwrite template images. - if (name() == "none") - { - updateValue(NULL); - return; - } - - LLUIImage* imagep = LLUI::getUIImage(name()); - if (imagep) - { - updateValue(imagep); - } - } - - void ParamValue >::updateBlockFromValue(bool make_block_authoritative) - { - if (getValue() == NULL) - { - name.set("none", make_block_authoritative); - } - else - { - name.set(getValue()->getName(), make_block_authoritative); - } - } - - - bool ParamCompare::equals( - LLUIImage* const &a, - LLUIImage* const &b) - { - // force all LLUIImages for XML UI export to be "non-default" - if (!a && !b) - return false; - else - return (a == b); - } -} - diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h deleted file mode 100644 index f07e8fa746..0000000000 --- a/indra/llui/lluiimage.h +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @file lluiimage.h - * @brief wrapper for images used in the UI that handles smart scaling, etc. - * - * $LicenseInfo:firstyear=2007&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_LLUIIMAGE_H -#define LL_LLUIIMAGE_H - -#include "v4color.h" -#include "llpointer.h" -#include "llrefcount.h" -#include "llrefcount.h" -#include "llrect.h" -#include -#include -#include "llinitparam.h" -#include "lltexture.h" - -extern const LLColor4 UI_VERTEX_COLOR; - -class LLUIImage : public LLRefCount -{ -public: - typedef boost::signals2::signal image_loaded_signal_t; - - LLUIImage(const std::string& name, LLPointer image); - virtual ~LLUIImage(); - - void setClipRegion(const LLRectf& region); - void setScaleRegion(const LLRectf& region); - - LLPointer getImage() { return mImage; } - const LLPointer& getImage() const { return mImage; } - - void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; - void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; - void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } - - void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; - void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } - void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); } - - void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; - void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } - void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } - - const std::string& getName() const { return mName; } - - virtual S32 getWidth() const; - virtual S32 getHeight() const; - - // returns dimensions of underlying textures, which might not be equal to ui image portion - S32 getTextureWidth() const; - S32 getTextureHeight() const; - - boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb ); - - void onImageLoaded(); - -protected: - image_loaded_signal_t* mImageLoaded; - - std::string mName; - LLRectf mScaleRegion; - LLRectf mClipRegion; - LLPointer mImage; - BOOL mUniformScaling; - BOOL mNoClip; -}; - -namespace LLInitParam -{ - template<> - class ParamValue > - : public CustomParamValue - { - typedef boost::add_reference::type>::type T_const_ref; - typedef CustomParamValue super_t; - public: - Optional name; - - ParamValue(LLUIImage* const& image) - : super_t(image) - { - updateBlockFromValue(false); - addSynonym(name, "name"); - } - - void updateValueFromBlock(); - void updateBlockFromValue(bool make_block_authoritative); - }; - - // Need custom comparison function for our test app, which only loads - // LLUIImage* as NULL. - template<> - struct ParamCompare - { - static bool equals(LLUIImage* const &a, LLUIImage* const &b); - }; -} - -typedef LLPointer LLUIImagePtr; -#endif diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 8f0a48018f..6c51024d2c 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -31,7 +31,7 @@ #include "llurlentry_stub.cpp" #include "lltut.h" #include "../lluicolortable.h" -#include "../lluiimage.h" +#include "lluiimage.h" #include diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 963473c92a..88a2cfb1e0 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -28,7 +28,7 @@ #include "linden_common.h" #include "../llurlmatch.h" -#include "../lluiimage.h" +#include "lluiimage.h" #include "lltut.h" // link seams diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 21b1512e58..a17a3b11ec 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -304,6 +304,7 @@ set(viewer_SOURCE_FILES llinventorybridge.cpp llinventoryfilter.cpp llinventoryfunctions.cpp + llinventoryicon.cpp llinventoryitemslist.cpp llinventorylistitem.cpp llinventorymodel.cpp @@ -872,6 +873,7 @@ set(viewer_HEADER_FILES llinventorybridge.h llinventoryfilter.h llinventoryfunctions.h + llinventoryicon.h llinventoryitemslist.h llinventorylistitem.h llinventorymodel.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6ca77ba4dd..fbf15ff5ce 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -771,7 +771,7 @@ bool LLAppViewer::init() LLUI::initClass(settings_map, LLUIImageList::getInstance(), ui_audio_callback, - &LLUI::sGLScaleFactor); + &LLUI::getScaleFactor()); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; // Setup paths and LLTrans after LLUI::initClass has been called. diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 809d344d01..df802f0a0e 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -40,6 +40,7 @@ #include "llcheckboxctrl.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" // for gInventory #include "llfirstuse.h" #include "llfloaterreg.h" diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 1208c9378e..60fa53f491 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -79,10 +79,10 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); - left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]); - right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]); - top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]); - bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]); + left = llround((F32) left * LLUI::getScaleFactor().mV[VX]); + right = llround((F32) right * LLUI::getScaleFactor().mV[VX]); + top = llround((F32) top * LLUI::getScaleFactor().mV[VY]); + bottom = llround((F32) bottom * LLUI::getScaleFactor().mV[VY]); F32 old_far_plane = LLViewerCamera::getInstance()->getFar(); F32 old_near_plane = LLViewerCamera::getInstance()->getNear(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index dc6147898a..4834d8dd70 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -50,6 +50,7 @@ #include "llclipboard.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" @@ -1510,7 +1511,7 @@ LLUIImagePtr LLItemBridge::getIcon() const mIsLink); } - return LLInventoryIcon::getIcon(LLInventoryIcon::ICONNAME_OBJECT); + return LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT); } PermissionMask LLItemBridge::getPermissionMask() const diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp new file mode 100644 index 0000000000..14efc25fb9 --- /dev/null +++ b/indra/newview/llinventoryicon.cpp @@ -0,0 +1,183 @@ +/** + * @file llinventoryicon.cpp + * @brief Implementation of the inventory icon. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llinventoryicon.h" + +#include "lldictionary.h" +#include "llinventorydefines.h" +#include "llui.h" +#include "llwearabletype.h" + +struct IconEntry : public LLDictionaryEntry +{ + IconEntry(const std::string &item_name) + : + LLDictionaryEntry(item_name) + {} +}; + +class LLIconDictionary : public LLSingleton, + public LLDictionary +{ +public: + LLIconDictionary(); +}; + +LLIconDictionary::LLIconDictionary() +{ + addEntry(LLInventoryType::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); + addEntry(LLInventoryType::ICONNAME_SOUND, new IconEntry("Inv_Sound")); + addEntry(LLInventoryType::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryType::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard")); + addEntry(LLInventoryType::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryType::ICONNAME_LANDMARK_VISITED, new IconEntry("Inv_Landmark")); + addEntry(LLInventoryType::ICONNAME_SCRIPT, new IconEntry("Inv_Script")); + addEntry(LLInventoryType::ICONNAME_CLOTHING, new IconEntry("Inv_Clothing")); + addEntry(LLInventoryType::ICONNAME_OBJECT, new IconEntry("Inv_Object")); + addEntry(LLInventoryType::ICONNAME_OBJECT_MULTI, new IconEntry("Inv_Object_Multi")); + addEntry(LLInventoryType::ICONNAME_NOTECARD, new IconEntry("Inv_Notecard")); + addEntry(LLInventoryType::ICONNAME_BODYPART, new IconEntry("Inv_Skin")); + addEntry(LLInventoryType::ICONNAME_SNAPSHOT, new IconEntry("Inv_Snapshot")); + + addEntry(LLInventoryType::ICONNAME_BODYPART_SHAPE, new IconEntry("Inv_BodyShape")); + addEntry(LLInventoryType::ICONNAME_BODYPART_SKIN, new IconEntry("Inv_Skin")); + addEntry(LLInventoryType::ICONNAME_BODYPART_HAIR, new IconEntry("Inv_Hair")); + addEntry(LLInventoryType::ICONNAME_BODYPART_EYES, new IconEntry("Inv_Eye")); + + addEntry(LLInventoryType::ICONNAME_CLOTHING_SHIRT, new IconEntry("Inv_Shirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_PANTS, new IconEntry("Inv_Pants")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SHOES, new IconEntry("Inv_Shoe")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SOCKS, new IconEntry("Inv_Socks")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_JACKET, new IconEntry("Inv_Jacket")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_GLOVES, new IconEntry("Inv_Gloves")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, new IconEntry("Inv_Undershirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, new IconEntry("Inv_Underpants")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_SKIRT, new IconEntry("Inv_Skirt")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_ALPHA, new IconEntry("Inv_Alpha")); + addEntry(LLInventoryType::ICONNAME_CLOTHING_TATTOO, new IconEntry("Inv_Tattoo")); + addEntry(LLInventoryType::ICONNAME_ANIMATION, new IconEntry("Inv_Animation")); + addEntry(LLInventoryType::ICONNAME_GESTURE, new IconEntry("Inv_Gesture")); + + addEntry(LLInventoryType::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics")); + + addEntry(LLInventoryType::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem")); + addEntry(LLInventoryType::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder")); + addEntry(LLInventoryType::ICONNAME_MESH, new IconEntry("Inv_Mesh")); + + addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid")); + + addEntry(LLInventoryType::ICONNAME_NONE, new IconEntry("NONE")); +} + +LLUIImagePtr LLInventoryIcon::getIcon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 misc_flag, + BOOL item_is_multi) +{ + const std::string& icon_name = getIconName(asset_type, inventory_type, misc_flag, item_is_multi); + return LLUI::getUIImage(icon_name); +} + +LLUIImagePtr LLInventoryIcon::getIcon(LLInventoryType::EIconName idx) +{ + return LLUI::getUIImage(getIconName(idx)); +} + +const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 misc_flag, + BOOL item_is_multi) +{ + LLInventoryType::EIconName idx = LLInventoryType::ICONNAME_OBJECT; + if (item_is_multi) + { + idx = LLInventoryType::ICONNAME_OBJECT_MULTI; + return getIconName(idx); + } + + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + idx = (inventory_type == LLInventoryType::IT_SNAPSHOT) ? LLInventoryType::ICONNAME_SNAPSHOT : LLInventoryType::ICONNAME_TEXTURE; + break; + case LLAssetType::AT_SOUND: + idx = LLInventoryType::ICONNAME_SOUND; + break; + case LLAssetType::AT_CALLINGCARD: + idx = (misc_flag != 0) ? LLInventoryType::ICONNAME_CALLINGCARD_ONLINE : LLInventoryType::ICONNAME_CALLINGCARD_OFFLINE; + break; + case LLAssetType::AT_LANDMARK: + idx = (misc_flag != 0) ? LLInventoryType::ICONNAME_LANDMARK_VISITED : LLInventoryType::ICONNAME_LANDMARK; + break; + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + idx = LLInventoryType::ICONNAME_SCRIPT; + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + idx = assignWearableIcon(misc_flag); + break; + case LLAssetType::AT_NOTECARD: + idx = LLInventoryType::ICONNAME_NOTECARD; + break; + case LLAssetType::AT_ANIMATION: + idx = LLInventoryType::ICONNAME_ANIMATION; + break; + case LLAssetType::AT_GESTURE: + idx = LLInventoryType::ICONNAME_GESTURE; + break; + case LLAssetType::AT_LINK: + idx = LLInventoryType::ICONNAME_LINKITEM; + break; + case LLAssetType::AT_LINK_FOLDER: + idx = LLInventoryType::ICONNAME_LINKFOLDER; + break; + case LLAssetType::AT_OBJECT: + idx = LLInventoryType::ICONNAME_OBJECT; + break; + case LLAssetType::AT_MESH: + idx = LLInventoryType::ICONNAME_MESH; + default: + break; + } + + return getIconName(idx); +} + + +const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx) +{ + const IconEntry *entry = LLIconDictionary::instance().lookup(idx); + return entry->mName; +} + +LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag) +{ + const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag); + return LLWearableType::getIconName(wearable_type); +} diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h new file mode 100644 index 0000000000..659448143d --- /dev/null +++ b/indra/newview/llinventoryicon.h @@ -0,0 +1,56 @@ +/** + * @file llinventoryfunctions.h + * @brief Miscellaneous inventory-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYICON_H +#define LL_LLINVENTORYICON_H + +#include "llassettype.h" +#include "llinventorytype.h" +#include "lluiimage.h" + +class LLInventoryIcon +{ +public: + static const std::string& getIconName(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, + U32 misc_flag = 0, // different meanings depending on item type + BOOL item_is_multi = FALSE); + static const std::string& getIconName(LLInventoryType::EIconName idx); + + static LLUIImagePtr getIcon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, + U32 misc_flag = 0, // different meanings depending on item type + BOOL item_is_multi = FALSE); + static LLUIImagePtr getIcon(LLInventoryType::EIconName idx); + +protected: + static LLInventoryType::EIconName assignWearableIcon(U32 misc_flag); +}; +#endif // LL_LLINVENTORYICON_H + + + diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index 3e0849a795..26041767fd 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -37,6 +37,7 @@ #include "lltextutil.h" // newview +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llviewerinventory.h" diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 7650fe9229..04744ab34c 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -119,8 +119,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]); setTextureSize(screen_width, screen_height); } @@ -469,8 +469,8 @@ void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)width * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)height * LLUI::getScaleFactor().mV[VY]); // when floater is minimized, these sizes are negative if ( screen_height > 0 && screen_width > 0 ) @@ -687,7 +687,7 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); if(mClearCache) { @@ -770,7 +770,7 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -884,14 +884,14 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); } - x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]); + x = llround((F32)x * LLUI::getScaleFactor().mV[VX]); if ( ! coords_opengl ) { - y = llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(y) * LLUI::getScaleFactor().mV[VY]); } else { - y = llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(getRect().getHeight() - y) * LLUI::getScaleFactor().mV[VY]); }; } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 31c0e3d01a..9a3ea0774b 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -35,6 +35,7 @@ #include "llviewerinventory.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llagent.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1ca24f3031..7c3425d71b 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -47,6 +47,7 @@ #include "llfolderview.h" #include "llinventorybridge.h" #include "llinventorydefines.h" +#include "llinventoryicon.h" #include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llpreviewanim.h" diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..64be5408be 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -33,6 +33,7 @@ #include "llbutton.h" #include "lliconctrl.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llnotifications.h" #include "llviewertexteditor.h" diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 3b486efd7e..cc697f8510 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1440,7 +1440,7 @@ void render_ui_2d() gGL.pushMatrix(); S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); - gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); + gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f); gGL.translatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgentCamera.mHUDCurZoom; gGL.scalef(zoom,zoom,1.f); @@ -1478,10 +1478,10 @@ void render_ui_2d() LLUI::sDirtyRect = last_rect; last_rect = t_rect; - last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]); - last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]); - last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]); - last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]); + last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); + last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); + last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); + last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]); LLRect clip_rect(last_rect); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d5ca01931f..dd29260f70 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2140,7 +2140,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) calcDisplayScale(); - BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor; + BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); LLUI::setScaleFactor(mDisplayScale); // update our window rectangle @@ -2346,7 +2346,7 @@ void LLViewerWindow::draw() // scale view by UI global scale factor and aspect ratio correction factor gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - LLVector2 old_scale_factor = LLUI::sGLScaleFactor; + LLVector2 old_scale_factor = LLUI::getScaleFactor(); // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); @@ -2360,7 +2360,7 @@ void LLViewerWindow::draw() (F32)getWindowHeightScaled() * -(F32)pos_y, 0.f); gGL.scalef(zoom_factor, zoom_factor, 1.f); - LLUI::sGLScaleFactor *= zoom_factor; + LLUI::getScaleFactor() *= zoom_factor; } // Draw tool specific overlay on world @@ -2408,7 +2408,7 @@ void LLViewerWindow::draw() LLFontGL::HCENTER, LLFontGL::TOP); } - LLUI::sGLScaleFactor = old_scale_factor; + LLUI::setScaleFactor(old_scale_factor); } LLUI::popMatrix(); gGL.popMatrix(); @@ -3208,8 +3208,8 @@ void LLViewerWindow::updateLayout() void LLViewerWindow::updateMouseDelta() { - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); - S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index c7e9215643..c196d70617 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -34,6 +34,7 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "lltransutil.h" #include "llviewerattachmenu.h" #include "llvoavatarself.h" diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index a3ccf87cfc..428be8efb9 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -421,7 +421,7 @@ void LLWorldMapView::draw() { // Inform the fetch mechanism of the size we need S32 draw_size = llround(sMapScale); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + overlayimage->setKnownDrawSize(llround(draw_size * LLUI::getScaleFactor().mV[VX]), llround(draw_size * LLUI::getScaleFactor().mV[VY])); // Draw something whenever we have enough info if (overlayimage->hasGLTexture()) { -- cgit v1.2.3 From b77e2eff481512667c35bc99946fb62eca1be169 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 8 Sep 2012 06:20:19 +0000 Subject: Fixed #include typo --- indra/llappearance/llwearabletype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 3a8e1b8be3..aa0afe348a 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "llwearabletype.h" #include "llinventorytype.h" -#include "llui/lltrans.h" +#include "lltrans.h" struct WearableEntry : public LLDictionaryEntry { -- cgit v1.2.3 From e1580128ab2a42ecd4019ef35069f9e939dc4ff2 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sun, 9 Sep 2012 12:12:19 +0000 Subject: Fixed crashes on login. Moved most of the remaining character/skeleton generation code into llappearance. Moved non-rendering related LLViewerJoint functionality into LLAvatarJoint. --- indra/llappearance/llavatarappearance.cpp | 245 ++++++++++++++-- indra/llappearance/llavatarappearance.h | 27 +- indra/llappearance/llavatarappearancedefines.cpp | 4 +- indra/llappearance/llavatarappearancedefines.h | 10 +- indra/llappearance/llavatarjoint.cpp | 120 ++++++-- indra/llappearance/llavatarjoint.h | 24 +- indra/llappearance/llavatarjointmesh.cpp | 10 + indra/llappearance/llavatarjointmesh.h | 12 +- indra/llappearance/lljointpickname.h | 3 + indra/llcharacter/llcharacter.h | 7 - indra/llcharacter/lljoint.cpp | 30 +- indra/llcharacter/lljoint.h | 8 +- indra/llcharacter/tests/lljoint_test.cpp | 6 +- indra/newview/llfloaterimagepreview.cpp | 4 +- indra/newview/llviewerjoint.cpp | 356 +---------------------- indra/newview/llviewerjoint.h | 76 +---- indra/newview/llviewerjointmesh.cpp | 15 - indra/newview/llviewerjointmesh.h | 7 +- indra/newview/llvoavatar.cpp | 246 +++++----------- indra/newview/llvoavatar.h | 7 +- indra/newview/llvoavatarself.cpp | 66 ----- indra/newview/llvoavatarself.h | 1 - 22 files changed, 508 insertions(+), 776 deletions(-) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 406e6153e0..e2dfa2fb74 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -24,8 +24,13 @@ * $/LicenseInfo$ */ -#include "linden_common.h" +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif +#include "linden_common.h" #include "llavatarappearance.h" #include "llavatarappearancedefines.h" @@ -36,9 +41,20 @@ #include "llpolymorph.h" #include "llpolymesh.h" #include "llpolyskeletaldistortion.h" +#include "llstl.h" #include "lltexglobalcolor.h" #include "llwearabledata.h" + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include + +using namespace LLAvatarAppearanceDefines; + //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- @@ -153,7 +169,9 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mWearableData(wearable_data) { - llassert(mWearableData); + LLMemType mt(LLMemType::MTYPE_AVATAR); + + llassert_always(mWearableData); mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) { @@ -167,13 +185,85 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mIsBuilt = FALSE; - mNumJoints = 0; - mSkeleton = NULL; - mNumCollisionVolumes = 0; mCollisionVolumes = NULL; +} + +// virtual +void LLAvatarAppearance::initInstance() +{ + //------------------------------------------------------------------------- + // initialize joint, mesh and shape members + //------------------------------------------------------------------------- + mRoot = createAvatarJoint(); + mRoot->setName( "mRoot" ); + + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + ++iter) + { + const EMeshIndex mesh_index = iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; + LLAvatarJoint* joint = createAvatarJoint(); + joint->setName(mesh_dict->mName); + joint->setMeshID(mesh_index); + mMeshLOD.push_back(joint); + + /* mHairLOD.setName("mHairLOD"); + mHairMesh0.setName("mHairMesh0"); + mHairMesh0.setMeshID(MESH_ID_HAIR); + mHairMesh1.setName("mHairMesh1"); */ + for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) + { + LLAvatarJointMesh* mesh = createAvatarJointMesh(); + std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast(lod); + // We pre-pended an m - need to capitalize first character for camelCase + mesh_name[1] = toupper(mesh_name[1]); + mesh->setName(mesh_name); + mesh->setMeshID(mesh_index); + mesh->setPickName(mesh_dict->mPickName); + mesh->setIsTransparent(FALSE); + switch((int)mesh_index) + { + case MESH_ID_HAIR: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_SKIRT: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_EYEBALL_LEFT: + case MESH_ID_EYEBALL_RIGHT: + mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); + break; + } + + joint->mMeshParts.push_back(mesh); + } + } - mRoot = new LLAvatarJoint(); + //------------------------------------------------------------------------- + // associate baked textures with meshes + //------------------------------------------------------------------------- + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); + ++iter) + { + const EMeshIndex mesh_index = iter->first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; + const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; + // Skip it if there's no associated baked texture. + if (baked_texture_index == BAKED_NUM_INDICES) continue; + + for (avatar_joint_mesh_list_t::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); + iter != mMeshLOD[mesh_index]->mMeshParts.end(); + ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + mBakedTextureDatas[(int)baked_texture_index].mJointMeshes.push_back(mesh); + } + } + + buildCharacter(); } @@ -187,7 +277,7 @@ LLAvatarAppearance::~LLAvatarAppearance() for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { deleteAndClear(mBakedTextureDatas[i].mTexLayerSet); - mBakedTextureDatas[i].mMeshes.clear(); + mBakedTextureDatas[i].mJointMeshes.clear(); for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin(); iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++) @@ -200,23 +290,21 @@ LLAvatarAppearance::~LLAvatarAppearance() mRoot->removeAllChildren(); mJointMap.clear(); - deleteAndClearArray(mSkeleton); + clearSkeleton(); deleteAndClearArray(mCollisionVolumes); - mNumJoints = 0; - deleteAndClear(mTexSkinColor); deleteAndClear(mTexHairColor); deleteAndClear(mTexEyeColor); - std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); - mMeshes.clear(); + std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer()); + mPolyMeshes.clear(); - for (std::vector::iterator jointIter = mMeshLOD.begin(); + for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin(); jointIter != mMeshLOD.end(); ++jointIter) { - LLAvatarJoint* joint = (LLAvatarJoint *) *jointIter; + LLAvatarJoint* joint = *jointIter; std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); joint->mMeshParts.clear(); } @@ -504,6 +592,22 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent return TRUE; } +//----------------------------------------------------------------------------- +// allocateCharacterJoints() +//----------------------------------------------------------------------------- +BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) +{ + clearSkeleton(); + + for(S32 joint_num = 0; joint_num < (S32)num; joint_num++) + { + mSkeleton.push_back(createAvatarJoint(joint_num)); + } + + return TRUE; +} + + //----------------------------------------------------------------------------- // buildSkeleton() //----------------------------------------------------------------------------- @@ -548,6 +652,15 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) return TRUE; } +//----------------------------------------------------------------------------- +// clearSkeleton() +//----------------------------------------------------------------------------- +void LLAvatarAppearance::clearSkeleton() +{ + std::for_each(mSkeleton.begin(), mSkeleton.end(), DeletePointer()); + mSkeleton.clear(); +} + //----------------------------------------------------------------------------- // LLAvatarAppearance::buildCharacter() // Deferred initialization and rebuild of the avatar. @@ -569,6 +682,21 @@ void LLAvatarAppearance::buildCharacter() mJointMap.clear(); mIsBuilt = FALSE; + //------------------------------------------------------------------------- + // clear mesh data + //------------------------------------------------------------------------- + for (avatar_joint_list_t::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); ++jointIter) + { + LLAvatarJoint* joint = *jointIter; + for (avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); + meshIter != joint->mMeshParts.end(); ++meshIter) + { + LLAvatarJointMesh * mesh = *meshIter; + mesh->setMesh(NULL); + } + } + //------------------------------------------------------------------------- // (re)load our skeleton and meshes //------------------------------------------------------------------------- @@ -755,7 +883,7 @@ BOOL LLAvatarAppearance::loadAvatar() } - loadLayersets(); + loadLayersets(); // avatar_lad.xml : for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); @@ -791,7 +919,17 @@ BOOL LLAvatarAppearance::loadAvatar() //----------------------------------------------------------------------------- BOOL LLAvatarAppearance::loadSkeletonNode () { - mRoot->addChild( &mSkeleton[0] ); + mRoot->addChild( mSkeleton[0] ); + + // make meshes children before calling parent version of the function + for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); + ++iter) + { + LLAvatarJoint *joint = *iter; + joint->mUpdateXform = FALSE; + joint->setMeshesToChildren(); + } mRoot->addChild(mMeshLOD[MESH_ID_HEAD]); mRoot->addChild(mMeshLOD[MESH_ID_EYELASH]); @@ -864,8 +1002,8 @@ BOOL LLAvatarAppearance::loadMeshNodes() switch(lod) case 0: mesh = &mHairMesh0; */ - for (LLAvatarAppearanceDictionary::Meshes::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); - mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); + for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin(); + mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end(); ++mesh_iter) { const EMeshIndex mesh_index = mesh_iter->first; @@ -906,8 +1044,8 @@ BOOL LLAvatarAppearance::loadMeshNodes() if (!info->mReferenceMeshName.empty()) { - polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); - if (polymesh_iter != mMeshes.end()) + polymesh_map_t::const_iterator polymesh_iter = mPolyMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mPolyMeshes.end()) { poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); poly_mesh->setAvatar(this); @@ -931,7 +1069,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() } // Multimap insert - mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); + mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); mesh->setMesh( poly_mesh ); mesh->setLOD( info->mMinPixelArea ); @@ -974,15 +1112,72 @@ BOOL LLAvatarAppearance::loadLayersets() layerset_iter != sAvatarXmlInfo->mLayerInfoList.end(); ++layerset_iter) { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. LLTexLayerSetInfo *layerset_info = *layerset_iter; - layerset_info->createVisualParams(this); + if (isSelf()) + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSet* layer_set = createTexLayerSet(); + + if (!layer_set->setInfo(layerset_info)) + { + stop_glerror(); + delete layer_set; + llwarns << "avatar file: layer_set->setInfo() failed" << llendl; + return FALSE; + } + + // scan baked textures and associate the layerset with the appropriate one + EBakedTextureIndex baked_index = BAKED_NUM_INDICES; + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + baked_index = baked_iter->first; + // ensure both structures are aware of each other + mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; + layer_set->setBakedTexIndex(baked_index); + break; + } + } + // if no baked texture was found, warn and cleanup + if (baked_index == BAKED_NUM_INDICES) + { + llwarns << " has invalid body_region attribute" << llendl; + delete layer_set; + return FALSE; + } + + // scan morph masks and let any affected layers know they have an associated morph + for (LLAvatarAppearance::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); + morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); + ++morph_iter) + { + LLMaskedMorph *morph = *morph_iter; + LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); + if (layer) + { + layer->setHasMorph(TRUE); + } + else + { + llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl; + success = FALSE; + } + } + } + else // !isSelf() + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSetInfo *layerset_info = *layerset_iter; + layerset_info->createVisualParams(this); + } } return success; } - - // virtual BOOL LLAvatarAppearance::isValid() const { diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 38a54d904d..96dd81be77 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -28,9 +28,8 @@ #define LL_AVATAR_APPEARANCE_H #include "llcharacter.h" -//#include "llframetimer.h" #include "llavatarappearancedefines.h" -#include "llavatarjoint.h" +#include "llavatarjointmesh.h" #include "lldriverparam.h" #include "lltexlayer.h" #include "llviewervisualparam.h" @@ -67,9 +66,10 @@ public: virtual ~LLAvatarAppearance(); static void initClass(); // initializes static members + virtual void initInstance(); // Called after construction to initialize the instance. virtual BOOL loadSkeletonNode(); - virtual BOOL loadMeshNodes(); - virtual BOOL loadLayersets(); + BOOL loadMeshNodes(); + BOOL loadLayersets(); /** Initialization @@ -97,8 +97,13 @@ public: ** SKELETON **/ +protected: + virtual LLAvatarJoint* createAvatarJoint() = 0; + virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0; + virtual LLAvatarJointMesh* createAvatarJointMesh() = 0; public: F32 getPelvisToFoot() const { return mPelvisToFoot; } + /*virtual*/ LLJoint* getRootJoint() { return mRoot; } LLVector3 mHeadOffset; // current head position LLAvatarJoint *mRoot; @@ -114,11 +119,13 @@ protected: void computeBodySize(); BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL allocateCharacterJoints(U32 num); BOOL buildSkeleton(const LLAvatarSkeletonInfo *info); protected: + void clearSkeleton(); BOOL mIsBuilt; // state of deferred character building - S32 mNumJoints; - LLJoint* mSkeleton; + typedef std::vector avatar_joint_list_t; + avatar_joint_list_t mSkeleton; //-------------------------------------------------------------------- // Pelvis height adjustment members. @@ -204,8 +211,8 @@ protected: protected: typedef std::multimap polymesh_map_t; - polymesh_map_t mMeshes; - std::vector mMeshLOD; + polymesh_map_t mPolyMeshes; + avatar_joint_list_t mMeshLOD; /** Meshes ** ** @@ -262,6 +269,8 @@ private: ** ** ** BAKED TEXTURES **/ +protected: + virtual LLTexLayerSet* createTexLayerSet() = 0; protected: struct LLMaskedMorph; typedef std::deque morph_list_t; @@ -274,7 +283,7 @@ protected: LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with - std::vector< LLJoint* > mMeshes; // std::vector mJoints[i]->mMeshParts + avatar_joint_mesh_list_t mJointMeshes; morph_list_t mMaskedMorphs; }; typedef std::vector bakedtexturedata_vec_t; diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 2c3cf781c1..0416309fc7 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -109,9 +109,9 @@ LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() 2, LLWearableType::WT_HAIR, LLWearableType::WT_ALPHA)); } -LLAvatarAppearanceDictionary::Meshes::Meshes() +LLAvatarAppearanceDictionary::MeshEntries::MeshEntries() { - // Meshes + // MeshEntries addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index c5285ddc02..e7c94104cc 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -174,12 +174,12 @@ public: const LLJointPickName mPickName; }; - struct Meshes : public LLDictionary + struct MeshEntries : public LLDictionary { - Meshes(); - } mMeshes; - const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); } - const Meshes& getMeshes() const { return mMeshes; } + MeshEntries(); + } mMeshEntries; + const MeshEntry* getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); } + const MeshEntries& getMeshEntries() const { return mMeshEntries; } //-------------------------------------------------------------------- // Baked Textures diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index 809a261633..eb450485c7 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -33,13 +33,9 @@ #include "llrender.h" #include "llmath.h" #include "llglheaders.h" -#include "llrendersphere.h" #include "llavatarappearance.h" -//#include "pipeline.h" -#define DEFAULT_LOD 0.0f - -const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; +const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f; //----------------------------------------------------------------------------- // Static Data @@ -48,21 +44,22 @@ BOOL LLAvatarJoint::sDisableLOD = FALSE; //----------------------------------------------------------------------------- // LLAvatarJoint() -// Class Constructor +// Class Constructors //----------------------------------------------------------------------------- -LLAvatarJoint::LLAvatarJoint() - : LLJoint() +LLAvatarJoint::LLAvatarJoint() : + LLJoint() { init(); } +LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) : + LLJoint(name, parent) +{ + init(); +} -//----------------------------------------------------------------------------- -// LLAvatarJoint() -// Class Constructor -//----------------------------------------------------------------------------- -LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) - : LLJoint(name, parent) +LLAvatarJoint::LLAvatarJoint(S32 joint_num) : + LLJoint(joint_num) { init(); } @@ -72,7 +69,7 @@ void LLAvatarJoint::init() { mValid = FALSE; mComponents = SC_JOINT | SC_BONE | SC_AXES; - mMinPixelArea = DEFAULT_LOD; + mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD; mPickName = PN_DEFAULT; mVisible = TRUE; mMeshID = 0; @@ -113,14 +110,6 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) } -//-------------------------------------------------------------------- -// isTransparent() -//-------------------------------------------------------------------- -BOOL LLAvatarJoint::isTransparent() -{ - return FALSE; -} - //-------------------------------------------------------------------- // setSkeletonComponents() //-------------------------------------------------------------------- @@ -132,7 +121,7 @@ void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive ) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { - LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); + LLAvatarJoint* joint = dynamic_cast(*iter); joint->setSkeletonComponents(comp, recursive); } } @@ -153,14 +142,87 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive) } } +void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast(*iter); + joint->updateFaceSizes(num_vertices, num_indices, pixel_area); + } +} + +void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast(*iter); + joint->updateFaceData(face, pixel_area, damp_wind, terse_update); + } +} + +void LLAvatarJoint::updateJointGeometry() +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast(*iter); + joint->updateJointGeometry(); + } +} + + +BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate) +{ + BOOL lod_changed = FALSE; + BOOL found_lod = FALSE; + + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast(*iter); + F32 jointLOD = joint->getLOD(); + + if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) + { + // we've already found a joint to enable, so enable the rest as alternatives + lod_changed |= joint->updateLOD(pixel_area, TRUE); + } + else + { + if (pixel_area >= jointLOD || sDisableLOD) + { + lod_changed |= joint->updateLOD(pixel_area, TRUE); + found_lod = TRUE; + } + else + { + lod_changed |= joint->updateLOD(pixel_area, FALSE); + } + } + } + return lod_changed; +} + +void LLAvatarJoint::dump() +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLAvatarJoint* joint = dynamic_cast(*iter); + joint->dump(); + } +} + void LLAvatarJoint::setMeshesToChildren() { removeAllChildren(); - for (std::vector::iterator iter = mMeshParts.begin(); + for (avatar_joint_mesh_list_t::iterator iter = mMeshParts.begin(); iter != mMeshParts.end(); iter++) { - addChild((LLAvatarJoint*) *iter); + addChild((*iter)); } } //----------------------------------------------------------------------------- @@ -172,9 +234,11 @@ LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() mUpdateXform = FALSE; } -LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent) : LLAvatarJoint(name, parent) +/*virtual*/ +U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) { - + llerrs << "Cannot call render() on LLAvatarJointCollisionVolume" << llendl; + return 0; } LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index cbfc1b73ea..1dfbd37456 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -36,6 +36,8 @@ class LLFace; class LLAvatarJointMesh; +extern const F32 DEFAULT_AVATAR_JOINT_LOD; + //----------------------------------------------------------------------------- // class LLViewerJoint //----------------------------------------------------------------------------- @@ -44,6 +46,8 @@ class LLAvatarJoint : { public: LLAvatarJoint(); + LLAvatarJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLAvatarJoint(const std::string &name, LLJoint *parent = NULL); virtual ~LLAvatarJoint(); @@ -55,12 +59,11 @@ public: // Returns true if this object is transparent. // This is used to determine in which order to draw objects. - virtual BOOL isTransparent(); + virtual BOOL isTransparent() { return FALSE; } // Returns true if this object should inherit scale modifiers from its immediate parent virtual BOOL inheritScale() { return FALSE; } - enum Components { SC_BONE = 1, @@ -83,7 +86,7 @@ public: // of this node under the same parent will be. F32 getLOD() { return mMinPixelArea; } void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } - + void setPickName(LLJointPickName name) { mPickName = name; } LLJointPickName getPickName() { return mPickName; } @@ -92,9 +95,18 @@ public: // Takes meshes in mMeshParts and sets each one as a child joint void setMeshesToChildren(); + // LLViewerJoint interface + virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) = 0; + virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); + virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); + virtual BOOL updateLOD(F32 pixel_area, BOOL activate); + virtual void updateJointGeometry(); + virtual void dump(); + + public: static BOOL sDisableLOD; - std::vector mMeshParts; //LLViewerJointMesh* + avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh* void setMeshID( S32 id ) {mMeshID = id;} protected: @@ -112,10 +124,10 @@ class LLAvatarJointCollisionVolume : public LLAvatarJoint { public: LLAvatarJointCollisionVolume(); - LLAvatarJointCollisionVolume(const std::string &name, LLJoint *parent = NULL); virtual ~LLAvatarJointCollisionVolume() {}; - virtual BOOL inheritScale() { return TRUE; } + /*virtual*/ BOOL inheritScale() { return TRUE; } + /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); void renderCollision(); diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 92c213126a..d39587defe 100755 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -233,6 +233,12 @@ void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) } } + +BOOL LLAvatarJointMesh::hasGLTexture() const +{ + return mTexture.notNull() && mTexture->hasGLTexture(); +} + //-------------------------------------------------------------------- // LLAvatarJointMesh::setLayerSet() // Sets the shape texture (takes precedence over normal texture) @@ -248,6 +254,10 @@ void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) } } +BOOL LLAvatarJointMesh::hasComposite() const +{ + return (mLayerSet && mLayerSet->hasComposite()); +} //-------------------------------------------------------------------- diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index dcd202bdaf..4b56a168ac 100755 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -59,9 +59,8 @@ public: //----------------------------------------------------------------------------- // class LLViewerJointMesh //----------------------------------------------------------------------------- -class LLAvatarJointMesh : public LLAvatarJoint +class LLAvatarJointMesh : public virtual LLAvatarJoint { - friend class LLAvatarAppearance; protected: LLColor4 mColor; // color value // LLColor4 mSpecular; // specular color (always white for now) @@ -94,6 +93,9 @@ public: // Destructor virtual ~LLAvatarJointMesh(); + // overloaded from base class + /*virtual*/ BOOL isTransparent() { return mIsTransparent; } + // Gets the shape color void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); @@ -106,11 +108,15 @@ public: // Sets the shape texture void setTexture( LLGLTexture *texture ); + BOOL hasGLTexture() const; + void setTestTexture( U32 name ) { mTestImageName = name; } // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) void setLayerSet( LLTexLayerSet* layer_set ); + BOOL hasComposite() const; + // Gets the poly mesh LLPolyMesh *getMesh(); @@ -129,6 +135,8 @@ public: // Gets ID for picking S32 getMeshID() { return mMeshID; } + void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } + private: // Allocate skin data BOOL allocateSkinData( U32 numSkinJoints ); diff --git a/indra/llappearance/lljointpickname.h b/indra/llappearance/lljointpickname.h index 17181520e3..1d41a761fc 100644 --- a/indra/llappearance/lljointpickname.h +++ b/indra/llappearance/lljointpickname.h @@ -28,6 +28,7 @@ #ifndef LL_LLJOINTPICKNAME_H #define LL_LLJOINTPICKNAME_H +class LLAvatarJointMesh; // Sets the OpenGL selection stack name that is pushed and popped // with this joint state. The default value indicates that no name @@ -43,4 +44,6 @@ enum LLJointPickName PN_5 = 5 }; +typedef std::vector avatar_joint_mesh_list_t; + #endif // LL_LLJOINTPICKNAME_H diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 2f2b2405b6..5740dbce77 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -93,13 +93,6 @@ public: // get the height & normal of the ground under a point virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm) = 0; - // allocate an array of joints for the character skeleton - // this must be overloaded to support joint subclasses, - // and is called implicitly from buildSkeleton(). - // Note this must handle reallocation as it will be called - // each time buildSkeleton() is called. - virtual BOOL allocateCharacterJoints( U32 num ) = 0; - // skeleton joint accessor to support joint subclasses virtual LLJoint *getCharacterJoint( U32 i ) = 0; diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 19907933cb..09a7c11a22 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -40,7 +40,9 @@ S32 LLJoint::sNumTouches = 0; // LLJoint() // Class Constructor //----------------------------------------------------------------------------- -LLJoint::LLJoint() + + +void LLJoint::init() { mName = "unnamed"; mParent = NULL; @@ -48,7 +50,20 @@ LLJoint::LLJoint() mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; - mJointNum = -1; +} + +LLJoint::LLJoint() : + mJointNum(-1) +{ + init(); + touch(); + mResetAfterRestoreOldXform = false; +} + +LLJoint::LLJoint(S32 joint_num) : + mJointNum(joint_num) +{ + init(); touch(); mResetAfterRestoreOldXform = false; } @@ -58,15 +73,12 @@ LLJoint::LLJoint() // LLJoint() // Class Constructor //----------------------------------------------------------------------------- -LLJoint::LLJoint(const std::string &name, LLJoint *parent) +LLJoint::LLJoint(const std::string &name, LLJoint *parent) : + mJointNum(0) { - mName = "unnamed"; - mParent = NULL; - mXform.setScaleChildOffset(TRUE); - mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); - mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; + init(); mUpdateXform = FALSE; - mJointNum = 0; + // *TODO: mResetAfterRestoreOldXform is not initialized!!! setName(name); if (parent) diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index dc3c58cf64..2b1e2005c6 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -105,10 +105,15 @@ public: public: LLJoint(); + LLJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLJoint( const std::string &name, LLJoint *parent=NULL ); - virtual ~LLJoint(); +private: + void init(); + +public: // set name and parent void setup( const std::string &name, LLJoint *parent=NULL ); @@ -178,7 +183,6 @@ public: virtual BOOL isAnimatable() const { return TRUE; } S32 getJointNum() const { return mJointNum; } - void setJointNum(S32 joint_num) { mJointNum = joint_num; } void restoreOldXform( void ); void restoreToDefaultXform( void ); diff --git a/indra/llcharacter/tests/lljoint_test.cpp b/indra/llcharacter/tests/lljoint_test.cpp index e92aa832d6..da151808f2 100644 --- a/indra/llcharacter/tests/lljoint_test.cpp +++ b/indra/llcharacter/tests/lljoint_test.cpp @@ -150,11 +150,11 @@ namespace tut template<> template<> void lljoint_object::test<11>() { - LLJoint lljoint("parent"); S32 joint_num = 12; - lljoint.setJointNum(joint_num); + LLJoint lljoint(joint_num); + lljoint.setName("parent"); S32 jointNum = lljoint.getJointNum(); - ensure("setJointNum()/getJointNum failed ", (jointNum == joint_num)); + ensure("getJointNum failed ", (jointNum == joint_num)); } template<> template<> diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 887cd2f4b0..3b472a2862 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -614,7 +614,7 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const } mDummyAvatar->mRoot->setVisible(FALSE, TRUE); - mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name); + mTargetMesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); mTargetMesh->setTestTexture(mTextureName); mTargetMesh->setVisible(TRUE, FALSE); mCameraDistance = distance; @@ -631,7 +631,7 @@ void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name) { if (mDummyAvatar) { - LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot->findJoint(mesh_name); + LLViewerJointMesh *mesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); // clear out existing test mesh if (mesh) { diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index bb45cf89fc..e46299f9d2 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -35,50 +35,26 @@ #include "llrender.h" #include "llmath.h" #include "llglheaders.h" -#include "llrendersphere.h" #include "llvoavatar.h" #include "pipeline.h" -#define DEFAULT_LOD 0.0f - -const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -BOOL LLViewerJoint::sDisableLOD = FALSE; +static const S32 MIN_PIXEL_AREA_3PASS_HAIR = 64*64; //----------------------------------------------------------------------------- // LLViewerJoint() -// Class Constructor +// Class Constructors //----------------------------------------------------------------------------- -LLViewerJoint::LLViewerJoint() - : LLAvatarJoint() -{ - init(); -} +LLViewerJoint::LLViewerJoint() : + LLAvatarJoint() +{ } +LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) : + LLAvatarJoint(name, parent) +{ } -//----------------------------------------------------------------------------- -// LLViewerJoint() -// Class Constructor -//----------------------------------------------------------------------------- -LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) - : LLAvatarJoint(name, parent) -{ - init(); -} - - -void LLViewerJoint::init() -{ - mValid = FALSE; - mComponents = SC_JOINT | SC_BONE | SC_AXES; - mMinPixelArea = DEFAULT_LOD; - mPickName = PN_DEFAULT; - mVisible = TRUE; - mMeshID = 0; -} +LLViewerJoint::LLViewerJoint(S32 joint_num) : + LLAvatarJoint(joint_num) +{ } //----------------------------------------------------------------------------- @@ -89,129 +65,6 @@ LLViewerJoint::~LLViewerJoint() { } - -//-------------------------------------------------------------------- -// renderSkeleton() -// DEBUG (UNUSED) -//-------------------------------------------------------------------- -// void LLViewerJoint::renderSkeleton(BOOL recursive) -// { -// F32 nc = 0.57735f; - -// //---------------------------------------------------------------- -// // push matrix stack -// //---------------------------------------------------------------- -// gGL.pushMatrix(); - -// //---------------------------------------------------------------- -// // render the bone to my parent -// //---------------------------------------------------------------- -// if (mComponents & SC_BONE) -// { -// drawBone(); -// } - -// //---------------------------------------------------------------- -// // offset to joint position and -// // rotate to our orientation -// //---------------------------------------------------------------- -// gGL.loadIdentity(); -// gGL.multMatrix( &getWorldMatrix().mMatrix[0][0] ); - -// //---------------------------------------------------------------- -// // render joint axes -// //---------------------------------------------------------------- -// if (mComponents & SC_AXES) -// { -// gGL.begin(LLRender::LINES); -// gGL.color3f( 1.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.1f, 0.0f, 0.0f ); - -// gGL.color3f( 0.0f, 1.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.1f, 0.0f ); - -// gGL.color3f( 0.0f, 0.0f, 1.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.0f ); -// gGL.vertex3f( 0.0f, 0.0f, 0.1f ); -// gGL.end(); -// } - -// //---------------------------------------------------------------- -// // render the joint graphic -// //---------------------------------------------------------------- -// if (mComponents & SC_JOINT) -// { -// gGL.color3f( 1.0f, 1.0f, 0.0f ); - -// gGL.begin(LLRender::TRIANGLES); - -// // joint top half -// glNormal3f(nc, nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); - -// glNormal3f(-nc, nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); - -// glNormal3f(-nc, -nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); - -// glNormal3f(nc, -nc, nc); -// gGL.vertex3f(0.0f, 0.0f, 0.05f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); - -// // joint bottom half -// glNormal3f(nc, nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); - -// glNormal3f(-nc, nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, 0.05f, 0.0f); - -// glNormal3f(-nc, -nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); -// gGL.vertex3f(-0.05f, 0.0f, 0.0f); - -// glNormal3f(nc, -nc, -nc); -// gGL.vertex3f(0.0f, 0.0f, -0.05f); -// gGL.vertex3f(0.05f, 0.0f, 0.0f); -// gGL.vertex3f(0.0f, -0.05f, 0.0f); - -// gGL.end(); -// } - -// //---------------------------------------------------------------- -// // render children -// //---------------------------------------------------------------- -// if (recursive) -// { -// for (child_list_t::iterator iter = mChildren.begin(); -// iter != mChildren.end(); ++iter) -// { -// LLViewerJoint* joint = (LLViewerJoint*)(*iter); -// joint->renderSkeleton(); -// } -// } - -// //---------------------------------------------------------------- -// // pop matrix stack -// //---------------------------------------------------------------- -// gGL.popMatrix(); -// } - - //-------------------------------------------------------------------- // render() //-------------------------------------------------------------------- @@ -292,13 +145,13 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); + LLAvatarJoint* joint = dynamic_cast(*iter); F32 jointLOD = joint->getLOD(); if (pixelArea >= jointLOD || sDisableLOD) { triangle_count += joint->render( pixelArea, TRUE, is_dummy ); - if (jointLOD != DEFAULT_LOD) + if (jointLOD != DEFAULT_AVATAR_JOINT_LOD) { break; } @@ -308,72 +161,6 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) return triangle_count; } - -//-------------------------------------------------------------------- -// drawBone() -// DEBUG (UNUSED) -//-------------------------------------------------------------------- -// void LLViewerJoint::drawBone() -// { -// if ( mParent == NULL ) -// return; - -// F32 boneSize = 0.02f; - -// // rotate to point to child (bone direction) -// gGL.pushMatrix(); - -// LLVector3 boneX = getPosition(); -// F32 length = boneX.normVec(); - -// LLVector3 boneZ(1.0f, 0.0f, 1.0f); - -// LLVector3 boneY = boneZ % boneX; -// boneY.normVec(); - -// boneZ = boneX % boneY; - -// LLMatrix4 rotateMat; -// rotateMat.setFwdRow( boneX ); -// rotateMat.setLeftRow( boneY ); -// rotateMat.setUpRow( boneZ ); -// gGL.multMatrix( &rotateMat.mMatrix[0][0] ); - -// // render the bone -// gGL.color3f( 0.5f, 0.5f, 0.0f ); - -// gGL.begin(LLRender::TRIANGLES); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, boneSize, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, boneSize); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, -boneSize); -// gGL.vertex3f( 0.0f, boneSize, 0.0f); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, -boneSize, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, -boneSize); - -// gGL.vertex3f( length, 0.0f, 0.0f); -// gGL.vertex3f( 0.0f, 0.0f, boneSize); -// gGL.vertex3f( 0.0f, -boneSize, 0.0f); - -// gGL.end(); - -// // restore matrix -// gGL.popMatrix(); -// } - -//-------------------------------------------------------------------- -// isTransparent() -//-------------------------------------------------------------------- -BOOL LLViewerJoint::isTransparent() -{ - return FALSE; -} - //-------------------------------------------------------------------- // drawShape() //-------------------------------------------------------------------- @@ -382,121 +169,4 @@ U32 LLViewerJoint::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) return 0; } -//-------------------------------------------------------------------- -// setSkeletonComponents() -//-------------------------------------------------------------------- -void LLViewerJoint::setSkeletonComponents( U32 comp, BOOL recursive ) -{ - mComponents = comp; - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setSkeletonComponents(comp, recursive); - } - } -} - -void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceSizes(num_vertices, num_indices, pixel_area); - } -} - -void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceData(face, pixel_area, damp_wind, terse_update); - } -} - -void LLViewerJoint::updateJointGeometry() -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateJointGeometry(); - } -} - - -BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate) -{ - BOOL lod_changed = FALSE; - BOOL found_lod = FALSE; - - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - F32 jointLOD = joint->getLOD(); - - if (found_lod || jointLOD == DEFAULT_LOD) - { - // we've already found a joint to enable, so enable the rest as alternatives - lod_changed |= joint->updateLOD(pixel_area, TRUE); - } - else - { - if (pixel_area >= jointLOD || sDisableLOD) - { - lod_changed |= joint->updateLOD(pixel_area, TRUE); - found_lod = TRUE; - } - else - { - lod_changed |= joint->updateLOD(pixel_area, FALSE); - } - } - } - return lod_changed; -} - -void LLViewerJoint::dump() -{ - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->dump(); - } -} - -void LLViewerJoint::setVisible(BOOL visible, BOOL recursive) -{ - mVisible = visible; - - if (recursive) - { - for (child_list_t::iterator iter = mChildren.begin(); - iter != mChildren.end(); ++iter) - { - LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->setVisible(visible, recursive); - } - } -} - - -void LLViewerJoint::setMeshesToChildren() -{ - removeAllChildren(); - for (std::vector::iterator iter = mMeshParts.begin(); - iter != mMeshParts.end(); iter++) - { - addChild((LLViewerJointMesh *) *iter); - } -} - - // End diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 37c80dafeb..fd262b6e80 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -40,95 +40,25 @@ class LLViewerJointMesh; // class LLViewerJoint //----------------------------------------------------------------------------- class LLViewerJoint : - public LLAvatarJoint + public virtual LLAvatarJoint { public: LLViewerJoint(); + LLViewerJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLViewerJoint(const std::string &name, LLJoint *parent = NULL); virtual ~LLViewerJoint(); - // Gets the validity of this joint - BOOL getValid() { return mValid; } - - // Primarily for debugging and character setup - // Derived classes may add text/graphic output. - // Draw skeleton graphic for debugging and character setup - void renderSkeleton(BOOL recursive=TRUE); // debug only (unused) - - // Draws a bone graphic to the parent joint. - // Derived classes may add text/graphic output. - // Called by renderSkeleton(). - void drawBone(); // debug only (unused) - // Render character hierarchy. // Traverses the entire joint hierarchy, setting up // transforms and calling the drawShape(). // Derived classes may add text/graphic output. virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); // Returns triangle count - // Returns true if this object is transparent. - // This is used to determine in which order to draw objects. - virtual BOOL isTransparent(); - - // Returns true if this object should inherit scale modifiers from its immediate parent - virtual BOOL inheritScale() { return FALSE; } - // Draws the shape attached to a joint. // Called by render(). virtual U32 drawShape( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); virtual void drawNormals() {} - - enum Components - { - SC_BONE = 1, - SC_JOINT = 2, - SC_AXES = 4 - }; - - // Selects which skeleton components to draw - void setSkeletonComponents( U32 comp, BOOL recursive = TRUE ); - - // Returns which skeleton components are enables for drawing - U32 getSkeletonComponents() { return mComponents; } - - // Sets the level of detail for this node as a minimum - // pixel area threshold. If the current pixel area for this - // object is less than the specified threshold, the node is - // not traversed. In addition, if a value is specified (not - // default of 0.0), and the pixel area is larger than the - // specified minimum, the node is rendered, but no other siblings - // of this node under the same parent will be. - F32 getLOD() { return mMinPixelArea; } - void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } - - void setPickName(LLJointPickName name) { mPickName = name; } - LLJointPickName getPickName() { return mPickName; } - - virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); - virtual BOOL updateLOD(F32 pixel_area, BOOL activate); - virtual void updateJointGeometry(); - virtual void dump(); - - void setVisible( BOOL visible, BOOL recursive ); - - // Takes meshes in mMeshParts and sets each one as a child joint - void setMeshesToChildren(); - -public: - static BOOL sDisableLOD; - std::vector mMeshParts; - void setMeshID( S32 id ) {mMeshID = id;} - -protected: - void init(); - - BOOL mValid; - U32 mComponents; - F32 mMinPixelArea; - LLJointPickName mPickName; - BOOL mVisible; - S32 mMeshID; }; #endif // LL_LLVIEWERJOINT_H diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 8d479ab0bf..64454a03d1 100755 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -200,21 +200,6 @@ void LLViewerJointMesh::uploadJointMatrices() } } -//-------------------------------------------------------------------- -// LLViewerJointMesh::drawBone() -//-------------------------------------------------------------------- -void LLViewerJointMesh::drawBone() -{ -} - -//-------------------------------------------------------------------- -// LLViewerJointMesh::isTransparent() -//-------------------------------------------------------------------- -BOOL LLViewerJointMesh::isTransparent() -{ - return mIsTransparent; -} - //-------------------------------------------------------------------- // DrawElementsBLEND and utility code //-------------------------------------------------------------------- diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index 039175830f..64887152a6 100755 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -41,9 +41,8 @@ class LLViewerTexLayerSet; //----------------------------------------------------------------------------- // class LLViewerJointMesh //----------------------------------------------------------------------------- -class LLViewerJointMesh : public LLAvatarJointMesh +class LLViewerJointMesh : public LLAvatarJointMesh, public LLViewerJoint { - friend class LLVOAvatar; public: // Constructor LLViewerJointMesh(); @@ -55,8 +54,6 @@ public: void uploadJointMatrices(); // overloaded from base class - /*virtual*/ void drawBone(); - /*virtual*/ BOOL isTransparent(); /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ); /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); @@ -65,8 +62,6 @@ public: /*virtual*/ void updateJointGeometry(); /*virtual*/ void dump(); - void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } - /*virtual*/ BOOL isAnimatable() const { return FALSE; } private: diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f0f469e959..081f1d62ca 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -24,12 +24,6 @@ * $/LicenseInfo$ */ -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#endif - #include "llviewerprecompiledheaders.h" #include "llvoavatar.h" @@ -109,12 +103,6 @@ extern F32 SPEED_ADJUST_MAX_SEC; extern F32 ANIM_SPEED_MAX; extern F32 ANIM_SPEED_MIN; -#if LL_MSVC -// disable boost::lexical_cast warning -#pragma warning (disable:4702) -#endif - -#include // #define OUTPUT_BREAST_DATA @@ -783,7 +771,7 @@ BOOL LLVOAvatar::isFullyTextured() const { for (S32 i = 0; i < mMeshLOD.size(); i++) { - LLViewerJoint* joint = (LLViewerJoint*) mMeshLOD[i]; + LLAvatarJoint* joint = mMeshLOD[i]; if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) { continue; // don't care about skirt textures if we're not wearing one. @@ -792,19 +780,19 @@ BOOL LLVOAvatar::isFullyTextured() const { continue; // nonexistent LOD OK. } - std::vector::iterator meshIter = joint->mMeshParts.begin(); + avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); if (meshIter != joint->mMeshParts.end()) { - LLViewerJointMesh *mesh = (LLViewerJointMesh *) *meshIter; + LLAvatarJointMesh *mesh = (*meshIter); if (!mesh) { continue; // nonexistent mesh OK } - if (mesh->mTexture.notNull() && mesh->mTexture->hasGLTexture()) + if (mesh->hasGLTexture()) { continue; // Mesh exists and has a baked texture. } - if (mesh->mLayerSet && mesh->mLayerSet->hasComposite()) + if (mesh->hasComposite()) { continue; // Mesh exists and has a composite texture. } @@ -1056,84 +1044,9 @@ void LLVOAvatar::cleanupClass() sXMLTree.cleanup(); } +// virtual void LLVOAvatar::initInstance(void) { - //------------------------------------------------------------------------- - // initialize joint, mesh and shape members - //------------------------------------------------------------------------- - if (mRoot) - { - delete mRoot; - } - mRoot = new LLViewerJoint(); - mRoot->setName( "mRoot" ); - - for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); - ++iter) - { - const EMeshIndex mesh_index = iter->first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; - LLViewerJoint* joint = new LLViewerJoint(); - joint->setName(mesh_dict->mName); - joint->setMeshID(mesh_index); - mMeshLOD.push_back(joint); - - /* mHairLOD.setName("mHairLOD"); - mHairMesh0.setName("mHairMesh0"); - mHairMesh0.setMeshID(MESH_ID_HAIR); - mHairMesh1.setName("mHairMesh1"); */ - for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) - { - LLViewerJointMesh* mesh = new LLViewerJointMesh(); - std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast(lod); - // We pre-pended an m - need to capitalize first character for camelCase - mesh_name[1] = toupper(mesh_name[1]); - mesh->setName(mesh_name); - mesh->setMeshID(mesh_index); - mesh->setPickName(mesh_dict->mPickName); - mesh->setIsTransparent(FALSE); - switch((int)mesh_index) - { - case MESH_ID_HAIR: - mesh->setIsTransparent(TRUE); - break; - case MESH_ID_SKIRT: - mesh->setIsTransparent(TRUE); - break; - case MESH_ID_EYEBALL_LEFT: - case MESH_ID_EYEBALL_RIGHT: - mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - break; - } - - joint->mMeshParts.push_back(mesh); - } - } - - //------------------------------------------------------------------------- - // associate baked textures with meshes - //------------------------------------------------------------------------- - for (LLAvatarAppearanceDictionary::Meshes::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshes().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getMeshes().end(); - ++iter) - { - const EMeshIndex mesh_index = iter->first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = iter->second; - const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; - // Skip it if there's no associated baked texture. - if (baked_texture_index == BAKED_NUM_INDICES) continue; - - for (std::vector::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin(); - iter != mMeshLOD[mesh_index]->mMeshParts.end(); - ++iter) - { - LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter; - mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh); - } - } - - //------------------------------------------------------------------------- // register motions //------------------------------------------------------------------------- @@ -1192,10 +1105,9 @@ void LLVOAvatar::initInstance(void) registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create ); registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); - } - - buildCharacter(); + + LLAvatarAppearance::initInstance(); // preload specific motions here createMotion( ANIM_AGENT_CUSTOMIZE); @@ -1204,7 +1116,30 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +} + +// virtual +LLAvatarJoint* LLVOAvatar::createAvatarJoint() +{ + return new LLViewerJoint(); +} +// virtual +LLAvatarJoint* LLVOAvatar::createAvatarJoint(S32 joint_num) +{ + return new LLViewerJoint(joint_num); +} + +// virtual +LLAvatarJointMesh* LLVOAvatar::createAvatarJointMesh() +{ + return new LLViewerJointMesh(); +} + +// virtual +LLTexLayerSet* LLVOAvatar::createTexLayerSet() +{ + return new LLViewerTexLayerSet(this); } const LLVector3 LLVOAvatar::getRenderPosition() const @@ -1279,7 +1214,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) float max_attachment_span = get_default_max_prim_scale() * 5.0f; //stretch bounding box by joint positions - for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) + for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) { LLPolyMesh* mesh = i->second; for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++) @@ -1551,23 +1486,11 @@ void LLVOAvatar::startDefaultMotions() // virtual void LLVOAvatar::buildCharacter() { - //------------------------------------------------------------------------- - // clear mesh data - //------------------------------------------------------------------------- - for (std::vector::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); ++jointIter) - { - LLViewerJoint* joint = (LLViewerJoint*) *jointIter; - for (std::vector::iterator meshIter = joint->mMeshParts.begin(); - meshIter != joint->mMeshParts.end(); ++meshIter) - { - LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter; - mesh->setMesh(NULL); - } - } - LLAvatarAppearance::buildCharacter(); + // Not done building yet; more to do. + mIsBuilt = FALSE; + //------------------------------------------------------------------------- // set head offset from pelvis //------------------------------------------------------------------------- @@ -1600,6 +1523,9 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- processAnimationStateChanges(); + mIsBuilt = TRUE; + stop_glerror(); + mMeshValid = TRUE; } @@ -1619,11 +1545,11 @@ void LLVOAvatar::releaseMeshData() //llinfos << "Releasing" << llendl; // cleanup mesh data - for (std::vector::iterator iter = mMeshLOD.begin(); + for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); iter != mMeshLOD.end(); ++iter) { - LLViewerJoint* joint = (LLViewerJoint*) *iter; + LLAvatarJoint* joint = (*iter); joint->setValid(FALSE, TRUE); } @@ -4718,10 +4644,12 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) //----------------------------------------------------------------------------- void LLVOAvatar::resetJointPositions( void ) { - for(S32 i = 0; i < (S32)mNumJoints; ++i) + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) { - mSkeleton[i].restoreOldXform(); - mSkeleton[i].setId( LLUUID::null ); + (*iter)->restoreOldXform(); + (*iter)->setId( LLUUID::null ); } mHasPelvisOffset = false; mPelvisFixup = mLastPelvisFixup; @@ -4753,16 +4681,17 @@ void LLVOAvatar::resetSpecificJointPosition( const std::string& name ) //----------------------------------------------------------------------------- void LLVOAvatar::resetJointPositionsToDefault( void ) { - //Subsequent joints are relative to pelvis - for( S32 i = 0; i < (S32)mNumJoints; ++i ) + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + for (; iter != end; ++iter) { - LLJoint* pJoint = (LLJoint*)&mSkeleton[i]; + LLJoint* pJoint = (*iter); if ( pJoint->doesJointNeedToBeReset() ) { - pJoint->setId( LLUUID::null ); //restore joints to default positions, however skip over the pelvis + // *TODO: How does this pointer check skip over pelvis? if ( pJoint ) { pJoint->restoreOldXform(); @@ -4895,43 +4824,18 @@ LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position) return gAgent.getPosAgentFromGlobal(position); } -//----------------------------------------------------------------------------- -// allocateCharacterJoints() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::allocateCharacterJoints( U32 num ) -{ - deleteAndClearArray(mSkeleton); - mNumJoints = 0; - - mSkeleton = new LLViewerJoint[num]; - - for(S32 joint_num = 0; joint_num < (S32)num; joint_num++) - { - mSkeleton[joint_num].setJointNum(joint_num); - } - - if (!mSkeleton) - { - return FALSE; - } - - mNumJoints = num; - return TRUE; -} - - //----------------------------------------------------------------------------- // getCharacterJoint() //----------------------------------------------------------------------------- LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) { - if ((S32)num >= mNumJoints + if ((S32)num >= mSkeleton.size() || (S32)num < 0) { return NULL; } - return (LLJoint*)&mSkeleton[num]; + return mSkeleton[num]; } //----------------------------------------------------------------------------- @@ -4949,16 +4853,6 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion ) //virtual BOOL LLVOAvatar::loadSkeletonNode () { - // make meshes children before calling parent version of the function - for (std::vector::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); - ++iter) - { - LLViewerJoint *joint = (LLViewerJoint *) *iter; - joint->mUpdateXform = FALSE; - joint->setMeshesToChildren(); - } - if (!LLAvatarAppearance::loadSkeletonNode()) { return FALSE; @@ -5695,9 +5589,11 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) { LLColor4 color = mTexHairColor->getColor(); - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); @@ -5962,9 +5858,11 @@ void LLVOAvatar::updateMeshTextures() } mBakedTextureDatas[i].mIsUsed = TRUE; - for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setTexture( baked_img ); @@ -5996,9 +5894,11 @@ void LLVOAvatar::updateMeshTextures() layerset->createComposite(); layerset->setUpdatesEnabled( TRUE ); mBakedTextureDatas[i].mIsUsed = FALSE; - for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setLayerSet( layerset ); @@ -6014,9 +5914,11 @@ void LLVOAvatar::updateMeshTextures() { const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); @@ -6778,9 +6680,11 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) mBakedTextureDatas[i].mIsLoaded = true; mBakedTextureDatas[i].mLastTextureIndex = id; mBakedTextureDatas[i].mIsUsed = true; - for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[i].mMeshes[k]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setTexture( image_baked ); @@ -6803,9 +6707,11 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) // This is paired with similar code in updateMeshTextures that sets hair mesh color. if (i == BAKED_HAIR) { - for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) { - LLViewerJointMesh* mesh = dynamic_cast(mBakedTextureDatas[BAKED_HAIR].mMeshes[i]); + LLAvatarJointMesh* mesh = (*iter); if (mesh) { mesh->setColor( 1.f, 1.f, 1.f, 1.f ); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index bda09b044d..cc94c2a3eb 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -172,7 +172,6 @@ public: virtual LLVector3 getCharacterVelocity(); virtual LLVector3 getCharacterAngularVelocity(); virtual LLJoint* getCharacterJoint(U32 num); - virtual BOOL allocateCharacterJoints(U32 num); virtual LLUUID remapMotionID(const LLUUID& id); virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); @@ -184,7 +183,6 @@ public: void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); - virtual LLJoint* getRootJoint() { return mRoot; } void resetJointPositions( void ); void resetJointPositionsToDefault( void ); @@ -341,6 +339,10 @@ protected: ** SKELETON **/ +protected: + /*virtual*/ LLAvatarJoint* createAvatarJoint(); // Returns LLViewerJoint + /*virtual*/ LLAvatarJoint* createAvatarJoint(S32 joint_num); // Returns LLViewerJoint + /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; @@ -521,6 +523,7 @@ public: // Baked textures //-------------------------------------------------------------------- public: + /*virtual*/ LLTexLayerSet* createTexLayerSet(); // Return LLViewerTexLayerSet void releaseComponentTextures(); // ! BACKWARDS COMPATIBILITY ! protected: static void onBakedTextureMasksLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f832a126bd..96fd41739f 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -249,8 +249,6 @@ BOOL LLVOAvatarSelf::loadAvatarSelf() llwarns << "avatar file: buildSkeleton() failed" << llendl; return FALSE; } - // TODO: make loadLayersets() called only by self. - //success &= loadLayersets(); return success; } @@ -585,70 +583,6 @@ LLVOAvatarSelf::~LLVOAvatarSelf() ** ** *********************************************************************************/ -//virtual -BOOL LLVOAvatarSelf::loadLayersets() -{ - BOOL success = TRUE; - for (LLAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin(); - iter != sAvatarXmlInfo->mLayerInfoList.end(); - ++iter) - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - const LLTexLayerSetInfo *info = *iter; - LLViewerTexLayerSet* layer_set = new LLViewerTexLayerSet( this ); - - if (!layer_set->setInfo(info)) - { - stop_glerror(); - delete layer_set; - llwarns << "avatar file: layer_set->parseData() failed" << llendl; - return FALSE; - } - - // scan baked textures and associate the layerset with the appropriate one - EBakedTextureIndex baked_index = BAKED_NUM_INDICES; - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); - ++baked_iter) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - if (layer_set->isBodyRegion(baked_dict->mName)) - { - baked_index = baked_iter->first; - // ensure both structures are aware of each other - mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; - layer_set->setBakedTexIndex(baked_index); - break; - } - } - // if no baked texture was found, warn and cleanup - if (baked_index == BAKED_NUM_INDICES) - { - llwarns << " has invalid body_region attribute" << llendl; - delete layer_set; - return FALSE; - } - - // scan morph masks and let any affected layers know they have an associated morph - for (LLVOAvatar::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin(); - morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end(); - ++morph_iter) - { - LLMaskedMorph *morph = *morph_iter; - LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); - if (layer) - { - layer->setHasMorph(TRUE); - } - else - { - llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl; - success = FALSE; - } - } - } - return success; -} // virtual BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) { diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index bdc1ccf133..907564f8e1 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -69,7 +69,6 @@ protected: BOOL loadAvatarSelf(); BOOL buildSkeletonSelf(const LLAvatarSkeletonInfo *info); BOOL buildMenus(); - /*virtual*/ BOOL loadLayersets(); /** Initialization ** ** -- cgit v1.2.3 From 6df8c2b42066efad4d46a601ecaabbc9bf1dcd91 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Sun, 9 Sep 2012 14:48:06 -0700 Subject: CHUI-285 : Complete. Fix participants repositioning. --- indra/newview/llimfloatercontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index fa0750c39c..978b91b598 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -358,6 +358,8 @@ void LLIMFloaterContainer::draw() } } + repositioningWidgets(); + if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -365,8 +367,6 @@ void LLIMFloaterContainer::draw() collapseMessagesPane(true); } LLFloater::draw(); - - repositioningWidgets(); } void LLIMFloaterContainer::tabClose() -- cgit v1.2.3 From 913375051e2dbe3f1ec68d7b8b86cac613e26ec3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 10 Sep 2012 16:12:20 +0300 Subject: CHUI-333 (Icons overlap in message panel when maximizing width of conversation list): increaced expanded_min_dim for the message pane --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e439fc9005..413e66738d 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -113,7 +113,7 @@ height="430" name="messages_layout_panel" width="412" - expanded_min_dim="205"> + expanded_min_dim="225"> Date: Mon, 10 Sep 2012 16:20:47 +0300 Subject: CHUI-332 (Overlap of icons in chrome when collapsing and expanding conversation list) changed expanded_min_dim of the right panel --- indra/newview/skins/default/xui/en/floater_im_container.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 413e66738d..1583add857 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -36,7 +36,7 @@ name="conversations_layout_panel" min_dim="38" width="268" - expanded_min_dim="120"> + expanded_min_dim="165"> Date: Mon, 10 Sep 2012 07:40:13 -0700 Subject: CHUI-283: Basic Implementation, just have hard coded avatar icon appearing and profile/info buttons visible. profile/info buttons do not have proper positioning or mouseclick events. --- indra/llcommon/llfoldertype.h | 4 +- indra/llui/llfolderviewitem.cpp | 8 ++- indra/llui/llfolderviewitem.h | 2 +- indra/newview/llconversationmodel.h | 4 +- indra/newview/llconversationview.cpp | 110 ++++++++++++++++++++++++++++++++- indra/newview/llconversationview.h | 42 +++++++++++-- indra/newview/llimfloatercontainer.cpp | 2 +- indra/newview/llviewerfoldertype.cpp | 2 + 8 files changed, 163 insertions(+), 11 deletions(-) mode change 100644 => 100755 indra/llcommon/llfoldertype.h mode change 100644 => 100755 indra/llui/llfolderviewitem.cpp mode change 100644 => 100755 indra/llui/llfolderviewitem.h mode change 100644 => 100755 indra/newview/llconversationmodel.h mode change 100644 => 100755 indra/newview/llconversationview.cpp mode change 100644 => 100755 indra/newview/llconversationview.h mode change 100644 => 100755 indra/newview/llimfloatercontainer.cpp mode change 100644 => 100755 indra/newview/llviewerfoldertype.cpp diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h old mode 100644 new mode 100755 index a0c847914f..6b5ae572a9 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -89,7 +89,9 @@ public: FT_COUNT, - FT_NONE = -1 + FT_NONE = -1, + + FT_PROFILE = 58 }; static EType lookup(const std::string& type_name); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp old mode 100644 new mode 100755 index 52923389cd..c46af27a04 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -609,13 +609,14 @@ void LLFolderViewItem::draw() static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + + getViewModelItem()->update(); + const Params& default_params = LLUICtrlFactory::getDefaultParams(); const S32 TOP_PAD = default_params.item_top_pad; const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - getViewModelItem()->update(); - //--------------------------------------------------------------------------------// // Draw open folder arrow // @@ -793,6 +794,9 @@ void LLFolderViewItem::draw() sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } + + + LLView::draw(); } const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h old mode 100644 new mode 100755 index 6eacbe8bd0..766d9b3fe3 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -231,7 +231,7 @@ public: virtual void onMouseLeave(S32 x, S32 y, MASK mask); - virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } + //virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return LLView::findChildView(name, recurse); } // virtual void handleDropped(); virtual void draw(); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h old mode 100644 new mode 100755 index 1a2e09dfab..7baabf7f76 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -29,6 +29,7 @@ #include "llfolderviewitem.h" #include "llfolderviewmodel.h" +#include "llviewerfoldertype.h" // Implementation of conversations list @@ -55,7 +56,7 @@ public: virtual const std::string& getSearchableName() const { return mName; } virtual const LLUUID& getUUID() const { return mUUID; } virtual time_t getCreationDate() const { return 0; } - virtual LLPointer getIcon() const { return NULL; } + virtual LLPointer getIcon() const { return LLUI::getUIImage(LLViewerFolderType::lookupIconName(LLFolderType::FT_PROFILE, FALSE)); } virtual LLPointer getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } @@ -115,6 +116,7 @@ public: LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); virtual ~LLConversationItemSession() {} + LLPointer getIcon() const { return NULL; } void setSessionID(const LLUUID& session_id) { mUUID = session_id; } void addParticipant(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp old mode 100644 new mode 100755 index fefb7e9cac..d1a8478697 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -32,9 +32,15 @@ #include "llimconversation.h" #include "llimfloatercontainer.h" + +#include "lluictrlfactory.h" +#include "llavatariconctrl.h" + // // Implementation of conversations list session widgets // + + LLConversationViewSession::Params::Params() : container() @@ -83,9 +89,111 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible) // Implementation of conversations list participant (avatar) widgets // -LLConversationViewParticipant::LLConversationViewParticipant( const LLFolderViewItem::Params& p ): +static LLDefaultChildRegistry::Register r("conversation_view_participant"); + +LLConversationViewParticipant::Params::Params() : +container(), +view_profile_button("view_profile_button"), +info_button("info_button") +{} + +LLConversationViewParticipant::LLConversationViewParticipant( const LLConversationViewParticipant::Params& p ): LLFolderViewItem(p) +{ + +} + +void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) +{ + LLButton::Params view_profile_button_params(params.view_profile_button()); + LLButton * button = LLUICtrlFactory::create(view_profile_button_params); + addChild(button); + + LLButton::Params info_button_params(params.info_button()); + button = LLUICtrlFactory::create(info_button_params); + addChild(button); +} + +BOOL LLConversationViewParticipant::postBuild() +{ + mInfoBtn = getChild("info_btn"); + mProfileBtn = getChild("profile_btn"); + + mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); + mProfileBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onProfileBtnClick, this)); + + + LLFolderViewItem::postBuild(); + return TRUE; +} + +void LLConversationViewParticipant::onInfoBtnClick() +{ + + +} + +void LLConversationViewParticipant::onProfileBtnClick() +{ + +} + +LLButton* LLConversationViewParticipant::createProfileButton() +{ + + LLButton::Params params; + + + // -- cgit v1.2.3 From 908f8735d4d60266504c97c13d65fda74045b731 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Fri, 9 Nov 2012 16:09:06 -0800 Subject: CHUI-517: Updating the copy in Preferences for Do Not Disturb mode. --- .../newview/skins/default/xui/en/panel_preferences_chat.xml | 12 ++++++------ .../skins/default/xui/en/panel_preferences_general.xml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 5524d0e4f0..4964df53bb 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -101,7 +101,7 @@ @@ -274,13 +274,13 @@ follows="left|top" layout="topleft" left="0" - height="12" + height="13" name="notifications_alert" - width="350" + width="500" top_pad="11" visible="true" text_color="DrYellow"> - To temporarily stop all notifications, use Me > Status > Busy. + To temporarily stop all notifications, use Communicate > Do Not Disturb. @@ -288,7 +288,7 @@ @@ -299,7 +299,7 @@ left="0" name="play_sound" width="100" - top_pad="13" + top_pad="8" visible="true"> Play sound: diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 2cb063e8ee..ea0f7d8593 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -409,7 +409,7 @@ name="text_box3" top_pad="3" width="240"> - Busy mode response: + Do Not Disturb response: Date: Fri, 9 Nov 2012 16:16:06 -0800 Subject: CHUI-517: Updating the copy for the avatar in-world name bubble status for Do Not Disturb mode. --- indra/newview/skins/default/xui/en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 79ee83969b..8310e0c62d 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -295,7 +295,7 @@ Please try logging in again in a minute. (Editing Appearance) Away - Busy + Do Not Disturb Blocked -- cgit v1.2.3 From f429decb0c222b293cee4d3b27c8340262fab572 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Fri, 9 Nov 2012 17:00:43 -0800 Subject: CHUI-486: Now the new chat preferences in drop down lists and checkboxes are storable. These values are accessible globally using gSavedSettings. --- indra/llui/llcheckboxctrl.cpp | 14 +-- indra/llui/llcheckboxctrl.h | 2 - indra/newview/app_settings/settings.xml | 121 +++++++++++++++++++++ .../default/xui/en/panel_preferences_chat.xml | 46 ++++---- 4 files changed, 143 insertions(+), 40 deletions(-) diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index 4fe444c1a4..5525520d78 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -107,7 +107,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) LLButton::Params params = p.check_button; params.rect(btn_rect); //params.control_name(p.control_name); - params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2)); + params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onCommit, this)); params.commit_on_return(false); // Checkboxes only allow boolean initial values, but buttons can // take any LLSD. @@ -123,18 +123,6 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl() // Children all cleaned up by default view destructor. } - -// static -void LLCheckBoxCtrl::onButtonPress( const LLSD& data ) -{ - //if (mRadioStyle) - //{ - // setValue(TRUE); - //} - - onCommit(); -} - void LLCheckBoxCtrl::onCommit() { if( getEnabled() ) diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 67d8091a97..5ce45b2135 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -103,8 +103,6 @@ public: virtual void setControlName(const std::string& control_name, LLView* context); - void onButtonPress(const LLSD& data); - virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. virtual void resetDirty(); // Clear dirty state diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5694cb9f30..bba1f4910a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4667,6 +4667,17 @@ Value 1 + KeepConversationLogTranscripts + + Comment + Keep a conversation log and transcripts + Persist + 1 + Type + Boolean + Value + 0 + LandBrushSize Comment @@ -6285,6 +6296,61 @@ Value 305 + NotificationConferenceIMOptions + + Comment + Specifies how the UI responds to Conference IM Notifications. + Persist + 1 + Type + String + Value + 0 + + NotificationFriendIMOptions + + Comment + Specifies how the UI responds to Friend IM Notifications. + Persist + 1 + Type + String + Value + 0 + + NotificationGroupChatOptions + + Comment + Specifies how the UI responds to Group Chat Notifications. + Persist + 1 + Type + String + Value + 0 + + NotificationNearbyChatOptions + + Comment + Specifies how the UI responds to Nearby Chat Notifications. + Persist + 1 + Type + String + Value + 0 + + NotificationNonFriendIMOptions + + Comment + Specifies how the UI responds to Non Friend IM Notifications. + Persist + 1 + Type + String + Value + 0 + NotificationToastLifeTime Comment @@ -6801,6 +6867,61 @@ Value 1 + PlaySoundGroupChatMessages + + Comment + Plays a sound when have a group chat message. + Persist + 1 + Type + Boolean + Value + 0 + + PlaySoundIncomingVoiceCall + + Comment + Plays a sound when have an incoming voice call. + Persist + 1 + Type + Boolean + Value + 1 + + PlaySoundInventoryOffer + + Comment + Plays a sound when have an inventory offer. + Persist + 1 + Type + Boolean + Value + 0 + + PlaySoundNewConversation + + Comment + Plays a sound when have a new conversation. + Persist + 1 + Type + Boolean + Value + 1 + + PlaySoundTeleportOffer + + Comment + Plays a sound when have a teleport offer. + Persist + 1 + Type + Boolean + Value + 1 + PluginAttachDebuggerToPlugins Comment diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 4964df53bb..f1b11e2ca8 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -37,6 +37,7 @@ top_pad="6" width="330" /> Date: Fri, 9 Nov 2012 17:19:03 -0800 Subject: CHUI-450 : Fixed how the list of speakers is updated, always add the agent avatar in it, takes voice activation into account --- indra/newview/llfloaterimcontainer.cpp | 4 ++-- indra/newview/llspeakers.cpp | 26 +++++++++++--------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index b20d19d0fd..2789b78c2d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1126,7 +1126,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool /* widget processing */ if (select_widget) { - LLFolderViewItem* widget = mConversationsWidgets[session_id]; + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); @@ -1539,7 +1539,7 @@ void LLFloaterIMContainer::openNearbyChat() //(which it should be...), open it so to make the list of participants visible. This happens to be the most common case when opening the Chat floater. if(mConversationsItems.size() == 1) { - LLConversationViewSession* nearby_chat = dynamic_cast(mConversationsWidgets[LLUUID()]); + LLConversationViewSession* nearby_chat = dynamic_cast(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) { nearby_chat->setOpen(TRUE); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 726199b7aa..5036334bdd 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -503,27 +503,23 @@ void LLSpeakerMgr::update(BOOL resort_ok) void LLSpeakerMgr::updateSpeakerList() { - // are we bound to the currently active voice channel? - if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel)) - { - std::set participants; - LLVoiceClient::getInstance()->getParticipantList(participants); - // add new participants to our list of known speakers - for (std::set::iterator participant_it = participants.begin(); - participant_it != participants.end(); - ++participant_it) + // Are we bound to the currently active voice channel? + if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) + { + std::set participants; + LLVoiceClient::getInstance()->getParticipantList(participants); + // If we are, add all voice client participants to our list of known speakers + for (std::set::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) { setSpeaker(*participant_it, LLVoiceClient::getInstance()->getDisplayName(*participant_it), LLSpeaker::STATUS_VOICE_ACTIVE, (LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)); - - } } else { - // Check if the list is empty, except if it's Nearby Chat (session_id NULL). + // If not, check if the list is empty, except if it's Nearby Chat (session_id NULL). LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { @@ -533,16 +529,16 @@ void LLSpeakerMgr::updateSpeakerList() LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { - // Allow to set buddies if they are on line. Allow any other avatar. + // Add buddies if they are on line, add any other avatar. if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) { setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } - // Also add the current agent - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } + // Finally, always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) -- cgit v1.2.3 From 99181a9777b7e42ed6e863a074789f37aa6b43f8 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 9 Nov 2012 19:06:00 -0800 Subject: CHUI-479 : WIP : Fixed the missing agent appearance in torn off dialogs by adding a consistency check and rebuild. --- indra/newview/llfloaterimsessiontab.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index a47c9177a1..c39319b373 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -263,11 +263,21 @@ void LLFloaterIMSessionTab::draw() { if (mRefreshTimer->hasExpired()) { - if (getParticipantList()) + LLParticipantList* item = getParticipantList(); + if (item) { - getParticipantList()->update(); + // Update all model items + item->update(); + // If the model and view list diverge in count, rebuild + // Note: this happens sometimes right around init (add participant events fire but get dropped) and is the cause + // of missing participants, often, the user agent itself. As there will be no other event fired, there's + // no other choice but get those inconsistencies regularly (and lightly) checked and scrubbed. + if (item->getChildrenCount() != mConversationsWidgets.size()) + { + buildConversationViewParticipant(); + } } - + refreshConversation(); // Restart the refresh timer @@ -376,7 +386,7 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() LLParticipantList* item = getParticipantList(); if (!item) { - // Nothing to do if the model list is empty + // Nothing to do if the model list is inexistent return; } @@ -470,7 +480,8 @@ void LLFloaterIMSessionTab::refreshConversation() session_name = LLIMModel::instance().getName(mSessionID); } updateSessionName(session_name); - } + } + mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); mConversationsRoot->update(); -- cgit v1.2.3 From ab5a0a1d4d0a029dd92c9fc108638736a57ce7c6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 12 Nov 2012 15:06:42 +0200 Subject: CHUI-362 FIXED (Torn off conversation name is highlighted when selected in conversation list with different conversation showing in message panel): connect new method "returnFloaterToHost" to click on quasi-URL "Bring it back" --- indra/newview/llfloaterimcontainer.cpp | 12 ++++++++++-- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/skins/default/xui/en/floater_im_container.xml | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 994a76189a..2707e3dcbb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -133,7 +133,6 @@ void LLFloaterIMContainer::onCurrentChannelChanged(const LLUUID& session_id) } } - BOOL LLFloaterIMContainer::postBuild() { mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLFloaterIMContainer::onNewMessageReceived, this, _1)); @@ -142,7 +141,8 @@ BOOL LLFloaterIMContainer::postBuild() setTabContainer(getChild("im_box_tab_container")); mStubPanel = getChild("stub_panel"); - mStubTextBox = getChild("stub_textbox"); + mStubTextBox = getChild("stub_textbox_2"); + mStubTextBox->setURLClickedCallback(boost::bind(&LLFloaterIMContainer::returnFloaterToHost, this)); mConversationsStack = getChild("conversations_stack"); mConversationsPane = getChild("conversations_layout_panel"); @@ -506,6 +506,14 @@ void LLFloaterIMContainer::showStub(bool stub_is_visible) mStubPanel->setVisible(stub_is_visible); } +// listener for click on mStubTextBox2 +void LLFloaterIMContainer::returnFloaterToHost() +{ + LLUUID session_id = this->getSelectedSession(); + LLFloaterIMSessionTab* floater = LLFloaterIMSessionTab::getConversation(session_id); + floater->onTearOffClicked(); +} + void LLFloaterIMContainer::setVisible(BOOL visible) { LLFloaterIMNearbyChat* nearby_chat; if (visible) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index a09cde60f5..e60576a50d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -65,7 +65,7 @@ public: /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - + void returnFloaterToHost(); void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 94854ee9ee..8f5a8c2c1b 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -91,6 +91,7 @@ public: void buildConversationViewParticipant(); void setSortOrder(const LLConversationSort& order); + virtual void onTearOffClicked(); virtual void updateMessages() {} @@ -106,7 +107,6 @@ protected: bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); - virtual void onTearOffClicked(); // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e3db3d52ed..1388b9e474 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -159,9 +159,9 @@ top="40" height="20" valign="center" - parse_urls="false" + parse_urls="true" wrap="true"> - Bring it back. + [secondlife:/// Bring it back.] -- cgit v1.2.3 From 91781df3701da9852dbe87a4d5c9d5e3abf09987 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Mon, 12 Nov 2012 18:18:34 -0800 Subject: CHUI-486: Now toasts only appear when proper 'Chat Preference' setting is set to 'Pop Up Message'. --- indra/newview/llfloaterimnearbychathandler.cpp | 6 ++++ indra/newview/llimview.cpp | 45 ++++++++++++++++++-------- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 0dfaa9174b..f382b65b1d 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -283,6 +283,12 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { + //Ignore Nearby Toasts + if(gSavedSettings.getString("NotificationNearbyChatOptions") != "0") + { + return; + } + //look in pool. if there is any message if(mStopProcessing) return; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6712127750..e4b51b719b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -139,19 +139,38 @@ void toast_callback(const LLSD& msg){ return; } - // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - msg["session_id"]); - if (!gSavedSettings.getBOOL("EnableGroupChatPopups") - && session->isGroupSessionType()) - { - return; - } - if (!gSavedSettings.getBOOL("EnableIMChatPopups") - && !session->isGroupSessionType()) - { - return; - } + // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + msg["session_id"]); + + + //Ignore P2P Friend/Non-Friend toasts + if(session->isP2PSessionType()) + { + //Ignores non-friends + if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && + gSavedSettings.getString("NotificationNonFriendIMOptions") != "0") + { + return; + } + //Ignores friends + else if(gSavedSettings.getString("NotificationFriendIMOptions") != "0") + { + return; + } + } + //Ignore Ad Hoc Toasts + else if(session->isAdHocSessionType() && + gSavedSettings.getString("NotificationConferenceIMOptions") != "0") + { + return; + } + //Ignore Group Toasts + else if(session->isGroupSessionType() && + gSavedSettings.getString("NotificationGroupChatOptions") != "0") + { + return; + } LLAvatarNameCache::get(msg["from_id"].asUUID(), boost::bind(&on_avatar_name_cache_toast, -- cgit v1.2.3 From 6ba822c0fffcf86c79d25c44625c2667ac23e64a Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Tue, 13 Nov 2012 13:32:24 +0200 Subject: CHUI-460 FIXED Reselect floater after toggling the participant list open or closed --- indra/newview/llconversationview.cpp | 2 +- indra/newview/llfloaterimcontainer.cpp | 12 +++++++++++- indra/newview/llfloaterimcontainer.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..53392ac372 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -240,7 +240,7 @@ void LLConversationViewSession::toggleOpen() { getParentFolder()->setSelection(this, true); } - + mContainer->reSelectConversation(); } } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2707e3dcbb..962e9f4df6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -334,7 +334,7 @@ void LLFloaterIMContainer::onExpandCollapseButtonClicked() { collapseConversationsPane(!mConversationsPane->isCollapsed()); } - selectConversation(mSelectedSession); + reSelectConversation(); } LLFloaterIMContainer* LLFloaterIMContainer::findInstance() @@ -1574,4 +1574,14 @@ void LLFloaterIMContainer::onNearbyChatClosed() closeFloater(); } +void LLFloaterIMContainer::reSelectConversation() +{ + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (session_floater->getHost()) + { + selectFloater(session_floater); + } + +} + // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index e60576a50d..ad1f0039e9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -163,6 +163,7 @@ public: LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); + void reSelectConversation(); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); -- cgit v1.2.3 From aa2640f13ab61fa55819af26b001978fa2dd9a3f Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Tue, 13 Nov 2012 14:04:14 +0200 Subject: CHUI-447 FIXED Set session name as avatar's display name, if session is created by getting new message. --- indra/newview/llimview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6712127750..781b0cb2ea 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2424,14 +2424,21 @@ void LLIMMgr::addMessage( //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; + bool name_is_setted = false; if(!session_name.empty() && session_name.size()>1) { fixed_session_name = session_name; + name_is_setted = true; } bool new_session = !hasSession(new_session_id); if (new_session) { + LLAvatarName av_name; + if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) + { + fixed_session_name = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + } LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); // When we get a new IM, and if you are a god, display a bit -- cgit v1.2.3 From 5a31b5dceaeb7dd7089c7426371aac39927c5c02 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 13 Nov 2012 11:19:45 -0800 Subject: CHUI-486: Code cleanup, instead of using values such as 0, 1, 2 now using strings 'toast', 'flash', 'none'. These values are used whether to show a notification or not. --- indra/newview/app_settings/settings.xml | 10 ++++---- indra/newview/llfloaterimnearbychathandler.cpp | 2 +- indra/newview/llimview.cpp | 9 ++++--- .../default/xui/en/panel_preferences_chat.xml | 30 +++++++++++----------- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9b8c86ffc8..b703b9cc8e 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6316,7 +6316,7 @@ Type String Value - 0 + toast NotificationFriendIMOptions @@ -6327,7 +6327,7 @@ Type String Value - 0 + toast NotificationGroupChatOptions @@ -6338,7 +6338,7 @@ Type String Value - 0 + toast NotificationNearbyChatOptions @@ -6349,7 +6349,7 @@ Type String Value - 0 + toast NotificationNonFriendIMOptions @@ -6360,7 +6360,7 @@ Type String Value - 0 + toast NotificationToastLifeTime diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index f382b65b1d..ab81b85d04 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -284,7 +284,7 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { //Ignore Nearby Toasts - if(gSavedSettings.getString("NotificationNearbyChatOptions") != "0") + if(gSavedSettings.getString("NotificationNearbyChatOptions") != "toast") { return; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e4b51b719b..d57ffb9a11 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -149,29 +149,30 @@ void toast_callback(const LLSD& msg){ { //Ignores non-friends if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && - gSavedSettings.getString("NotificationNonFriendIMOptions") != "0") + gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast") { return; } //Ignores friends - else if(gSavedSettings.getString("NotificationFriendIMOptions") != "0") + else if(gSavedSettings.getString("NotificationFriendIMOptions") != "toast") { return; } } //Ignore Ad Hoc Toasts else if(session->isAdHocSessionType() && - gSavedSettings.getString("NotificationConferenceIMOptions") != "0") + gSavedSettings.getString("NotificationConferenceIMOptions") != "toast") { return; } //Ignore Group Toasts else if(session->isGroupSessionType() && - gSavedSettings.getString("NotificationGroupChatOptions") != "0") + gSavedSettings.getString("NotificationGroupChatOptions") != "toast") { return; } + //Show toast LLAvatarNameCache::get(msg["from_id"].asUUID(), boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index f1b11e2ca8..8ab5c9a99c 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -137,15 +137,15 @@ + value="toast"/> + value="flash"/> + value="none"/> + value="toast"/> + value="flash"/> + value="none"/> + value="toast"/> + value="flash"/> + value="none"/> + value="toast"/> + value="flash"/> + value="none"/> + value="toast"/> + value="flash"/> + value="none"/> Date: Tue, 13 Nov 2012 21:20:05 +0200 Subject: CHUI-512 FIXED (New incoming conversations take focus in message panel only and do not show toasts). Rejected update message when floater hasn't focus --- indra/newview/llfloaterimsession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 0c622e07c4..e1dc5b91d0 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -142,7 +142,7 @@ void LLFloaterIMSession::newIMCallback(const LLSD& data) LLFloaterIMSession* floater = LLFloaterReg::findTypedInstance("impanel", session_id); // update if visible, otherwise will be updated when opened - if (floater && floater->getVisible()) + if (floater && (floater->getHost()? floater->hasFocus() : floater->getVisible())) { floater->updateMessages(); } -- cgit v1.2.3 From df1fd5d4bbe8e71389872e4cdbac3e9f165cc3f8 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 14 Nov 2012 00:07:46 +0200 Subject: CHUI-508 FIXED Attach to and Attach to HUD menus not showing in inventory floater to select attachment point --- indra/newview/llinventorybridge.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 280a1775e9..52f2897788 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5453,6 +5453,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) p.on_enable.parameter = cbparams; LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; LLUICtrlFactory::create(p, parent); + items.push_back(p.name); } } } -- cgit v1.2.3 From d75824d520ba1965e48196f8b230ded0f15c5841 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 13 Nov 2012 16:45:56 -0800 Subject: CHUI-486: Post code review changes for last submit, just added in some parenthesis for conditional statements, thus making them more clear. --- indra/newview/llimview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3b217ef482..0f4bbd054a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -148,8 +148,8 @@ void toast_callback(const LLSD& msg){ if(session->isP2PSessionType()) { //Ignores non-friends - if(LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL && - gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast") + if((LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL) + && (gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast")) { return; } @@ -160,14 +160,14 @@ void toast_callback(const LLSD& msg){ } } //Ignore Ad Hoc Toasts - else if(session->isAdHocSessionType() && - gSavedSettings.getString("NotificationConferenceIMOptions") != "toast") + else if(session->isAdHocSessionType() + && (gSavedSettings.getString("NotificationConferenceIMOptions") != "toast")) { return; } //Ignore Group Toasts - else if(session->isGroupSessionType() && - gSavedSettings.getString("NotificationGroupChatOptions") != "toast") + else if(session->isGroupSessionType() + && (gSavedSettings.getString("NotificationGroupChatOptions") != "toast")) { return; } -- cgit v1.2.3 From 40949724345a00a22b1fae5d0645c244cbf47567 Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Wed, 14 Nov 2012 15:28:05 +0200 Subject: CHUI-389 FIXED Added parameter for sessionAdded to get access to has_offline_msg value. Set UnreadIMs icon to visible if messages were sent while offline. --- indra/newview/llchiclet.h | 2 +- indra/newview/llchicletbar.cpp | 2 +- indra/newview/llchicletbar.h | 2 +- indra/newview/llconversationlog.cpp | 33 +++++++++++++++++++++++------ indra/newview/llconversationlog.h | 12 ++++++----- indra/newview/llconversationloglist.cpp | 4 ++++ indra/newview/llconversationloglistitem.cpp | 5 +++++ indra/newview/llconversationloglistitem.h | 1 + indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llimview.cpp | 6 +++--- indra/newview/llimview.h | 4 ++-- indra/newview/llsyswellwindow.cpp | 2 +- indra/newview/llsyswellwindow.h | 2 +- 14 files changed, 55 insertions(+), 24 deletions(-) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 3c8389e20d..d6be2df103 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -873,7 +873,7 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver { friend class LLUICtrlFactory; public: - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) {} /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index ad7890b47a..c66ae1cdd0 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -84,7 +84,7 @@ LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) } //virtual -void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { if (!getChicletPanel()) return; diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index a9a5b61ae7..dc991ca772 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -50,7 +50,7 @@ public: LLChicletPanel* getChicletPanel() { return mChicletPanel; } // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 3d2b6a5c00..a0765f5e16 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -223,13 +223,17 @@ void LLConversationLog::enableLogging(bool enable) notifyObservers(); } -void LLConversationLog::logConversation(const LLUUID& session_id) +void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offline_msg) { const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); if (session && conversation) { + if(has_offline_msg) + { + updateOfflineIMs(session, has_offline_msg); + } updateConversationTimestamp(conversation); } else if (session && !conversation) @@ -265,7 +269,22 @@ void LLConversationLog::updateConversationName(const LLIMModel::LLIMSession* ses if (conversation) { conversation->setConverstionName(name); - notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_NAME); + } +} + +void LLConversationLog::updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages) +{ + if (!session) + { + return; + } + + LLConversation* conversation = findConversation(session); + if (conversation) + { + conversation->setOfflineMessages(new_messages); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_OfflineIMs); } } @@ -274,7 +293,7 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation if (conversation) { conversation->updateTimestamp(); - notifyPrticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); + notifyParticularConversationObservers(conversation->getSessionID(), LLConversationLogObserver::CHANGED_TIME); } } @@ -337,9 +356,9 @@ void LLConversationLog::removeObserver(LLConversationLogObserver* observer) mObservers.erase(observer); } -void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { - logConversation(session_id); + logConversation(session_id, has_offline_msg); } void LLConversationLog::cache() @@ -477,7 +496,7 @@ void LLConversationLog::notifyObservers() } } -void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask) +void LLConversationLog::notifyParticularConversationObservers(const LLUUID& session_id, U32 mask) { std::set::const_iterator iter = mObservers.begin(); for (; iter != mObservers.end(); ++iter) @@ -489,7 +508,7 @@ void LLConversationLog::notifyPrticularConversationObservers(const LLUUID& sessi void LLConversationLog::onNewMessageReceived(const LLSD& data) { const LLUUID session_id = data["session_id"].asUUID(); - logConversation(session_id); + logConversation(session_id, false); } void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session) diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 7d0b9113c6..8f6ac3f5d1 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -59,7 +59,7 @@ public: bool hasOfflineMessages() const { return mHasOfflineIMs; } void setConverstionName(std::string conv_name) { mConversationName = conv_name; } - + void setOfflineMessages(bool new_messages) { mHasOfflineIMs = new_messages; } bool isOlderThan(U32 days) const; /* @@ -123,7 +123,7 @@ public: void removeObserver(LLConversationLogObserver* observer); // LLIMSessionObserver triggers - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub virtual void sessionRemoved(const LLUUID& session_id){} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub @@ -147,9 +147,9 @@ private: /** * adds conversation to the conversation list and notifies observers */ - void logConversation(const LLUUID& session_id); + void logConversation(const LLUUID& session_id, BOOL has_offline_msg); - void notifyPrticularConversationObservers(const LLUUID& session_id, U32 mask); + void notifyParticularConversationObservers(const LLUUID& session_id, U32 mask); /** * constructs file name in which conversations log will be saved @@ -165,6 +165,7 @@ private: void createConversation(const LLIMModel::LLIMSession* session); void updateConversationTimestamp(LLConversation* conversation); void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name); + void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages); LLConversation* findConversation(const LLIMModel::LLIMSession* session); @@ -184,7 +185,8 @@ public: enum EConversationChange { CHANGED_TIME = 1, // last interaction time changed - CHANGED_NAME = 2 // conversation name changed + CHANGED_NAME = 2, // conversation name changed + CHANGED_OfflineIMs = 3 }; virtual ~LLConversationLogObserver(){} diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 429e99f7ad..6dbcb7bef7 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -171,6 +171,10 @@ void LLConversationLogList::changed(const LLUUID& session_id, U32 mask) mIsDirty = true; } } + else if (mask & LLConversationLogObserver::CHANGED_OfflineIMs) + { + item->updateOfflineIMs(); + } } void LLConversationLogList::addNewItem(const LLConversation* conversation) diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp index 9fad0e603e..4e984d603b 100644 --- a/indra/newview/llconversationloglistitem.cpp +++ b/indra/newview/llconversationloglistitem.cpp @@ -119,6 +119,11 @@ void LLConversationLogListItem::updateName() mConversationName->setValue(mConversation->getConversationName()); } +void LLConversationLogListItem::updateOfflineIMs() +{ + getChild("unread_ims_icon")->setVisible(mConversation->hasOfflineMessages()); +} + void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) { getChildView("hovered_icon")->setVisible(true); diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h index 57f72db382..ee28456bbb 100644 --- a/indra/newview/llconversationloglistitem.h +++ b/indra/newview/llconversationloglistitem.h @@ -69,6 +69,7 @@ public: */ void updateTimestamp(); void updateName(); + void updateOfflineIMs(); private: diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 962e9f4df6..af5db13023 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -96,7 +96,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer() } } -void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index ad1f0039e9..afc8d00174 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -85,7 +85,7 @@ public: static void idle(void* user_data); // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); /*virtual*/ void sessionRemoved(const LLUUID& session_id); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0f4bbd054a..0bb370e6fe 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -724,7 +724,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co // When notifying observer, name of session is used instead of "name", because they may not be the // same if it is an adhoc session (in this case name is localized in LLIMSession constructor). std::string session_name = LLIMModel::getInstance()->getName(session_id); - LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, session_name, other_participant_id); + LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, session_name, other_participant_id,has_offline_msg); return true; @@ -2974,11 +2974,11 @@ void LLIMMgr::clearPendingAgentListUpdates(const LLUUID& session_id) } } -void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, bool has_offline_msg) { for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) { - (*it)->sessionAdded(session_id, name, other_participant_id); + (*it)->sessionAdded(session_id, name, other_participant_id, has_offline_msg); } } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 054388bc6c..19b738069c 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -295,7 +295,7 @@ class LLIMSessionObserver { public: virtual ~LLIMSessionObserver() {} - virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; + virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) = 0; virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0; virtual void sessionRemoved(const LLUUID& session_id) = 0; @@ -462,7 +462,7 @@ private: static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group); - void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, bool has_offline_msg); //Triggers when a session has already been added void notifyObserverSessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 18e0d9d0d2..1b8bdf3b46 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -617,7 +617,7 @@ BOOL LLIMWellWindow::postBuild() //virtual void LLIMWellWindow::sessionAdded(const LLUUID& session_id, - const std::string& name, const LLUUID& other_participant_id) + const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); if (!session) return; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 378d5e0aa2..d6480f1fc6 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -170,7 +170,7 @@ public: /*virtual*/ BOOL postBuild(); // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); + /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; /*virtual*/ void sessionRemoved(const LLUUID& session_id); -- cgit v1.2.3 From 7a088e9b2c8ffddbf5cd8dad72281a64a32d7c63 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 14 Nov 2012 19:39:50 +0200 Subject: CHUI-501 FIXED Add link to Privacy tab from Comms floater --- indra/newview/llfloaterimcontainer.cpp | 19 +++++++++++-------- indra/newview/llfloaterpreference.cpp | 20 ++++++++++++++++++++ indra/newview/llfloaterpreference.h | 4 ++++ .../skins/default/xui/en/menu_participant_view.xml | 7 +++++++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af5db13023..ec1068d191 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -717,15 +717,18 @@ void LLFloaterIMContainer::onCustomAction(const LLSD& userdata) } if ("chat_preferences" == command) { - LLFloaterPreference* floater_prefs = LLFloaterReg::showTypedInstance("preferences"); - if (floater_prefs) + LLFloaterPreference * floater_prefp = LLFloaterReg::showTypedInstance("preferences"); + if (floater_prefp) { - LLTabContainer* tab_container = floater_prefs->getChild("pref core"); - LLPanel* chat_panel = tab_container->getPanelByName("chat"); - if (tab_container && chat_panel) - { - tab_container->selectTabPanel(chat_panel); - } + floater_prefp->selectChatPanel(); + } + } + if ("privacy_preferences" == command) + { + LLFloaterPreference * floater_prefp = LLFloaterReg::showTypedInstance("preferences"); + if (floater_prefp) + { + floater_prefp->selectPrivacyPanel(); } } } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 7c5e0776a7..ffd59ba8b6 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1570,6 +1570,26 @@ void LLFloaterPreference::setCacheLocation(const LLStringExplicit& location) cache_location_editor->setToolTip(location); } +void LLFloaterPreference::selectPanel(const LLSD& name) +{ + LLTabContainer * tab_containerp = getChild("pref core"); + LLPanel * panel = tab_containerp->getPanelByName(name); + if (NULL != panel) + { + tab_containerp->selectTabPanel(panel); + } +} + +void LLFloaterPreference::selectPrivacyPanel() +{ + selectPanel("im"); +} + +void LLFloaterPreference::selectChatPanel() +{ + selectPanel("chat"); +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 10a416beb5..4c1c122fb1 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -82,6 +82,8 @@ public: void processProfileProperties(const LLAvatarData* pAvatarData ); void storeAvatarProperties( const LLAvatarData* pAvatarData ); void saveAvatarProperties( void ); + void selectPrivacyPanel(); + void selectChatPanel(); protected: void onBtnOK(); @@ -164,6 +166,8 @@ public: void buildPopupLists(); static void refreshSkin(void* data); + void selectPanel(const LLSD& name); + private: static std::string sSkin; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 6fa0707eea..523ce7b35b 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -68,6 +68,13 @@ function="IMFloaterContainer.Action" parameter="chat_preferences" /> + + + Date: Wed, 14 Nov 2012 13:09:54 -0500 Subject: SH-3541 WIP - fixed one cause of local textures failing to load --- indra/newview/llviewerregion.cpp | 2 +- indra/newview/llvoavatarself.cpp | 33 +++++++++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index c8ab055e3f..f225a7640b 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1745,7 +1745,7 @@ bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) std::string LLViewerRegion::getCapability(const std::string& name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed"))) + if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) { llwarns << "getCapability called before caps received" << llendl; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 2b95a38086..88bf596a35 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2275,30 +2275,27 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { if (!isIndexLocalTexture(type)) return; - if (!covered_by_baked) + if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) { - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) - { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - imagep->setBoostLevel(getAvatarBoostLevel()); + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) - { - mHasGrey = TRUE; // for statistics gathering - } - } - else + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) { - // texture asset is missing mHasGrey = TRUE; // for statistics gathering } } + else + { + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering + } } LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const -- cgit v1.2.3 From e15921e42b4ac14504b22b0acbb349aa6d19664b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 14 Nov 2012 10:37:52 -0800 Subject: CHUI-479 : WIP : Small refactoring to allow participant to be added to session whether or not its parent folder is. --- indra/newview/llconversationview.cpp | 21 +++++++++++++-------- indra/newview/llconversationview.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..ad334869fb 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -460,21 +460,26 @@ void LLConversationViewParticipant::refresh() void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) { - //Add the item to the folder (conversation) + // Add the item to the folder (conversation) LLFolderViewItem::addToFolder(folder); - //Now retrieve the folder (conversation) UUID, which is the speaker session + // Retrieve the folder (conversation) UUID, which is also the speaker session UUID LLConversationItem* vmi = this->getParentFolder() ? dynamic_cast(this->getParentFolder()->getViewModelItem()) : NULL; - if(vmi) + if (vmi) { - //Allows speaking icon image to be loaded based on mUUID - mAvatarIcon->setValue(mUUID); - - //Allows the speaker indicator to be activated based on the user and conversation - mSpeakingIndicator->setSpeakerId(mUUID, vmi->getUUID()); + addToSession(vmi->getUUID()); } } +void LLConversationViewParticipant::addToSession(const LLUUID& session_id) +{ + //Allows speaking icon image to be loaded based on mUUID + mAvatarIcon->setValue(mUUID); + + //Allows the speaker indicator to be activated based on the user and conversation + mSpeakingIndicator->setSpeakerId(mUUID, session_id); +} + void LLConversationViewParticipant::onInfoBtnClick() { LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mUUID)); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index cc6995c207..3610ac67de 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -121,6 +121,7 @@ public: bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); void addToFolder(LLFolderViewFolder* folder); + void addToSession(const LLUUID& session_id); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index c39319b373..e78422145d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -417,6 +417,7 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); mConversationsWidgets[uuid] = participant_view; participant_view->addToFolder(mConversationsRoot); + participant_view->addToSession(mSessionID); participant_view->setVisible(TRUE); refreshConversation(); } -- cgit v1.2.3 From 33068c6da8f079c557e4fb520b074f6e5ce40ba4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 14 Nov 2012 10:40:51 -0800 Subject: CHUI-479 : WIP : Add debug tracing into speaking indicator manager and monitors (to be deleted eventually). --- indra/newview/llconversationmodel.cpp | 10 +++++++++ indra/newview/llconversationmodel.h | 1 + indra/newview/llconversationview.cpp | 32 ++++++++++++++++++++++++++++ indra/newview/llconversationview.h | 8 +++++-- indra/newview/lloutputmonitorctrl.cpp | 29 +++++++++++++++++++++++-- indra/newview/llspeakingindicatormanager.cpp | 7 ++++++ indra/newview/llspeakingindicatormanager.h | 2 +- 7 files changed, 84 insertions(+), 5 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 47a82bfe17..8aa740e5d1 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -440,6 +440,16 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam } } +LLConversationItemSession* LLConversationItemParticipant::getParentSession() +{ + LLConversationItemSession* parent_session = NULL; + if (hasParent()) + { + parent_session = dynamic_cast(mParent); + } + return parent_session; +} + void LLConversationItemParticipant::dumpDebugData() { llinfos << "Merov debug : participant, uuid = " << mUUID << ", name = " << mName << ", display name = " << mDisplayName << ", muted = " << mIsMuted << ", moderator = " << mIsModerator << llendl; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 481d46af58..2ee21d0c16 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -195,6 +195,7 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } void fetchAvatarName(); + LLConversationItemSession* getParentSession(); void dumpDebugData(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 295dd2ae6d..11eef3f7dc 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -327,6 +327,7 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); } + llinfos << "Merov debug : onCurrentVoiceSessionChanged, switchIndicator is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); mCallIconLayoutPanel->setVisible(is_active); } @@ -366,6 +367,11 @@ LLConversationViewParticipant::LLConversationViewParticipant( const LLConversati { } +LLConversationViewParticipant::~LLConversationViewParticipant() +{ + mActiveVoiceChannelConnection.disconnect(); +} + void LLConversationViewParticipant::initFromParams(const LLConversationViewParticipant::Params& params) { LLAvatarIconCtrl::Params avatar_icon_params(params.avatar_icon()); @@ -392,6 +398,7 @@ BOOL LLConversationViewParticipant::postBuild() mInfoBtn->setClickedCallback(boost::bind(&LLConversationViewParticipant::onInfoBtnClick, this)); mInfoBtn->setVisible(false); + mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewParticipant::onCurrentVoiceSessionChanged, this, _1)); mSpeakingIndicator = getChild("speaking_indicator"); if (!sStaticInitialized) @@ -445,6 +452,29 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) return arranged; } +void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& session_id) +{ + llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; + LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged participant_model = " << participant_model << llendl; + + if (participant_model) + { + //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 1" << llendl; + LLConversationItemSession* parent_session = participant_model->getParentSession(); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged parent_session = " << parent_session << llendl; + if (parent_session) + { + //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 2" << llendl; + bool is_active = (parent_session->getUUID() == session_id); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged, is_active = " << is_active << llendl; + mSpeakingIndicator->switchIndicator(is_active); + //llinfos << "Merov debug : onCurrentVoiceSessionChanged switchIndicator done" << llendl; + } + } + //llinfos << "Merov debug : onCurrentVoiceSessionChanged end" << llendl; +} + void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data @@ -453,6 +483,7 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsMuted(vmi->isMuted()); + //mSpeakingIndicator->switchIndicator(true); // Do the regular upstream refresh LLFolderViewItem::refresh(); @@ -471,6 +502,7 @@ void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) mAvatarIcon->setValue(mUUID); //Allows the speaker indicator to be activated based on the user and conversation +// llinfos << "Merov debug : setSpeakerId of " << mUUID << ", session id = " << vmi->getUUID() << llendl; mSpeakingIndicator->setSpeakerId(mUUID, vmi->getUUID()); } } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index cc6995c207..4b2c9b2d76 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -94,7 +94,7 @@ private: bool mMinimizedMode; LLVoiceClientStatusObserver* mVoiceClientObserver; - + boost::signals2::connection mActiveVoiceChannelConnection; }; @@ -116,7 +116,7 @@ public: Params(); }; - virtual ~LLConversationViewParticipant( void ) { } + virtual ~LLConversationViewParticipant( void ); bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } virtual void refresh(); @@ -140,6 +140,8 @@ protected: void onInfoBtnClick(); private: + void onCurrentVoiceSessionChanged(const LLUUID& session_id); + LLAvatarIconCtrl* mAvatarIcon; LLButton * mInfoBtn; LLOutputMonitorCtrl* mSpeakingIndicator; @@ -156,6 +158,8 @@ private: static void initChildrenWidths(LLConversationViewParticipant* self); void updateChildren(); LLView* getItemChildView(EAvatarListItemChildIndex child_view_index); + + boost::signals2::connection mActiveVoiceChannelConnection; }; #endif // LL_LLCONVERSATIONVIEW_H diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 4a9a50d96a..3569516388 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -278,21 +278,45 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { + static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); + bool test_on = (speaker_id == test_uuid); + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, this = " << this << ", session_id = " << session_id << llendl; + } if (speaker_id.isNull() && mSpeakerId.notNull()) { LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } - if (speaker_id.isNull() || speaker_id == mSpeakerId) return; + if (speaker_id.isNull() || speaker_id == mSpeakerId) + { + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, nothing done because mSpeakerId == speaker_id" << llendl; + } + return; + } if (mSpeakerId.notNull()) { + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, unregisterSpeakingIndicator" << llendl; + } // Unregister previous registration to avoid crash. EXT-4782. - LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); + if (getTargetSessionID() == session_id) + { + LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); + } } mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; + if (test_on) + { + llinfos << "Merov debug : setSpeakerId, registerSpeakingIndicator" << llendl; + } LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); //mute management @@ -320,6 +344,7 @@ void LLOutputMonitorCtrl::onChange() // virtual void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { + llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 900379ae1e..316a2739b8 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -155,6 +155,7 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i BOOL is_in_same_voice = LLVoiceClient::getInstance()->isParticipant(speaker_id); speakers_uuids.insert(speaker_id); + llinfos << "Merov debug : registerSpeakingIndicator call switchSpeakerIndicators, switch = " << is_in_same_voice << llendl; switchSpeakerIndicators(speakers_uuids, is_in_same_voice); } @@ -195,6 +196,7 @@ SpeakingIndicatorManager::~SpeakingIndicatorManager() void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) { + llinfos << "Merov debug : sOnCurrentChannelChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); mSwitchedIndicatorsOn.clear(); } @@ -208,16 +210,21 @@ void SpeakingIndicatorManager::onParticipantsChanged() LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL; // switch all indicators off + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end FALSE switch" << llendl; mSwitchedIndicatorsOn.clear(); LL_DEBUGS("SpeakingIndicator") << "Switching all ON, count: " << speakers_uuids.size() << LL_ENDL; // then switch current voice participants indicators on + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, TRUE" << llendl; switchSpeakerIndicators(speakers_uuids, TRUE); + llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end TRUE switch" << llendl; } void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) { + llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << llendl; LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); LLUUID session_id; if (voice_channel) diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index b0a147865b..c2cf2a3702 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -37,7 +37,7 @@ public: virtual ~LLSpeakingIndicator(){} virtual void switchIndicator(bool switch_on) = 0; -private: +//private: friend class SpeakingIndicatorManager; // Accessors for target voice session UUID. // They are intended to be used only from SpeakingIndicatorManager to ensure target session is -- cgit v1.2.3 From 284e1b44d7bcc463b0d3ca56eae76b19e8fea03f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 Nov 2012 13:54:48 -0500 Subject: Fix for build failures --- indra/newview/llvoavatar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 47cb31ae18..6f4dfdbe2a 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5881,7 +5881,9 @@ void LLVOAvatar::updateMeshTextures() if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) { LLViewerFetchedTexture* baked_img; +#ifndef LL_RELEASE_FOR_DOWNLOAD LLViewerFetchedTexture* existing_baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); +#endif const std::string url = getImageURL(i, mBakedTextureDatas[i].mLastTextureID); if (!url.empty()) { -- cgit v1.2.3 From d541d99fce104d28eac378947261297461603462 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 14 Nov 2012 21:44:58 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #1 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): build new class LLFlashTimer based on LLSysWellChiclet::FlashToLitTimer; prepared it for general purpose; replaced LLSysWellChiclet::FlashToLitTimer to LLFlashTimer --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llchiclet.cpp | 65 ++------------------------------- indra/newview/llchiclet.h | 5 ++- 4 files changed, 10 insertions(+), 66 deletions(-) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f652c9e50c..574fdc495a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -178,6 +178,7 @@ set(viewer_SOURCE_FILES llfilepicker.cpp llfilteredwearablelist.cpp llfirstuse.cpp + llflashtimer.cpp llflexibleobject.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp @@ -762,6 +763,7 @@ set(viewer_HEADER_FILES llfilepicker.h llfilteredwearablelist.h llfirstuse.h + llflashtimer.h llflexibleobject.h llfloaterabout.h llfloaterbvhpreview.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b703b9cc8e..14117ee47b 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13142,7 +13142,7 @@ Value 50.0 - WellIconFlashCount + FlashCount Comment Number of flashes of IM Well and Notification Well icons after which flashing buttons stay lit up. Requires restart. @@ -13153,7 +13153,7 @@ Value 3 - WellIconFlashPeriod + FlashPeriod Comment Period at which IM Well and Notification Well icons flash (seconds). Requires restart. diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 64d8a68a99..d6860640b7 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -67,60 +67,6 @@ boost::signals2::signal callback_t; - - /** - * Constructor. - * - * @param count - how many times callback should be called (twice to not change original state) - * @param period - how frequently callback should be called - * @param cb - callback to be called each tick - */ - FlashToLitTimer(S32 count, F32 period, callback_t cb) - : LLEventTimer(period) - , mCallback(cb) - , mFlashCount(2 * count) - , mCurrentFlashCount(0) - { - mEventTimer.stop(); - } - - BOOL tick() - { - mCallback(); - - if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop(); - return FALSE; - } - - void flash() - { - mCurrentFlashCount = 0; - mEventTimer.start(); - } - - void stopFlashing() - { - mEventTimer.stop(); - } - -private: - callback_t mCallback; - - /** - * How many times Well will blink. - */ - S32 mFlashCount; - S32 mCurrentFlashCount; -}; LLSysWellChiclet::Params::Params() : button("button") @@ -145,13 +91,8 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) mButton = LLUICtrlFactory::create(button_params); addChild(mButton); - // use settings from settings.xml to be able change them via Debug settings. See EXT-5973. - // Due to Timer is implemented as derived class from EventTimer it is impossible to change period - // in runtime. So, both settings are made as required restart. - static S32 flash_to_lit_count = gSavedSettings.getS32("WellIconFlashCount"); - static F32 flash_period = gSavedSettings.getF32("WellIconFlashPeriod"); - mFlashToLitTimer = new FlashToLitTimer(flash_to_lit_count, flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this)); + mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); } LLSysWellChiclet::~LLSysWellChiclet() @@ -191,7 +132,7 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) { mButton->setToggleState(toggled); } -void LLSysWellChiclet::changeLitState() +void LLSysWellChiclet::changeLitState(bool blink) { setNewMessagesState(!mIsNewMessagesState); } @@ -320,7 +261,7 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) // we have to flash to 'Lit' state each time new unread message is coming. if (counter > mCounter && im_not_visible) { - mFlashToLitTimer->flash(); + mFlashToLitTimer->startFlashing(); } else if (counter == 0) { diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index d6be2df103..79ffad92ef 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -29,6 +29,7 @@ #include "llavatariconctrl.h" #include "llbutton.h" +#include "llflashtimer.h" #include "llpanel.h" #include "lltextbox.h" #include "lloutputmonitorctrl.h" @@ -844,7 +845,7 @@ protected: * There is an assumption that it will be called 2*N times to do not change its start state. * @see FlashToLitTimer */ - void changeLitState(); + void changeLitState(bool blink); /** * Displays menu. @@ -860,7 +861,7 @@ protected: S32 mMaxDisplayedCount; bool mIsNewMessagesState; - FlashToLitTimer* mFlashToLitTimer; + LLFlashTimer* mFlashToLitTimer; LLContextMenu* mContextMenu; }; -- cgit v1.2.3 From 2540568a83ca07856ddb760a6983efb3b85430a2 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 Nov 2012 14:50:05 -0500 Subject: SH-3541 WIP - prioritize local textures when in local appearance --- indra/newview/llvoavatarself.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 88bf596a35..619058fd25 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2279,12 +2279,15 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - imagep->setBoostLevel(getAvatarBoostLevel()); + if (isUsingLocalAppearance()) + { + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + } imagep->resetTextureStats(); imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->forceUpdateBindStats() ; if (imagep->getDiscardLevel() < 0) { -- cgit v1.2.3 From 5a2c57048522355b943dda91537f2890eb1b7b66 Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Wed, 14 Nov 2012 22:52:54 +0000 Subject: Updating appearance utility package --- autobuild.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index ec71aa6f55..df511b7242 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@ archive hash - 77467c492c9fba1ae68ae630e92d8cb1 + a92421d42f358733bd7961120d91dbfe url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/266679/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121106.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/267036/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121114.tar.bz2 name linux -- cgit v1.2.3 From dccfd66d94ad813b55d6dc1667f94288079893e9 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 Nov 2012 18:30:14 -0500 Subject: block appearance messages while editing --- indra/newview/llvoavatar.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6f4dfdbe2a..3a5cc9fc14 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6462,6 +6462,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) return; } + if (isSelf() && isEditingAppearance()) + { + llinfos << "ignoring appearance message while in appearance edit" << llendl; + return; + } + mUseServerBakes = (appearance_version > 0); applyParsedTEMessage(tec); -- cgit v1.2.3 From 19e22ca030d6ac8e63a2db41f24460bbfb72fff1 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 15 Nov 2012 00:18:16 +0000 Subject: Bumping appearance utility source --- autobuild.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index df511b7242..41250621b2 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@ archive hash - a92421d42f358733bd7961120d91dbfe + d6da17e42aab527bbdd408aebfef8b00 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/267036/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121114.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/267038/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121115.tar.bz2 name linux -- cgit v1.2.3 From bd62d1d33717536e71f5fbb5ab4a477a69494c77 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 14 Nov 2012 20:00:01 -0800 Subject: CHUI-479 : WIP : More tracing --- indra/newview/llconversationmodel.cpp | 18 ++++++++++++------ indra/newview/llconversationmodel.h | 2 +- indra/newview/lloutputmonitorctrl.cpp | 8 +++++++- indra/newview/llspeakingindicatormanager.cpp | 8 ++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 8aa740e5d1..1c56bd672d 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -349,15 +349,21 @@ const bool LLConversationItemSession::getTime(F64& time) const return has_time; } -void LLConversationItemSession::dumpDebugData() +void LLConversationItemSession::dumpDebugData(bool dump_children) { + // Session info llinfos << "Merov debug : session " << this << ", uuid = " << mUUID << ", name = " << mName << ", is loaded = " << mIsLoaded << llendl; - LLConversationItemParticipant* participant = NULL; - child_list_t::iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + // Children info + if (dump_children) { - participant = dynamic_cast(*iter); - participant->dumpDebugData(); + for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + LLConversationItemParticipant* participant = dynamic_cast(*iter); + if (participant) + { + participant->dumpDebugData(); + } + } } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 2ee21d0c16..dd849210a8 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -168,7 +168,7 @@ public: void addVoiceOptions(menuentry_vec_t& items); virtual const bool getTime(F64& time) const; - void dumpDebugData(); + void dumpDebugData(bool dump_children = false); private: bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 3569516388..063b90e76b 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -48,6 +48,8 @@ LLColor4 LLOutputMonitorCtrl::sColorBound; //F32 LLOutputMonitorCtrl::sRectWidthRatio = 0.f; //F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f; +static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); + LLOutputMonitorCtrl::Params::Params() : draw_border("draw_border"), image_mute("image_mute"), @@ -278,7 +280,6 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { - static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); bool test_on = (speaker_id == test_uuid); if (test_on) { @@ -345,6 +346,11 @@ void LLOutputMonitorCtrl::onChange() void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; + bool test_on = (mSpeakerId == test_uuid); + if (test_on && !switch_on) + { + llinfos << "Merov debug : switching agent off!" << llendl; + } // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 316a2739b8..752218c776 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -224,13 +224,13 @@ void SpeakingIndicatorManager::onParticipantsChanged() void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) { - llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << llendl; LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); LLUUID session_id; if (voice_channel) { session_id = voice_channel->getSessionID(); } + llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << ", voice channel = " << session_id << llendl; speaker_ids_t::const_iterator it_uuid = speakers_uuids.begin(); for (; it_uuid != speakers_uuids.end(); ++it_uuid) @@ -255,17 +255,17 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea } was_switched_on = was_switched_on || switch_current_on; + llinfos << "Merov debug : indicator for " << *it_uuid << ", switch_current_on = " << switch_current_on << ", session = " << indicator->getTargetSessionID() << llendl; indicator->switchIndicator(switch_current_on); - } if (was_found) { - LL_DEBUGS("SpeakingIndicator") << mSpeakingIndicators.count(*it_uuid) << " indicators where found" << LL_ENDL; + LL_DEBUGS("SpeakingIndicator") << mSpeakingIndicators.count(*it_uuid) << " indicators were found" << LL_ENDL; if (switch_on && !was_switched_on) { - LL_DEBUGS("SpeakingIndicator") << "but non of them where switched on" << LL_ENDL; + LL_DEBUGS("SpeakingIndicator") << "but none of them were switched on" << LL_ENDL; } if (was_switched_on) -- cgit v1.2.3 From dbc37f6ca74dba6c6d5194e0397d5cfe6f570c1d Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Thu, 15 Nov 2012 10:38:21 +0200 Subject: CHUI-397 (Delay in removing names from participant list in nearby chat) CHUI-440 (Nearby chat participant list does not clear after teleport when conversation floater is closed/minimized) fixed --- indra/llui/llfolderviewitem.h | 1 + indra/newview/llconversationview.cpp | 14 +++++++++++++- indra/newview/llspeakers.cpp | 8 ++++++++ indra/newview/llspeakers.h | 3 +++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index b157aabdcf..152ca242e1 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -118,6 +118,7 @@ protected: // For now assuming all colors are the same in derived classes. static LLUIColor sFgColor; + static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; static LLUIColor sHighlightFgColor; static LLUIColor sFocusOutlineColor; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 53392ac372..d1649a93b1 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -409,6 +409,7 @@ BOOL LLConversationViewParticipant::postBuild() void LLConversationViewParticipant::draw() { static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); @@ -421,7 +422,18 @@ void LLConversationViewParticipant::draw() F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad; F32 text_left = (F32)getLabelXPos(); - LLColor4 color = mIsSelected ? sHighlightFgColor : sFgColor; + + LLColor4 color; + LLLocalSpeakerMgr *speakerMgr = LLLocalSpeakerMgr::getInstance(); + + if (speakerMgr && speakerMgr->isSpeakerToBeRemoved(mUUID)) + { + color = sFgDisabledColor; + } + else + { + color = mIsSelected ? sHighlightFgColor : sFgColor; + } drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 5036334bdd..88f29d7587 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -254,6 +254,10 @@ bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_ return true; } +bool LLSpeakersDelayActionsStorage::isTimerStarted(const LLUUID& speaker_id) +{ + return (mActionTimersMap.size() > 0) && (mActionTimersMap.find(speaker_id) != mActionTimersMap.end()); +} // // ModerationResponder @@ -603,6 +607,10 @@ const LLUUID LLSpeakerMgr::getSessionID() return mVoiceChannel->getSessionID(); } +bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id) +{ + return mSpeakerDelayRemover && mSpeakerDelayRemover->isTimerStarted(speaker_id); +} void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) { diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 8ab08661d3..7d518fe07b 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -193,6 +193,8 @@ public: void unsetActionTimer(const LLUUID& speaker_id); void removeAllTimers(); + + bool isTimerStarted(const LLUUID& speaker_id); private: /** * Callback of the each instance of LLSpeakerActionTimer. @@ -237,6 +239,7 @@ public: void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } const LLUUID getSessionID(); + bool isSpeakerToBeRemoved(const LLUUID& speaker_id); /** * Removes avaline speaker. -- cgit v1.2.3 From 0b910871ab2935bde912314515f8b53ec3ff754e Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 15 Nov 2012 13:12:04 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #2 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): build new class LLFlashTimer based on LLSysWellChiclet::FlashToLitTimer; prepared it for general purpose; replaced LLSysWellChiclet::FlashToLitTimer to LLFlashTimer --- indra/newview/llflashtimer.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++ indra/newview/llflashtimer.h | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 indra/newview/llflashtimer.cpp create mode 100644 indra/newview/llflashtimer.h diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp new file mode 100644 index 0000000000..f44ca9f90c --- /dev/null +++ b/indra/newview/llflashtimer.cpp @@ -0,0 +1,72 @@ +/** + * @file llflashtimer.cpp + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&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 "llflashtimer.h" +#include "llviewercontrol.h" + +LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) + : LLEventTimer(period) + , mCallback(cb) + , mCurrentTickCount(0) +{ + mEventTimer.stop(); + + // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. + // Due to Timer is implemented as derived class from EventTimer it is impossible to change period + // in runtime. So, both settings are made as required restart. + mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); + if (mPeriod<=0) + { + mPeriod = gSavedSettings.getF32("FlashPeriod"); + } +} + +BOOL LLFlashTimer::tick() +{ + bool blink = !(mCurrentTickCount % 2); + mCallback(blink); + + if (++mCurrentTickCount >= mFlashCount) + { + mEventTimer.stop(); + } + + return FALSE; +} + +void LLFlashTimer::startFlashing() +{ + mCurrentTickCount = 0; + mEventTimer.start(); +} + +void LLFlashTimer::stopFlashing() +{ + mEventTimer.stop(); +} diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h new file mode 100644 index 0000000000..95e458dff6 --- /dev/null +++ b/indra/newview/llflashtimer.h @@ -0,0 +1,62 @@ +/** + * @file llflashtimer.h + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&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_FLASHTIMER_H +#define LL_FLASHTIMER_H + +#include "lleventtimer.h" + +class LLFlashTimer : public LLEventTimer +{ +public: + + typedef boost::function callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + LLFlashTimer(callback_t cb, S32 count = 0, F32 period = 0.0); + ~LLFlashTimer() {}; + + /*virtual*/ BOOL tick(); + + void startFlashing(); + void stopFlashing(); + +private: + callback_t mCallback; + /** + * How many times Well will blink. + */ + S32 mFlashCount; + S32 mCurrentTickCount; +}; + +#endif /* LL_FLASHTIMER_H */ -- cgit v1.2.3 From ebce476bd6e4b4b8a6404fa83e8fa0d8b1e64dc5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 15 Nov 2012 11:13:45 -0500 Subject: SH-3484 WIP, SH-3546 WIP, SH-3541 WIP - restrict useBakedTexture when in local update, minor readability tweaks --- indra/newview/llvoavatar.cpp | 64 ++++++++++++++++++++++------------------ indra/newview/llvoavatarself.cpp | 4 ++- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3a5cc9fc14..160f498443 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5805,7 +5805,9 @@ void LLVOAvatar::updateMeshTextures() const LLViewerTexture* te_image = getImage(i, 0); if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) { - setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered. + // IMG_DEFAULT_AVATAR = a special texture that's never rendered. + const LLUUID& image_id = (i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR); + setImage(i, LLViewerTextureManager::getFetchedTexture(image_id), 0); } } @@ -5833,12 +5835,11 @@ void LLVOAvatar::updateMeshTextures() if (!other_culled) { // When an avatar is changing clothes and not in Appearance mode, - // use the last-known good baked texture until it finish the first + // use the last-known good baked texture until it finishes the first // render of the new layerset. layerset = getTexLayerSet(i); - layerset_invalid = layerset - && ( !layerset->getViewerComposite()->isInitialized() - || !layerset->isLocalTextureDataAvailable() ); + layerset_invalid = layerset && ( !layerset->getViewerComposite()->isInitialized() + || !layerset->isLocalTextureDataAvailable() ); use_lkg_baked_layer[i] = (!is_layer_baked[i] && (mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR) && layerset_invalid); @@ -5919,16 +5920,21 @@ void LLVOAvatar::updateMeshTextures() } else if (!isUsingLocalAppearance() && is_layer_baked[i]) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; + LLViewerFetchedTexture* baked_img = + LLViewerTextureManager::staticCastToFetchedTexture( + getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureID ) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). + // Even though the file may not be finished loading, + // we'll consider it loaded and use it (rather than + // doing compositing). useBakedTexture( baked_img->getID() ); } else { mBakedTextureDatas[i].mIsLoaded = FALSE; - if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) + if ( (baked_img->getID() != IMG_INVISIBLE) && + ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), src_callback_list, paused); @@ -5983,7 +5989,8 @@ void LLVOAvatar::updateMeshTextures() } - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); ++baked_iter) { @@ -6766,7 +6773,7 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - //llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; + // llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; LLUUID id = src_vi->getID(); LLUUID *avatar_idp = (LLUUID *)userdata; @@ -6797,12 +6804,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - - /* if(id == head_baked->getID()) - mHeadBakedLoaded = TRUE; - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); */ for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -6813,23 +6814,28 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) mBakedTextureDatas[i].mLastTextureID = id; mBakedTextureDatas[i].mIsUsed = true; - debugColorizeSubMeshes(i,LLColor4::green); - - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) + if (isUsingLocalAppearance()) { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setTexture( image_baked ); - } + llinfos << "not changing to baked texture while isUsingLocalAppearance" << llendl; } - if (mBakedTextureDatas[i].mTexLayerSet) + else { - //mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); + debugColorizeSubMeshes(i,LLColor4::green); + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setTexture( image_baked ); + } + } } - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = + LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 619058fd25..77deb5e3bc 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1379,7 +1379,8 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* laye const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - ret &= (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + BOOL tex_avail = (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + ret &= tex_avail; } } return ret; @@ -1781,6 +1782,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te local_tex_obj->setID(tex->getID()); setBakedReady(type,baked_version_ready,index); } + //virtual void LLVOAvatarSelf::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { -- cgit v1.2.3 From 70b9dd6ee6af483bf1c96631bb25fd6a3703b351 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Thu, 15 Nov 2012 10:41:53 -0800 Subject: CHUI-524: FIX Removing a function call that results in a circular logic loop and an eventual stack overflow crash. --- indra/newview/llfloaterimsessiontab.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 3a1cc2880a..26a97ea422 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -313,7 +313,13 @@ void LLFloaterIMSessionTab::onFocusReceived() if (container) { container->selectConversationPair(mSessionID, true); + // XXX stinson 11/15/2012 : calling show stub from this focus handler results in a circular + // logic loop of function calls that eventually result in a stack overflow. + // See CHUI-524 for documentation +#define XXX_STINSON_HACK_CHUI_524 1 +#if !XXX_STINSON_HACK_CHUI_524 container->showStub(! getHost()); +#endif } } -- cgit v1.2.3 From a3ad89dd3535e2621b9f100fe45a2a3814b4045a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 15 Nov 2012 13:54:22 -0500 Subject: removed param location from archetype dump - not currently used --- indra/newview/llvoavatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 160f498443..94a59253c4 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6356,10 +6356,10 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value) wtype = vparam->getWearableType(); } S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); - apr_file_printf(file, "\t\t\n", + apr_file_printf(file, "\t\t\n", viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(), - LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str(), - param_location_name(vparam->getParamLocation()).c_str() + LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str() +// param_location_name(vparam->getParamLocation()).c_str() ); } -- cgit v1.2.3 From f93604c399c889e06980554e1cb59a833e7f847d Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 15 Nov 2012 15:20:05 -0500 Subject: WIP Working on adding http request to increment the COF version when a change is made to an item in an agent's current outfit folder. SH-3339 --- indra/cmake/Variables.cmake | 1 + indra/newview/llpaneleditwearable.cpp | 42 +++++++++++++++++++++++++++++++++++ indra/newview/llpaneleditwearable.h | 12 ++++++---- indra/newview/llviewerregion.cpp | 1 + 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 895b3003db..4cd878a2e3 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -97,6 +97,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (WORD_SIZE EQUAL 32) set(DEB_ARCHITECTURE i386) + set(FIND_LIBRARY_USE_LIB64_PATHS OFF) else (WORD_SIZE EQUAL 32) set(DEB_ARCHITECTURE amd64) endif (WORD_SIZE EQUAL 32) diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 7832156a0e..9862c98cc8 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1028,6 +1028,46 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) } } +//static +void LLPanelEditWearable::incrementCofVersion() +{ + // Create a response handler + LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this)); + + // Look up the capability to POST to. + std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion"); + + // If we don't have a region, report it as an error + if (getRegion() == NULL) + { + responderPtr->error(0U, "region is not defined"); + } + else + { + // Find the capability to send maturity preference + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + + // If the capability is not defined, report it as an error + if (url.empty()) + { + responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); + } + else + { + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) + << "' via capability to: " << url << llendl; + LLSD headers; + LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); + } + } +} + void LLPanelEditWearable::saveChanges(bool force_save_as) { if (!mWearablePtr || !isDirty()) @@ -1050,6 +1090,8 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) { gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } + + LLPanelEditWearable::incrementCofVersion(); } void LLPanelEditWearable::revertChanges() diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 309d512e23..619486bb5b 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -31,6 +31,8 @@ #include "llscrollingpanellist.h" #include "llmodaldialog.h" #include "llavatarappearancedefines.h" +#include "llagent.h" +#include "llviewerregion.h" #include "llwearabletype.h" class LLAccordionCtrl; @@ -94,7 +96,7 @@ private: void toggleTypeSpecificControls(LLWearableType::EType type); void updateTypeSpecificControls(LLWearableType::EType type); - //alpha mask checkboxes + // alpha mask checkboxes void configureAlphaCheckbox(LLAvatarAppearanceDefines::ETextureIndex te, const std::string& name); void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te); void updateAlphaCheckboxes(); @@ -104,7 +106,7 @@ private: // callback for HeightUnits parameter. bool changeHeightUnits(const LLSD& new_value); - // updates current metric and replacemet metric label text + // updates current metric and replacement metric label text void updateMetricLayout(BOOL new_value); // updates avatar height label @@ -114,6 +116,8 @@ private: void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel); + static void incrementCofVersion(); + // the pointer to the wearable we're editing. NULL means we're not editing a wearable. LLViewerWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; @@ -128,7 +132,7 @@ private: LLTextBox *mTxtAvatarHeight; - // localized and parametrized strings that used to build avatar_height_label + // localized and parameterized strings that used to build avatar_height_label std::string mMeters; std::string mFeet; std::string mHeigth; @@ -151,7 +155,7 @@ private: LLPanel *mPanelEyes; LLPanel *mPanelHair; - //clothes + // clothes LLPanel *mPanelShirt; LLPanel *mPanelPants; LLPanel *mPanelShoes; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 0855bc9243..94533d97df 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1541,6 +1541,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("FetchLibDescendents2"); capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); + capabilityNames.append("IncrementCOFVersion"); } capabilityNames.append("GetDisplayNames"); -- cgit v1.2.3 From 4ea44918dd040520bdd8eb1e52f2b6ba6cfa6f8b Mon Sep 17 00:00:00 2001 From: maxim_productengine Date: Fri, 16 Nov 2012 19:36:46 +0200 Subject: CHUI-525 FIXED Tootlips are added for Info buttons --- indra/newview/skins/default/xui/en/panel_avatar_list_item.xml | 1 + indra/newview/skins/default/xui/en/panel_group_list_item.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index b7c58eb6ab..aa1b929412 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -129,6 +129,7 @@ left_pad="3" right="-53" name="info_btn" + tool_tip="More info" tab_stop="false" top_delta="0" width="16" /> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 12735026fa..cfe3aeb7c9 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -56,6 +56,7 @@ left_pad="3" right="-31" name="info_btn" + tool_tip="More info" tab_stop="false" top_delta="-2" width="16" /> -- cgit v1.2.3 From 16f5a67e6550c2041b69b5c8523ad9884d7110f1 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 15 Nov 2012 23:35:14 +0200 Subject: CHUI-442 FIXED Nearby chat does not open conversations floater when clicking first nearby chat toast in a session --- indra/newview/llfloaterimsessiontab.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 3a1cc2880a..da77ca0079 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -165,6 +165,11 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) || gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) { floater_container->addFloater(conversp, TRUE, LLTabContainer::END); + + if (!floater_container->getVisible()) + { + LLFloaterReg::toggleInstanceOrBringToFront("im_container"); + } } else { -- cgit v1.2.3 From e89616aac812a7c6080d577f8a284f6df56a51ea Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Thu, 15 Nov 2012 15:11:22 -0800 Subject: Backed out changeset: 80bab29003f8 Removing hack fix for CHUI-524. --- indra/newview/llfloaterimsessiontab.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 26a97ea422..3a1cc2880a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -313,13 +313,7 @@ void LLFloaterIMSessionTab::onFocusReceived() if (container) { container->selectConversationPair(mSessionID, true); - // XXX stinson 11/15/2012 : calling show stub from this focus handler results in a circular - // logic loop of function calls that eventually result in a stack overflow. - // See CHUI-524 for documentation -#define XXX_STINSON_HACK_CHUI_524 1 -#if !XXX_STINSON_HACK_CHUI_524 container->showStub(! getHost()); -#endif } } -- cgit v1.2.3 From 37d7f469055d3ba4b81815fa2ac8459022e1e3cf Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 15 Nov 2012 15:32:02 -0800 Subject: CHUI-524: The root reason of crash was in the infinity recursion in the chain of calls LLFloater::setFocus->LLFloater::setFrontmost->LLFloaterView::bringToFront. And problem was not related to CHUI-362. Reviewed by Stinson. --- indra/llui/llfloater.cpp | 10 +++++++++- indra/llui/llfloater.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e57ba02bf..1b6e4ed0e5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2234,7 +2234,8 @@ LLFloaterView::LLFloaterView (const Params& p) mFocusCycleMode(FALSE), mMinimizePositionVOffset(0), mSnapOffsetBottom(0), - mSnapOffsetRight(0) + mSnapOffsetRight(0), + mFrontChild(NULL) { mSnapView = getHandle(); } @@ -2383,6 +2384,13 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { + if (mFrontChild == child) + { + return; + } + + mFrontChild = child; + // *TODO: make this respect floater's mAutoFocus value, instead of // using parameter if (child->getHost()) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 07b79d5523..ca0710cdc1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -576,6 +576,7 @@ private: S32 mMinimizePositionVOffset; typedef std::vector, boost::signals2::connection> > hidden_floaters_t; hidden_floaters_t mHiddenFloaters; + LLFloater * mFrontChild; }; // -- cgit v1.2.3 From d3474c6eaf5f26986e7988f4ca773f67e034c49d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 15 Nov 2012 15:42:22 -0800 Subject: CHUI-489: Now sounds exist for teleport and inventory offers. The sound is specified in notifications.xml. Also changes for CHUI 486, which allow the user to set preferences for hearing sounds for a New Conversation, Incoming Voice Call, Teleport Offer and Inventory Offer. --- indra/llui/llfloater.cpp | 15 ++++++++++++++- indra/llui/llnotifications.cpp | 5 +++++ indra/llui/llnotifications.h | 1 + indra/newview/llimview.cpp | 6 +++++- indra/newview/lltoastnotifypanel.cpp | 15 +++++++++++++++ indra/newview/skins/default/xui/en/notifications.xml | 6 ++++-- .../skins/default/xui/en/panel_preferences_chat.xml | 1 + 7 files changed, 45 insertions(+), 4 deletions(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e57ba02bf..3ab66f3321 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -64,6 +64,8 @@ // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; +extern LLControlGroup gSavedSettings; + namespace LLInitParam { void TypeValues::declareValues() @@ -660,7 +662,18 @@ void LLFloater::openFloater(const LLSD& key) && !getFloaterHost() && (!getVisible() || isMinimized())) { - make_ui_sound("UISndWindowOpen"); + bool playSound = true; + + //Don't play a sound for incoming voice call based upon chat preference setting + if(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE) + { + playSound = false; + } + + if(playSound) + { + make_ui_sound("UISndWindowOpen"); + } } //RN: for now, we don't allow rehosting from one multifloater to another diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 929b7da081..fe84dbbdaf 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -899,6 +899,11 @@ bool LLNotification::hasFormElements() const return mTemplatep->mForm->getNumElements() != 0; } +void LLNotification::playSound() +{ + LLUI::sAudioCallback(mTemplatep->mSoundEffect); +} + LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const { return mTemplatep->mCombineBehavior; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index c677dfe298..088931858a 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -524,6 +524,7 @@ public: bool canLogToIM() const; bool canShowToast() const; bool hasFormElements() const; + void playSound(); typedef enum e_combine_behavior { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0f4bbd054a..f7b182e891 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2494,7 +2494,11 @@ void LLIMMgr::addMessage( return; } - make_ui_sound("UISndNewIncomingIMSession"); + //Play sound for new conversations + if(gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE) + { + make_ui_sound("UISndNewIncomingIMSession"); + } } bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index ccad49bc30..8672dc479d 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -493,6 +493,21 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) } // adjust panel's height to the text size snapToMessageHeight(mTextBox, MAX_LENGTH); + + bool playSound = true; + + if((mNotification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || mNotification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) + { + playSound = false; + } + + if(playSound) + { + mNotification->playSound(); + } } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6c2ad869ac..bf2bfaf386 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6460,7 +6460,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="UserGiveItem" log_to_im ="true" - type="offer"> + type="offer" + sound="UISndNewIncomingIMSession"> [NAME_SLURL] has given you this [OBJECTTYPE]: [ITEM_SLURL] @@ -6517,7 +6518,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th name="TeleportOffered" log_to_im="true" log_to_chat="false" - type="offer"> + type="offer" + sound="UISndNewIncomingIMSession"> [NAME_SLURL] has offered to teleport you to their location: “[MESSAGE]” diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 8ab5c9a99c..712e8bff7f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -322,6 +322,7 @@ name="incoming_voice_call" width="150" /> Date: Thu, 15 Nov 2012 17:34:34 -0800 Subject: CHUI-489: Found a bug in last commit for this issue. The sound notification (for inventory/teleport offer) would be played for the toast popup as well as once the conversations floater was opened. And also when a button was clicked in the conversation floater to 'accept' or 'deny' the offer. Now only playing the sound notification when the initial offer has been made. --- indra/newview/llnotificationofferhandler.cpp | 17 +++++++++++++++++ indra/newview/lltoastnotifypanel.cpp | 15 +-------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 6e641575fa..8b7cac9f4b 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -117,6 +117,23 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLScreenChannel* channel = dynamic_cast(mChannel.get()); if(channel) channel->addToast(p); + + bool playSound = true; + + //Play notification sound for inventory offer and teleport offer based upon chat preference + if((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) + { + playSound = false; + } + + if(playSound) + { + notification->playSound(); + } + } if (notification->canLogToIM()) diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 8672dc479d..844d7314d9 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -494,20 +494,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) // adjust panel's height to the text size snapToMessageHeight(mTextBox, MAX_LENGTH); - bool playSound = true; - - if((mNotification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) - || mNotification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) - { - playSound = false; - } - - if(playSound) - { - mNotification->playSound(); - } + } -- cgit v1.2.3 From ec5d1e48c4071500400b885e5893373bab0e3d99 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 15 Nov 2012 18:07:57 -0800 Subject: CHUI-479 : WIP : Introduce a publicly available LLSpeakingIndicatorManager::updateSpeakingIndicators() method so to reset all indicators when creating new dialogs. --- indra/newview/llconversationview.cpp | 25 ++++++++++++------------- indra/newview/lloutputmonitorctrl.cpp | 5 ----- indra/newview/llspeakingindicatormanager.cpp | 28 ++++++++++++++++++---------- indra/newview/llspeakingindicatormanager.h | 5 +++++ 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index cc7a76e353..d971c943f0 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -307,7 +307,9 @@ void LLConversationViewSession::refresh() mSessionTitle->setText(vmi->getDisplayName()); } - // Note: for the moment, all that needs to be done is done by LLFolderViewItem::refresh() + // Update all speaking indicators + llinfos << "Merov debug : LLConversationViewSession::refresh, updateSpeakingIndicators" << llendl; + LLSpeakingIndicatorManager::updateSpeakingIndicators(); // Do the regular upstream refresh LLFolderViewFolder::refresh(); @@ -327,7 +329,6 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); } - llinfos << "Merov debug : onCurrentVoiceSessionChanged, switchIndicator is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); mCallIconLayoutPanel->setVisible(is_active); } @@ -456,34 +457,32 @@ void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& s { llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged participant_model = " << participant_model << llendl; if (participant_model) { - //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 1" << llendl; LLConversationItemSession* parent_session = participant_model->getParentSession(); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged parent_session = " << parent_session << llendl; if (parent_session) { - //llinfos << "Merov debug : onCurrentVoiceSessionChanged enter if 2" << llendl; bool is_active = (parent_session->getUUID() == session_id); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged, is_active = " << is_active << llendl; mSpeakingIndicator->switchIndicator(is_active); - //llinfos << "Merov debug : onCurrentVoiceSessionChanged switchIndicator done" << llendl; } } - //llinfos << "Merov debug : onCurrentVoiceSessionChanged end" << llendl; } void LLConversationViewParticipant::refresh() { // Refresh the participant view from its model data - LLConversationItemParticipant* vmi = dynamic_cast(getViewModelItem()); - vmi->resetRefresh(); + LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); + participant_model->resetRefresh(); // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat - mSpeakingIndicator->setIsMuted(vmi->isMuted()); - //mSpeakingIndicator->switchIndicator(true); + mSpeakingIndicator->setIsMuted(participant_model->isMuted()); + //LLConversationItemSession* parent_session = participant_model->getParentSession(); + //if (parent_session) + //{ + // bool is_active = (parent_session->getUUID() == session_id); + // mSpeakingIndicator->switchIndicator(is_active); + //} // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 063b90e76b..536f1fbd73 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -346,11 +346,6 @@ void LLOutputMonitorCtrl::onChange() void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; - bool test_on = (mSpeakerId == test_uuid); - if (test_on && !switch_on) - { - llinfos << "Merov debug : switching agent off!" << llendl; - } // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 752218c776..d9f9ed5966 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -74,6 +74,16 @@ public: */ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator); + /** + * Callback of changing voice participant list (from LLVoiceClientParticipantObserver). + * + * Switches off indicators had been switched on and switches on indicators of current participants list. + * There is only a few indicators in lists should be switched off/on. + * So, method does not calculate difference between these list it only switches off already + * switched on indicators and switches on indicators of voice channel participants + */ + void onParticipantsChanged(); + private: typedef std::set speaker_ids_t; typedef std::multimap speaking_indicators_mmap_t; @@ -93,16 +103,6 @@ private: */ void sOnCurrentChannelChanged(const LLUUID& session_id); - /** - * Callback of changing voice participant list (from LLVoiceClientParticipantObserver). - * - * Switches off indicators had been switched on and switches on indicators of current participants list. - * There is only a few indicators in lists should be switched off/on. - * So, method does not calculate difference between these list it only switches off already - * switched on indicators and switches on indicators of voice channel participants - */ - void onParticipantsChanged(); - /** * Changes state of indicators specified by LLUUIDs * @@ -321,5 +321,13 @@ void LLSpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speak } } +void LLSpeakingIndicatorManager::updateSpeakingIndicators() +{ + if(SpeakingIndicatorManager::instanceExists()) + { + SpeakingIndicatorManager::instance().onParticipantsChanged(); + } +} + // EOF diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index c2cf2a3702..8ee368e258 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -78,6 +78,11 @@ namespace LLSpeakingIndicatorManager * @param speaking_indicator instance of the speaker indicator to be unregistered. */ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator); + + /** + * Switch on/off registered speaking indicator according to the most current voice client status + */ + void updateSpeakingIndicators(); } #endif // LL_LLSPEAKINGINDICATORMANAGER_H -- cgit v1.2.3 From 568d818ffe214c358f92717ceb86dd20cb4aed26 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Thu, 15 Nov 2012 19:08:08 -0800 Subject: CHUI-518: WIP First pass as implementing auto-reject voice calls in do not disturb mode. --- indra/newview/llimview.cpp | 16 +++++++++++----- indra/newview/llviewermessage.cpp | 4 +--- indra/newview/llviewermessage.h | 2 ++ indra/newview/skins/default/xui/en/notifications.xml | 1 + indra/newview/skins/default/xui/en/strings.xml | 3 ++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0bb370e6fe..50e2b48f30 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -64,6 +64,7 @@ #include "lltoolbarview.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" +#include "message.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -2801,12 +2802,17 @@ void LLIMMgr::inviteToSession( if (voice_invite) { - if ( // if we are rejecting group calls - (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && notify_box_type == "VoiceInviteGroup") || - // or we're rejecting non-friend voice calls and this isn't a friend - (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)) - ) + bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); + bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); + bool isRejectDoNotDisturb = gAgent.isDoNotDisturb(); + if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) { + if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) + { + LLSD args; + LLIMMgr::getInstance()->addSystemMessage(session_id, "you_auto_rejected_call", args); + send_do_not_disturb_message(gMessageSystem, caller_id, session_id); + } // silently decline the call LLIncomingCallDialog::processCallResponse(1, payload); return; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 56c9f81259..e21db146db 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,8 +179,6 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE // TeleportYourAgent }; -static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); - bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -3240,7 +3238,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } } -static void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) +void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) { if (gAgent.isDoNotDisturb()) { diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index b298f0060b..447fdeb9c7 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -152,6 +152,8 @@ void send_group_notice(const LLUUID& group_id, const std::string& message, const LLInventoryItem* item); +void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id = LLUUID::null); + void handle_lure(const LLUUID& invitee); void handle_lure(const uuid_vec_t& ids); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6c2ad869ac..eaa020ff49 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3695,6 +3695,7 @@ Do Not Disturb is on. You will not be notified of incoming communications. - Other residents will receive your Do Not Disturb response (set in Preferences > General). - Teleportation offers will be declined. +- Voice calls will be rejected. - Inventory offers will go to your Trash. Your call has been answered You started a voice call You joined the voice call - [NAME] started a voice call + You automatically rejected the voice call while 'Do Not Disturb' was on. + [NAME] started a voice call Joining voice call... -- cgit v1.2.3 From 987350fcb3cf2da03b70ac3fbadb0429f523d07a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 15 Nov 2012 19:24:45 -0800 Subject: CHUI-489: Code review cleanup for both CHUI-489 and CHUI-486. This should be last commit for CHUI-489. --- indra/llui/llfloater.cpp | 7 +------ indra/llui/llnotifications.cpp | 7 ++++--- indra/llui/llnotificationtemplate.h | 6 ++---- indra/newview/llnotificationofferhandler.cpp | 16 +++++----------- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index a3b5fb993d..ada2bde55e 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -662,13 +662,8 @@ void LLFloater::openFloater(const LLSD& key) && !getFloaterHost() && (!getVisible() || isMinimized())) { - bool playSound = true; - //Don't play a sound for incoming voice call based upon chat preference setting - if(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE) - { - playSound = false; - } + bool playSound = !(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE); if(playSound) { diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index fe84dbbdaf..9618c002f5 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -413,12 +413,13 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), mLogToChat(p.log_to_chat), mLogToIM(p.log_to_im), - mShowToast(p.show_toast) + mShowToast(p.show_toast), + mSoundName("") { if (p.sound.isProvided() && LLUI::sSettingGroups["config"]->controlExists(p.sound)) { - mSoundEffect = LLUUID(LLUI::sSettingGroups["config"]->getString(p.sound)); + mSoundName = p.sound; } BOOST_FOREACH(const LLNotificationTemplate::UniquenessContext& context, p.unique.contexts) @@ -901,7 +902,7 @@ bool LLNotification::hasFormElements() const void LLNotification::playSound() { - LLUI::sAudioCallback(mTemplatep->mSoundEffect); + make_ui_sound(mTemplatep->mSoundName.c_str()); } LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 9434efe1b9..906b83a400 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -323,10 +323,8 @@ struct LLNotificationTemplate LLNotificationFormPtr mForm; // default priority for notifications of this type ENotificationPriority mPriority; - // UUID of the audio file to be played when this notification arrives - // this is loaded as a name, but looked up to get the UUID upon template load. - // If null, it wasn't specified. - LLUUID mSoundEffect; + // Stores the sound name which can then be used to play the sound using make_ui_sound + std::string mSoundName; // List of tags that rules can match against. std::list mTags; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8b7cac9f4b..91003c7d53 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -118,22 +118,16 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) if(channel) channel->addToast(p); - bool playSound = true; - - //Play notification sound for inventory offer and teleport offer based upon chat preference - if((notification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) - || notification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE) - { - playSound = false; - } + //Will not play a notification sound for inventory and teleport offer based upon chat preference + bool playSound = !((notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer") == FALSE) + || notification->getName() == "TeleportOffered" + && gSavedSettings.getBOOL("PlaySoundTeleportOffer") == FALSE); if(playSound) { notification->playSound(); } - } if (notification->canLogToIM()) -- cgit v1.2.3 From 50b69c3f97c0b58791f7dd67f8b2fbdc9e8ef503 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 16 Nov 2012 12:38:40 +0200 Subject: CHUI-487, CHUI-488 W.I.P. #3 (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): implemented conversation's item flashing --- indra/llui/llbutton.cpp | 6 +++++- indra/llui/llfolderviewitem.cpp | 16 ++++++++++++---- indra/llui/llfolderviewitem.h | 2 ++ indra/newview/llflashtimer.cpp | 14 ++++++++++++-- indra/newview/llflashtimer.h | 6 +++++- indra/newview/llfloaterimcontainer.cpp | 11 +++++++++++ indra/newview/llfloaterimcontainer.h | 1 + 7 files changed, 48 insertions(+), 8 deletions(-) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 705fe16559..3b9076ee54 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -176,7 +176,11 @@ LLButton::LLButton(const LLButton::Params& p) { static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams()); - +if (this->getName() == "chat") +{ +bool q = false; +q = !q; +} if (!p.label_selected.isProvided()) { mSelectedLabel = mUnselectedLabel; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 822534ffcf..90568f344a 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,9 +23,11 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ + +#include "../newview/llflashtimer.h" + #include "linden_common.h" #include "llfolderviewitem.h" - #include "llfolderview.h" #include "llfolderviewmodel.h" #include "llpanel.h" @@ -142,6 +144,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { + mFlashTimer = new LLFlashTimer(); + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); @@ -676,12 +680,16 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; + bool flashing = mFlashTimer->isFlashing(); + + if (flashing? mFlashTimer->isHighlight() : mIsSelected) // always render "current" item (only render other selected items if + // mShowSingleSelection is FALSE) or flashing item - if (mIsSelected) // always render "current" item. Only render other selected items if mShowSingleSelection is FALSE { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLColor4 bg_color = bgColor; - if (!mIsCurSelection) + bool selection = flashing? mFlashTimer->isHighlight() : mIsCurSelection; + if (!selection) { // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); @@ -701,7 +709,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo getRect().getWidth() - 2, focus_bottom, bg_color, hasKeyboardFocus); - if (mIsCurSelection) + if (selection) { gl_rect_2d(FOCUS_LEFT, focus_top, diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 152ca242e1..c16d65206f 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -29,6 +29,7 @@ #include "llview.h" #include "lluiimage.h" +class LLFlashTimer; class LLFolderView; class LLFolderViewModelItem; class LLFolderViewFolder; @@ -272,6 +273,7 @@ public: private: static std::map sFonts; // map of styles to fonts + LLFlashTimer* mFlashTimer; }; diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp index f44ca9f90c..2feacfa218 100644 --- a/indra/newview/llflashtimer.cpp +++ b/indra/newview/llflashtimer.cpp @@ -29,11 +29,13 @@ #include "llflashtimer.h" #include "llviewercontrol.h" +#include "lleventtimer.h" LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) : LLEventTimer(period) , mCallback(cb) , mCurrentTickCount(0) + , mIsFlashing(false) { mEventTimer.stop(); @@ -49,8 +51,11 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) BOOL LLFlashTimer::tick() { - bool blink = !(mCurrentTickCount % 2); - mCallback(blink); + mIsHighlight = !(mCurrentTickCount % 2); + if (mCallback) + { + mCallback(mIsHighlight); + } if (++mCurrentTickCount >= mFlashCount) { @@ -63,10 +68,15 @@ BOOL LLFlashTimer::tick() void LLFlashTimer::startFlashing() { mCurrentTickCount = 0; + mIsFlashing = true; mEventTimer.start(); } void LLFlashTimer::stopFlashing() { + mIsFlashing = false; + mIsHighlight = false; mEventTimer.stop(); } + + diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h index 95e458dff6..c030edfc52 100644 --- a/indra/newview/llflashtimer.h +++ b/indra/newview/llflashtimer.h @@ -42,13 +42,15 @@ public: * @param period - how frequently callback should be called * @param cb - callback to be called each tick */ - LLFlashTimer(callback_t cb, S32 count = 0, F32 period = 0.0); + LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); ~LLFlashTimer() {}; /*virtual*/ BOOL tick(); void startFlashing(); void stopFlashing(); + bool isFlashing() {return mIsFlashing;} + bool isHighlight() {return mIsHighlight;} private: callback_t mCallback; @@ -57,6 +59,8 @@ private: */ S32 mFlashCount; S32 mCurrentTickCount; + bool mIsHighlight; + bool mIsFlashing; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index aebfdb5bce..da6f3a484d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1154,6 +1154,7 @@ void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) } } + // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { @@ -1596,4 +1597,14 @@ void LLFloaterIMContainer::reSelectConversation() } +void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id) +{ + LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); + if (widget) + { + widget->; + } + +} + // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index afc8d00174..443688668b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -164,6 +164,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); + void flashConversationItemWidget(const LLUUID& session_id); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); -- cgit v1.2.3 From ed3f43aec48097c56d617a8948d2577624762a88 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 16 Nov 2012 11:14:12 -0800 Subject: CHUI-479 : WIP : Tracing of LLIMModel::processSessionInitializedReply (to be deleted). --- indra/newview/llfloaterimcontainer.cpp | 25 +++++++++++++++++++++++-- indra/newview/llfloaterimsessiontab.cpp | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2707e3dcbb..af090338d7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -98,6 +98,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer() void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { + llinfos << "Merov debug : sessionAdded, uuid = " << session_id << ", name = " << name << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -109,14 +110,33 @@ void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std: void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { + llinfos << "Merov debug : sessionVoiceOrIMStarted, uuid = " << session_id << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - // *TODO: We should do this *without* delete and recreate - addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); + llinfos << "Merov debug : sessionIDUpdated, old_session_id = " << old_session_id << ", new_session_id = " << new_session_id << llendl; + // Retrieve the session LLFloaterIMSessionTab + // just close it: that should erase the mSession, close the tab and remove the list item + // *TODO : take the mSessions element (pointing to the tab) out of the list + //bool change_focus = removeConversationListItem(old_session_id); + // *TODO : detach the old tab from the host + // *TODO : delete the tab (that's one thing that's reentrant) + LLFloater* floaterp = get_ptr_in_map(mSessions, old_session_id); + if (floaterp) + { + llinfos << "Merov debug : closeFloater, start" << llendl; + floaterp->closeFloater(); + llinfos << "Merov debug : closeFloater, end" << llendl; + } + bool change_focus = false; + llinfos << "Merov debug : addConversationListItem" << llendl; + addConversationListItem(new_session_id, change_focus); + llinfos << "Merov debug : addToHost" << llendl; + LLFloaterIMSessionTab::addToHost(new_session_id); + llinfos << "Merov debug : end sessionIDUpdated" << llendl; } void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) @@ -1300,6 +1320,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { + llinfos << "Merov debug : removeConversationListItem, uuid = " << uuid << llendl; // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6b13f5f381..6fbc713590 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -721,6 +721,7 @@ void LLFloaterIMSessionTab::onClose(bool app_quitting) LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { + llinfos << "Merov debug : LLFloaterIMSessionTab::onClose, mKey = " << mKey << llendl; im_box->removeConversationListItem(mKey); } } -- cgit v1.2.3 From e298c2ded8e25a28127c668cf30a74a25c139041 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 16 Nov 2012 22:36:12 +0200 Subject: CHUI-487, CHUI-488 FIXED (Enable flashing FUI button behavior and Implement Flashing Conversations panel line item behavior): implemented FUI button flashing; clean up code --- indra/llui/CMakeLists.txt | 2 + indra/llui/llbutton.cpp | 46 ++++++++---------- indra/llui/llbutton.h | 6 +-- indra/llui/llflashtimer.cpp | 80 ++++++++++++++++++++++++++++++++ indra/llui/llflashtimer.h | 67 +++++++++++++++++++++++++++ indra/llui/llfolderviewitem.cpp | 15 +++--- indra/llui/llfolderviewitem.h | 3 +- indra/llui/lltabcontainer.cpp | 4 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llflashtimer.cpp | 82 --------------------------------- indra/newview/llflashtimer.h | 66 -------------------------- indra/newview/llfloaterimcontainer.cpp | 14 ++++-- indra/newview/llfloaterimcontainer.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 10 ++++ 14 files changed, 206 insertions(+), 193 deletions(-) create mode 100644 indra/llui/llflashtimer.cpp create mode 100644 indra/llui/llflashtimer.h delete mode 100644 indra/newview/llflashtimer.cpp delete mode 100644 indra/newview/llflashtimer.h diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 80cec6c9f3..ccc7aa8cec 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -47,6 +47,7 @@ set(llui_SOURCE_FILES lleditmenuhandler.cpp llf32uictrl.cpp llfiltereditor.cpp + llflashtimer.cpp llflatlistview.cpp llfloater.cpp llfloaterreg.cpp @@ -153,6 +154,7 @@ set(llui_HEADER_FILES lleditmenuhandler.h llf32uictrl.h llfiltereditor.h + llflashtimer.h llflatlistview.h llfloater.h llfloaterreg.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 3b9076ee54..8a34e221b1 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -170,17 +170,18 @@ LLButton::LLButton(const LLButton::Params& p) mMouseUpSignal(NULL), mHeldDownSignal(NULL), mUseDrawContextAlpha(p.use_draw_context_alpha), - mHandleRightMouse(p.handle_right_mouse), - mButtonFlashCount(p.button_flash_count), - mButtonFlashRate(p.button_flash_rate) + mHandleRightMouse(p.handle_right_mouse) { + // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be + // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"); + S32 flash_count = p.button_flash_count || 0; + F32 flash_rate = p.button_flash_rate || 0.0; // + mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams()); -if (this->getName() == "chat") -{ -bool q = false; -q = !q; -} + if (!p.label_selected.isProvided()) { mSelectedLabel = mUnselectedLabel; @@ -271,6 +272,7 @@ LLButton::~LLButton() delete mMouseDownSignal; delete mMouseUpSignal; delete mHeldDownSignal; + delete mFlashingTimer; } // HACK: Committing a button is the same as instantly clicking it. @@ -595,22 +597,11 @@ void LLButton::draw() { static LLCachedControl sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - bool flash = FALSE; - if( mFlashing) - { - if ( sEnableButtonFlashing) - { - F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); - // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); - } - else - { // otherwise just highlight button in flash color - flash = true; - } - } + mFlashing = mFlashingTimer->isFlashing(); + + bool flash = mFlashing && + (!sEnableButtonFlashing || mFlashingTimer->isHighlight()); bool pressed_by_keyboard = FALSE; if (hasFocus()) @@ -955,10 +946,13 @@ void LLButton::setToggleState(BOOL b) void LLButton::setFlashing( BOOL b ) { - if ((bool)b != mFlashing) + if (b) + { + mFlashingTimer->startFlashing(); + } + else { - mFlashing = b; - mFlashingTimer.reset(); + mFlashingTimer->stopFlashing(); } } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index deaa0823c6..92548298f5 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llbadgeowner.h" #include "llcontrol.h" +#include "llflashtimer.h" #include "lluictrl.h" #include "v4color.h" #include "llframetimer.h" @@ -201,6 +202,7 @@ public: void setHighlight(bool b); void setFlashing( BOOL b ); BOOL getFlashing() const { return mFlashing; } + LLFlashTimer* getFlashTimer() {return mFlashingTimer;} void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } LLFontGL::HAlign getHAlign() const { return mHAlign; } @@ -285,8 +287,6 @@ protected: LLFrameTimer mMouseDownTimer; bool mNeedsHighlight; - S32 mButtonFlashCount; - F32 mButtonFlashRate; void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); void resetMouseDownTimer(); @@ -373,7 +373,7 @@ protected: bool mForcePressedState; bool mDisplayPressedState; - LLFrameTimer mFlashingTimer; + LLFlashTimer* mFlashingTimer; bool mHandleRightMouse; }; diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp new file mode 100644 index 0000000000..c572a83ff5 --- /dev/null +++ b/indra/llui/llflashtimer.cpp @@ -0,0 +1,80 @@ +/** + * @file llflashtimer.cpp + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&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 "../newview/llviewerprecompiledheaders.h" + +#include "llflashtimer.h" +#include "../newview/llviewercontrol.h" +#include "lleventtimer.h" + +LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) + : LLEventTimer(period) + , mCallback(cb) + , mCurrentTickCount(0) + , mIsFlashing(false) +{ + mEventTimer.stop(); + + // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. + // Due to Timer is implemented as derived class from EventTimer it is impossible to change period + // in runtime. So, both settings are made as required restart. + mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); + if (mPeriod<=0) + { + mPeriod = gSavedSettings.getF32("FlashPeriod"); + } +} + +BOOL LLFlashTimer::tick() +{ + mIsHighlight = !(mCurrentTickCount % 2); + if (mCallback) + { + mCallback(mIsHighlight); + } + + if (++mCurrentTickCount >= mFlashCount) + { + mEventTimer.stop(); + } + + return FALSE; +} + +void LLFlashTimer::startFlashing() +{ + mCurrentTickCount = 0; + mIsFlashing = true; + mEventTimer.start(); +} + +void LLFlashTimer::stopFlashing() +{ + mIsFlashing = false; + mIsHighlight = false; + mEventTimer.stop(); +} + + diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h new file mode 100644 index 0000000000..2ef6ebcc8a --- /dev/null +++ b/indra/llui/llflashtimer.h @@ -0,0 +1,67 @@ +/** + * @file llflashtimer.h + * @brief LLFlashTimer class implementation + * + * $LicenseInfo:firstyear=2002&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_FLASHTIMER_H +#define LL_FLASHTIMER_H + +#include "lleventtimer.h" + +class LLFlashTimer : public LLEventTimer +{ +public: + + typedef boost::function callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ + LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); + ~LLFlashTimer() {}; + + /*virtual*/ BOOL tick(); + + void startFlashing(); + void stopFlashing(); + + bool isFlashing() {return mIsFlashing;} + bool isHighlight() {return mIsHighlight;} + +private: + callback_t mCallback; + /** + * How many times parent will blink. + */ + S32 mFlashCount; + S32 mCurrentTickCount; + bool mIsHighlight; + bool mIsFlashing; +}; + +#endif /* LL_FLASHTIMER_H */ diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 90568f344a..d65f53cd4d 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,8 +23,9 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ +#include "../newview/llviewerprecompiledheaders.h" -#include "../newview/llflashtimer.h" +#include "llflashtimer.h" #include "linden_common.h" #include "llfolderviewitem.h" @@ -164,17 +165,19 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) } } +// Destroys the object +LLFolderViewItem::~LLFolderViewItem() +{ + delete mFlashTimer; + mViewModelItem = NULL; +} + BOOL LLFolderViewItem::postBuild() { refresh(); return TRUE; } -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) -{ - mViewModelItem = NULL; -} LLFolderView* LLFolderViewItem::getRoot() { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index c16d65206f..c8d6c37b04 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -26,10 +26,10 @@ #ifndef LLFOLDERVIEWITEM_H #define LLFOLDERVIEWITEM_H +#include "llflashtimer.h" #include "llview.h" #include "lluiimage.h" -class LLFlashTimer; class LLFolderView; class LLFolderViewModelItem; class LLFolderViewFolder; @@ -163,6 +163,7 @@ public: S32 getIconPad(); S32 getTextPad(); + LLFlashTimer* getFlashTimer() {return mFlashTimer;} // If 'selection' is 'this' then note that otherwise ignore. // Returns TRUE if this item ends up being selected. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index c24eb2ee90..d1f77830a6 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -506,8 +506,8 @@ void LLTabContainer::draw() } } - mPrevArrowBtn->setFlashing(FALSE); - mNextArrowBtn->setFlashing(FALSE); + mPrevArrowBtn->getFlashTimer()->stopFlashing(); + mNextArrowBtn->getFlashTimer()->stopFlashing(); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 574fdc495a..f652c9e50c 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -178,7 +178,6 @@ set(viewer_SOURCE_FILES llfilepicker.cpp llfilteredwearablelist.cpp llfirstuse.cpp - llflashtimer.cpp llflexibleobject.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp @@ -763,7 +762,6 @@ set(viewer_HEADER_FILES llfilepicker.h llfilteredwearablelist.h llfirstuse.h - llflashtimer.h llflexibleobject.h llfloaterabout.h llfloaterbvhpreview.h diff --git a/indra/newview/llflashtimer.cpp b/indra/newview/llflashtimer.cpp deleted file mode 100644 index 2feacfa218..0000000000 --- a/indra/newview/llflashtimer.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file llflashtimer.cpp - * @brief LLFlashTimer class implementation - * - * $LicenseInfo:firstyear=2002&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 "llflashtimer.h" -#include "llviewercontrol.h" -#include "lleventtimer.h" - -LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) - : LLEventTimer(period) - , mCallback(cb) - , mCurrentTickCount(0) - , mIsFlashing(false) -{ - mEventTimer.stop(); - - // By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973. - // Due to Timer is implemented as derived class from EventTimer it is impossible to change period - // in runtime. So, both settings are made as required restart. - mFlashCount = 2 * ((count>0)? count : gSavedSettings.getS32("FlashCount")); - if (mPeriod<=0) - { - mPeriod = gSavedSettings.getF32("FlashPeriod"); - } -} - -BOOL LLFlashTimer::tick() -{ - mIsHighlight = !(mCurrentTickCount % 2); - if (mCallback) - { - mCallback(mIsHighlight); - } - - if (++mCurrentTickCount >= mFlashCount) - { - mEventTimer.stop(); - } - - return FALSE; -} - -void LLFlashTimer::startFlashing() -{ - mCurrentTickCount = 0; - mIsFlashing = true; - mEventTimer.start(); -} - -void LLFlashTimer::stopFlashing() -{ - mIsFlashing = false; - mIsHighlight = false; - mEventTimer.stop(); -} - - diff --git a/indra/newview/llflashtimer.h b/indra/newview/llflashtimer.h deleted file mode 100644 index c030edfc52..0000000000 --- a/indra/newview/llflashtimer.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file llflashtimer.h - * @brief LLFlashTimer class implementation - * - * $LicenseInfo:firstyear=2002&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_FLASHTIMER_H -#define LL_FLASHTIMER_H - -#include "lleventtimer.h" - -class LLFlashTimer : public LLEventTimer -{ -public: - - typedef boost::function callback_t; - - /** - * Constructor. - * - * @param count - how many times callback should be called (twice to not change original state) - * @param period - how frequently callback should be called - * @param cb - callback to be called each tick - */ - LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); - ~LLFlashTimer() {}; - - /*virtual*/ BOOL tick(); - - void startFlashing(); - void stopFlashing(); - bool isFlashing() {return mIsFlashing;} - bool isHighlight() {return mIsHighlight;} - -private: - callback_t mCallback; - /** - * How many times Well will blink. - */ - S32 mFlashCount; - S32 mCurrentTickCount; - bool mIsHighlight; - bool mIsFlashing; -}; - -#endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index da6f3a484d..90ddeef5bb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -41,6 +41,7 @@ #include "llcallbacklist.h" #include "llgroupactions.h" #include "llgroupiconctrl.h" +#include "llflashtimer.h" #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" #include "llimview.h" @@ -1594,17 +1595,22 @@ void LLFloaterIMContainer::reSelectConversation() { selectFloater(session_floater); } - } -void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id) +void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget) { - widget->; + if (is_flashes) + { + widget->getFlashTimer()->startFlashing(); + } + else + { + widget->getFlashTimer()->stopFlashing(); + } } - } // EOF diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 443688668b..9112b54018 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -164,7 +164,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); - void flashConversationItemWidget(const LLUUID& session_id); + void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); private: LLConversationViewSession* createConversationItemWidget(LLConversationItem* item); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 69b42cdd6d..42e7e6cb55 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -40,6 +40,7 @@ #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" +#include "lltoolbarview.h" #include "llfloaterimnearbychat.h" const F32 REFRESH_INTERVAL = 0.2f; @@ -328,11 +329,20 @@ std::string LLFloaterIMSessionTab::appendTime() void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args) { + // Update the participant activity time LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { im_box->setTimeNow(mSessionID,chat.mFromID); + + // TODO: Warning! The next two lines of code are included below only temporarily + // to demonstrate the correct format call the appropriate functions. + // They should be moved to the right places when working on CHUI-486. ~Alex ProductEngine. + // ---- start demo ---- + im_box->flashConversationItemWidget(mSessionID, true); // flashing of the conversation's item + gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + // ---- end demo ----- } -- cgit v1.2.3 From ee810bf2abe230769bd5ee81dc76e54d5fcda34c Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Fri, 16 Nov 2012 17:07:45 -0500 Subject: WIP First buildable code after adding support for SH-3339. --- indra/cmake/Variables.cmake | 24 ++------- indra/newview/llpaneleditwearable.cpp | 96 ++++++++++++++++++++++++----------- indra/newview/llpaneleditwearable.h | 3 +- 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 54c77da64e..4cd878a2e3 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -70,6 +70,10 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(LINUX ON BOOl FORCE) + if (INSTALL_PROPRIETARY) + set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") + endif (INSTALL_PROPRIETARY) + # If someone has specified a word size, use that to determine the # architecture. Otherwise, let the architecture specify the word size. if (WORD_SIZE EQUAL 32) @@ -94,36 +98,18 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (WORD_SIZE EQUAL 32) set(DEB_ARCHITECTURE i386) set(FIND_LIBRARY_USE_LIB64_PATHS OFF) - set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH}) else (WORD_SIZE EQUAL 32) set(DEB_ARCHITECTURE amd64) - set(FIND_LIBRARY_USE_LIB64_PATHS ON) endif (WORD_SIZE EQUAL 32) - execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH - RESULT_VARIABLE DPKG_RESULT - OUTPUT_VARIABLE DPKG_ARCH - OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH RESULT_VARIABLE DPKG_RESULT OUTPUT_VARIABLE DPKG_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) #message (STATUS "DPKG_RESULT ${DPKG_RESULT}, DPKG_ARCH ${DPKG_ARCH}") if (DPKG_RESULT EQUAL 0) set(CMAKE_LIBRARY_ARCHITECTURE ${DPKG_ARCH}) - set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib/${DPKG_ARCH} /usr/local/lib/${DPKG_ARCH} ${CMAKE_SYSTEM_LIBRARY_PATH}) endif (DPKG_RESULT EQUAL 0) - include(ConfigurePkgConfig) - set(LL_ARCH ${ARCH}_linux) set(LL_ARCH_DIR ${ARCH}-linux) - - if (INSTALL_PROPRIETARY) - # Only turn on headless if we can find osmesa libraries. - include(FindPkgConfig) - pkg_check_modules(OSMESA osmesa) - if (OSMESA_FOUND) - set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") - endif (OSMESA_FOUND) - endif (INSTALL_PROPRIETARY) - endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 9862c98cc8..997edbab07 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -26,6 +26,8 @@ #include "llviewerprecompiledheaders.h" +#include + #include "llpaneleditwearable.h" #include "llpanel.h" #include "llviewerwearable.h" @@ -47,6 +49,7 @@ #include "llscrollingpanelparam.h" #include "llradiogroup.h" #include "llnotificationsutil.h" +#include "llhttpclient.h" #include "llcolorswatch.h" #include "lltexturectrl.h" @@ -1028,44 +1031,75 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) } } +class LLIncrementCofVersionResponder : public LLHTTPClient::Responder +{ +public: + LLIncrementCofVersionResponder(S32 retries); + virtual ~LLIncrementCofVersionResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + LLAgent *mAgent; + S32 mRetries; +}; + +LLIncrementCofVersionResponder::LLIncrementCofVersionResponder(S32 retries) + : LLHTTPClient::Responder(), + mRetries(retries) +{ +} + +LLIncrementCofVersionResponder::~LLIncrementCofVersionResponder() +{ +} + +void LLIncrementCofVersionResponder::result(const LLSD &pContent) +{ + lldebugs << "Successfully incremented agent's COF." << llendl; + +} + +void LLIncrementCofVersionResponder::error(U32 pStatus, const std::string& pReason) +{ + llwarns << "While attempting to increment the agent's cof we got an error because '" + << pReason << "' [status:" << pStatus << "]" << llendl; + LLPanelEditWearable::incrementCofVersion(mRetries++); +} + //static -void LLPanelEditWearable::incrementCofVersion() +void LLPanelEditWearable::incrementCofVersion(S32 retries) { - // Create a response handler - LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this)); + // Create a response handler + LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLIncrementCofVersionResponder(retries)); - // Look up the capability to POST to. - std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion"); + // If we don't have a region, report it as an error + if (gAgent.getRegion() == NULL) + { + responderPtr->error(0U, "region is not defined"); + } + else + { + // Find the capability to send maturity preference + std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion"); - // If we don't have a region, report it as an error - if (getRegion() == NULL) + // If the capability is not defined, report it as an error + if (url.empty()) { - responderPtr->error(0U, "region is not defined"); + responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); } else { - // Find the capability to send maturity preference - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - - // If the capability is not defined, report it as an error - if (url.empty()) - { - responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); - } - else - { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); - - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) - << "' via capability to: " << url << llendl; - LLSD headers; - LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); - } - } + llinfos << "Requesting cof_version be incremented via capability to: " + << url << llendl; + LLSD headers; + LLSD body = LLSD::emptyMap(); + LLHTTPClient::post(url, body, responderPtr, headers, 30.0f); + } + } } void LLPanelEditWearable::saveChanges(bool force_save_as) @@ -1091,7 +1125,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } - LLPanelEditWearable::incrementCofVersion(); + LLPanelEditWearable::incrementCofVersion(0); } void LLPanelEditWearable::revertChanges() diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 619486bb5b..9c9eac791e 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -78,6 +78,7 @@ public: virtual void setVisible(BOOL visible); + static void incrementCofVersion(S32 retries); private: typedef std::map value_map_t; @@ -116,8 +117,6 @@ private: void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel); - static void incrementCofVersion(); - // the pointer to the wearable we're editing. NULL means we're not editing a wearable. LLViewerWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; -- cgit v1.2.3 From c6a0f0ae1dec5ef2f7657d8c1ca07d85c1fef55d Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Fri, 16 Nov 2012 16:17:11 -0800 Subject: CHUI-518: FIX Removing the LLIMMgr::getInstance() as the containing method is already a non-static member method of the same class. --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a38153c315..e2b678626b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2814,7 +2814,7 @@ void LLIMMgr::inviteToSession( if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) { LLSD args; - LLIMMgr::getInstance()->addSystemMessage(session_id, "you_auto_rejected_call", args); + addSystemMessage(session_id, "you_auto_rejected_call", args); send_do_not_disturb_message(gMessageSystem, caller_id, session_id); } // silently decline the call -- cgit v1.2.3 From 2d9285cddb4a48fb766b21fac2705c8873e15f93 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Fri, 16 Nov 2012 18:53:05 -0800 Subject: CHUI-529: Now the conversations floater will appear when the chat preference is set for friend, non-friend, conference, group and nearby chat. --- indra/newview/llfloaterimnearbychathandler.cpp | 50 ++++++---- indra/newview/llimview.cpp | 104 +++++++++++++-------- .../default/xui/en/panel_preferences_chat.xml | 20 ++++ 3 files changed, 116 insertions(+), 58 deletions(-) diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index ab81b85d04..2d8a6d46fe 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -41,6 +41,7 @@ #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance #include "llviewerwindow.h"//for screen channel position #include "llfloaterimnearbychat.h" +#include "llfloaterimcontainer.h" #include "llrootview.h" #include "lllayoutstack.h" @@ -283,12 +284,6 @@ bool LLFloaterIMNearbyChatScreenChannel::createPoolToast() void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) { - //Ignore Nearby Toasts - if(gSavedSettings.getString("NotificationNearbyChatOptions") != "toast") - { - return; - } - //look in pool. if there is any message if(mStopProcessing) return; @@ -606,19 +601,36 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, toast_msg = chat_msg.mText; } - // Add a nearby chat toast. - LLUUID id; - id.generate(); - chat["id"] = id; - std::string r_color_name = "White"; - F32 r_color_alpha = 1.0f; - LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); - - chat["text_color"] = r_color_name; - chat["color_alpha"] = r_color_alpha; - chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; - chat["message"] = toast_msg; - channel->addChat(chat); + + //Will show toast when chat preference is set + if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") + { + // Add a nearby chat toast. + LLUUID id; + id.generate(); + chat["id"] = id; + std::string r_color_name = "White"; + F32 r_color_alpha = 1.0f; + LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); + + chat["text_color"] = r_color_name; + chat["color_alpha"] = r_color_alpha; + chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; + chat["message"] = toast_msg; + channel->addChat(chat); + } + //Will show Conversations floater when chat preference is set + else if(gSavedSettings.getString("NotificationNearbyChatOptions") == "openconversations") + { + LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); + + if(floaterIMContainer) + { + floaterIMContainer->setVisible(TRUE); + floaterIMContainer->setFrontmost(TRUE); + } + } + } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 818de4eaf4..106811b7e0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -112,6 +112,55 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } +//Will return true if the preference is allowed (user configures these preferences via 'Chat Preference' Dialog +bool ignoreNotification(const LLSD& msg, const char * preferenceString) +{ + //Get the session so we can find out the type of session + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + msg["session_id"]); + + const LLRelationship * relationship; + + // Skip system messages + if (msg["from_id"].asUUID() == LLUUID::null) + { + return true; + } + + //Ignore P2P Friend/Non-Friend Notification + if(session->isP2PSessionType()) + { + relationship = LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]); + + //Ignores non-friends + if(relationship == NULL + && (gSavedSettings.getString("NotificationNonFriendIMOptions") != preferenceString)) + { + return true; + } + //Ignores friends + else if(relationship + && gSavedSettings.getString("NotificationFriendIMOptions") != preferenceString) + { + return true; + } + } + //Ignore Ad Hoc Notification + else if(session->isAdHocSessionType() + && (gSavedSettings.getString("NotificationConferenceIMOptions") != preferenceString)) + { + return true; + } + //Ignore Group Notification + else if(session->isGroupSessionType() + && (gSavedSettings.getString("NotificationGroupChatOptions") != preferenceString)) + { + return true; + } + + return false; +} + void toast_callback(const LLSD& msg){ // do not show toast in do not disturb mode or it goes from agent if (gAgent.isDoNotDisturb() || gAgent.getID() == msg["from_id"]) @@ -133,55 +182,32 @@ void toast_callback(const LLSD& msg){ return; } - // Skip toasting for system messages - if (msg["from_id"].asUUID() == LLUUID::null) - { - return; - } - - // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - msg["session_id"]); - - - //Ignore P2P Friend/Non-Friend toasts - if(session->isP2PSessionType()) - { - //Ignores non-friends - if((LLAvatarTracker::instance().getBuddyInfo(msg["from_id"]) == NULL) - && (gSavedSettings.getString("NotificationNonFriendIMOptions") != "toast")) - { - return; - } - //Ignores friends - else if(gSavedSettings.getString("NotificationFriendIMOptions") != "toast") - { - return; - } - } - //Ignore Ad Hoc Toasts - else if(session->isAdHocSessionType() - && (gSavedSettings.getString("NotificationConferenceIMOptions") != "toast")) + //Show toast + if(ignoreNotification(msg, "toast") == false) { - return; + LLAvatarNameCache::get(msg["from_id"].asUUID(), + boost::bind(&on_avatar_name_cache_toast, + _1, _2, msg)); } - //Ignore Group Toasts - else if(session->isGroupSessionType() - && (gSavedSettings.getString("NotificationGroupChatOptions") != "toast")) +} + +void open_conversations_callback(const LLSD& msg) +{ + LLFloaterIMContainer * floaterIMContainer = LLFloaterIMContainer::getInstance(); + + if(floaterIMContainer + && ignoreNotification(msg, "openconversations") == false) { - return; + floaterIMContainer->setVisible(TRUE); + floaterIMContainer->setFrontmost(TRUE); } - - //Show toast - LLAvatarNameCache::get(msg["from_id"].asUUID(), - boost::bind(&on_avatar_name_cache_toast, - _1, _2, msg)); } LLIMModel::LLIMModel() { addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1)); addNewMsgCallback(boost::bind(&toast_callback, _1)); + addNewMsgCallback(boost::bind(&open_conversations_callback, _1)); } LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg) diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 712e8bff7f..0c94b6b223 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -134,6 +134,10 @@ top_delta="-6" name="FriendIMOptions" width="223"> + + + + + Date: Fri, 16 Nov 2012 21:01:57 -0800 Subject: CHUI-479 : Fixed : Rebuild the root on the LLFloaterIMSession when modifying the session ID --- indra/newview/llfloaterimcontainer.cpp | 42 ++++++++----------- indra/newview/llfloaterimsessiontab.cpp | 72 +++++++++++++++++---------------- indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 55 insertions(+), 60 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af090338d7..bd692aa850 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -117,26 +117,20 @@ void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) void LLFloaterIMContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - llinfos << "Merov debug : sessionIDUpdated, old_session_id = " << old_session_id << ", new_session_id = " << new_session_id << llendl; - // Retrieve the session LLFloaterIMSessionTab - // just close it: that should erase the mSession, close the tab and remove the list item - // *TODO : take the mSessions element (pointing to the tab) out of the list - //bool change_focus = removeConversationListItem(old_session_id); - // *TODO : detach the old tab from the host - // *TODO : delete the tab (that's one thing that's reentrant) - LLFloater* floaterp = get_ptr_in_map(mSessions, old_session_id); - if (floaterp) - { - llinfos << "Merov debug : closeFloater, start" << llendl; - floaterp->closeFloater(); - llinfos << "Merov debug : closeFloater, end" << llendl; - } - bool change_focus = false; - llinfos << "Merov debug : addConversationListItem" << llendl; + // The general strategy when a session id is modified is to delete all related objects and create them anew. + + // Note however that the LLFloaterIMSession has its session id updated through a call to sessionInitReplyReceived() + // and do not need to be deleted and recreated (trying this creates loads of problems). We do need however to suppress + // its related mSessions record as it's indexed with the wrong id. + // Grabbing the updated LLFloaterIMSession and readding it in mSessions will eventually be done by addConversationListItem(). + mSessions.erase(old_session_id); + + // Delete the model and participants related to the old session + bool change_focus = removeConversationListItem(old_session_id); + + // Create a new conversation with the new id addConversationListItem(new_session_id, change_focus); - llinfos << "Merov debug : addToHost" << llendl; LLFloaterIMSessionTab::addToHost(new_session_id); - llinfos << "Merov debug : end sessionIDUpdated" << llendl; } void LLFloaterIMContainer::sessionRemoved(const LLUUID& session_id) @@ -483,14 +477,14 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) else if (type == "update_session") { session_view->refresh(); - if (conversation_floater) - { - conversation_floater->refreshConversation(); - } } mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); + if (conversation_floater) + { + conversation_floater->refreshConversation(); + } return false; } @@ -1253,10 +1247,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& return item_it->second; } - // Remove the conversation item that might exist already: it'll be recreated anew further down anyway - // and nothing wrong will happen removing it if it doesn't exist - removeConversationListItem(uuid,false); - // Create a conversation session model LLConversationItemSession* item = NULL; LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6fbc713590..22131eac49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -52,6 +52,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mCloseBtn(NULL) , mSessionID(session_id.asUUID()) , mConversationsRoot(NULL) + , mScroller(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorTopPad(0) @@ -68,10 +69,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); - - // Zero expiry time is set only once to allow initial update. - mRefreshTimer->setTimerExpirySec(0); - mRefreshTimer->start(); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -195,33 +192,16 @@ BOOL LLFloaterIMSessionTab::postBuild() mParticipantListPanel = getChild("speakers_list_panel"); - // Create a root view folder for all participants - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - mConversationsRoot = LLUICtrlFactory::create(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - // Add a scroller for the folder (participant) view LLRect scroller_view_rect = mParticipantListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams()); scroller_params.rect(scroller_view_rect); - LLScrollContainer* scroller = LLUICtrlFactory::create(scroller_params); - scroller->setFollowsAll(); - - // Insert that scroller into the panel widgets hierarchy and folder view - mParticipantListPanel->addChild(scroller); - scroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(scroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + mScroller = LLUICtrlFactory::create(scroller_params); + mScroller->setFollowsAll(); + // Insert that scroller into the panel widgets hierarchy + mParticipantListPanel->addChild(mScroller); mChatHistory = getChild("chat_history"); @@ -235,8 +215,6 @@ BOOL LLFloaterIMSessionTab::postBuild() setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); - buildConversationViewParticipant(); - mSaveRect = isTornOff(); initRectControl(); @@ -249,8 +227,14 @@ BOOL LLFloaterIMSessionTab::postBuild() result = LLDockableFloater::postBuild(); } + // Now ready to build the conversation and participants list + buildConversationViewParticipant(); refreshConversation(); - + + // Zero expiry time is set only once to allow initial update. + mRefreshTimer->setTimerExpirySec(0); + mRefreshTimer->start(); + return result; } @@ -276,9 +260,8 @@ void LLFloaterIMSessionTab::draw() { buildConversationViewParticipant(); } + refreshConversation(); } - - refreshConversation(); // Restart the refresh timer mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); @@ -390,7 +373,31 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() // Nothing to do if the model list is inexistent return; } - + + // Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture + // We need to redo this when rebuilding as the session id (mSessionID) *may* have changed + if (mConversationsRoot) + { + // Remove the old root if any + mScroller->removeChild(mConversationsRoot); + } + // Create the root using an ad-hoc base item + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + mConversationsRoot = LLUICtrlFactory::create(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Attach that root to the scroller + mScroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(mScroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + // Create the participants widgets now LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); @@ -420,7 +427,6 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p participant_view->addToFolder(mConversationsRoot); participant_view->addToSession(mSessionID); participant_view->setVisible(TRUE); - refreshConversation(); } } @@ -432,7 +438,6 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part mConversationsRoot->extractItem(widget); delete widget; mConversationsWidgets.erase(participant_id); - refreshConversation(); } } @@ -443,7 +448,6 @@ void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& part { widget->refresh(); } - refreshConversation(); } void LLFloaterIMSessionTab::refreshConversation() diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 8f5a8c2c1b..b765d121de 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -146,6 +146,7 @@ protected: conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; + LLScrollContainer* mScroller; LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; -- cgit v1.2.3 From 2d25eb18adc0c2c97c63a8e02f2274362672137c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Sat, 17 Nov 2012 13:24:41 -0800 Subject: CHUI-479 : Clean up unecessary tracking code --- indra/newview/llconversationview.cpp | 8 -------- indra/newview/llfloaterimcontainer.cpp | 2 -- indra/newview/llfloaterimsessiontab.cpp | 1 - indra/newview/lloutputmonitorctrl.cpp | 27 ++------------------------- indra/newview/llspeakingindicatormanager.cpp | 8 -------- indra/newview/llspeakingindicatormanager.h | 2 +- 6 files changed, 3 insertions(+), 45 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d971c943f0..64618fabba 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -308,7 +308,6 @@ void LLConversationViewSession::refresh() } // Update all speaking indicators - llinfos << "Merov debug : LLConversationViewSession::refresh, updateSpeakingIndicators" << llendl; LLSpeakingIndicatorManager::updateSpeakingIndicators(); // Do the regular upstream refresh @@ -455,7 +454,6 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height) void LLConversationViewParticipant::onCurrentVoiceSessionChanged(const LLUUID& session_id) { - llinfos << "Merov debug : onCurrentVoiceSessionChanged begin, uuid = " << mUUID << ", session_id = " << session_id << llendl; LLConversationItemParticipant* participant_model = dynamic_cast(getViewModelItem()); if (participant_model) @@ -477,12 +475,6 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsMuted(participant_model->isMuted()); - //LLConversationItemSession* parent_session = participant_model->getParentSession(); - //if (parent_session) - //{ - // bool is_active = (parent_session->getUUID() == session_id); - // mSpeakingIndicator->switchIndicator(is_active); - //} // Do the regular upstream refresh LLFolderViewItem::refresh(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index bd692aa850..78b930984f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -110,7 +110,6 @@ void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std: void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - llinfos << "Merov debug : sessionVoiceOrIMStarted, uuid = " << session_id << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -1310,7 +1309,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { - llinfos << "Merov debug : removeConversationListItem, uuid = " << uuid << llendl; // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 22131eac49..c2c6e739e9 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -725,7 +725,6 @@ void LLFloaterIMSessionTab::onClose(bool app_quitting) LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); if (im_box) { - llinfos << "Merov debug : LLFloaterIMSessionTab::onClose, mKey = " << mKey << llendl; im_box->removeConversationListItem(mKey); } } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 536f1fbd73..e4621a7fc3 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -48,8 +48,6 @@ LLColor4 LLOutputMonitorCtrl::sColorBound; //F32 LLOutputMonitorCtrl::sRectWidthRatio = 0.f; //F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f; -static LLUUID test_uuid("c684ce33-89fb-4544-8f7b-dae243c8b214"); - LLOutputMonitorCtrl::Params::Params() : draw_border("draw_border"), image_mute("image_mute"), @@ -280,44 +278,24 @@ BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { - bool test_on = (speaker_id == test_uuid); - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, this = " << this << ", session_id = " << session_id << llendl; - } if (speaker_id.isNull() && mSpeakerId.notNull()) { LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } - if (speaker_id.isNull() || speaker_id == mSpeakerId) + if (speaker_id.isNull() || (speaker_id == mSpeakerId)) { - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, nothing done because mSpeakerId == speaker_id" << llendl; - } return; } if (mSpeakerId.notNull()) { - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, unregisterSpeakingIndicator" << llendl; - } // Unregister previous registration to avoid crash. EXT-4782. - if (getTargetSessionID() == session_id) - { - LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); - } + LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; - if (test_on) - { - llinfos << "Merov debug : setSpeakerId, registerSpeakingIndicator" << llendl; - } LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); //mute management @@ -345,7 +323,6 @@ void LLOutputMonitorCtrl::onChange() // virtual void LLOutputMonitorCtrl::switchIndicator(bool switch_on) { - llinfos << "Merov debug : switchIndicator, mSpeakerId = " << mSpeakerId << ", switch_on = " << switch_on << llendl; // ensure indicator is visible in case it is not in visible chain // to be called when parent became visible next time to notify parent that visibility is changed. setVisible(TRUE); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index d9f9ed5966..76da7d1aee 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -155,7 +155,6 @@ void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_i BOOL is_in_same_voice = LLVoiceClient::getInstance()->isParticipant(speaker_id); speakers_uuids.insert(speaker_id); - llinfos << "Merov debug : registerSpeakingIndicator call switchSpeakerIndicators, switch = " << is_in_same_voice << llendl; switchSpeakerIndicators(speakers_uuids, is_in_same_voice); } @@ -196,7 +195,6 @@ SpeakingIndicatorManager::~SpeakingIndicatorManager() void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) { - llinfos << "Merov debug : sOnCurrentChannelChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); mSwitchedIndicatorsOn.clear(); } @@ -210,16 +208,12 @@ void SpeakingIndicatorManager::onParticipantsChanged() LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL; // switch all indicators off - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, FALSE" << llendl; switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE); - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end FALSE switch" << llendl; mSwitchedIndicatorsOn.clear(); LL_DEBUGS("SpeakingIndicator") << "Switching all ON, count: " << speakers_uuids.size() << LL_ENDL; // then switch current voice participants indicators on - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, TRUE" << llendl; switchSpeakerIndicators(speakers_uuids, TRUE); - llinfos << "Merov debug : onParticipantsChanged call switchSpeakerIndicators, end TRUE switch" << llendl; } void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on) @@ -230,7 +224,6 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea { session_id = voice_channel->getSessionID(); } - llinfos << "Merov debug : switchSpeakerIndicators, switch_on = " << switch_on << ", voice channel = " << session_id << llendl; speaker_ids_t::const_iterator it_uuid = speakers_uuids.begin(); for (; it_uuid != speakers_uuids.end(); ++it_uuid) @@ -255,7 +248,6 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea } was_switched_on = was_switched_on || switch_current_on; - llinfos << "Merov debug : indicator for " << *it_uuid << ", switch_current_on = " << switch_current_on << ", session = " << indicator->getTargetSessionID() << llendl; indicator->switchIndicator(switch_current_on); } diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h index 8ee368e258..e5afcd1cb7 100644 --- a/indra/newview/llspeakingindicatormanager.h +++ b/indra/newview/llspeakingindicatormanager.h @@ -37,7 +37,7 @@ public: virtual ~LLSpeakingIndicator(){} virtual void switchIndicator(bool switch_on) = 0; -//private: +private: friend class SpeakingIndicatorManager; // Accessors for target voice session UUID. // They are intended to be used only from SpeakingIndicatorManager to ensure target session is -- cgit v1.2.3 From 0cb67ec3762c1f1671fd01e331fe64a210098fd2 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Mon, 19 Nov 2012 07:42:39 +0200 Subject: CHUI-423 (User typing /me something in chat does not show correctly in italics on outgoing or incoming chat) --- indra/newview/llchathistory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 605e3ece51..a33bd88273 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -809,7 +809,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) { delimiter = LLStringUtil::null; - name_params.font.style = "ITALIC"; + body_message_params.font.style = "ITALIC"; } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; -- cgit v1.2.3 From f043bc32fd202de88d6823bb938128147ab4a04c Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Mon, 19 Nov 2012 09:08:02 +0200 Subject: CHUI-434 (Don't display phone icon and disable phone button when voice isn't enabled) --- indra/newview/llconversationview.cpp | 20 +++++++------------- indra/newview/llconversationview.h | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 4c52794e4c..b9d62e85c4 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -57,14 +57,11 @@ public: virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) { - if (conversation - && status != STATUS_JOINING - && status != STATUS_LEFT_CHANNEL - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking()) - { - conversation->showVoiceIndicator(); - } + conversation->showVoiceIndicator(conversation + && status != STATUS_JOINING + && status != STATUS_LEFT_CHANNEL + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking()); } private: @@ -288,12 +285,9 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const return (iter == getItemsEnd() ? NULL : participant); } -void LLConversationViewSession::showVoiceIndicator() +void LLConversationViewSession::showVoiceIndicator(bool visible) { - if (LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()) - { - mCallIconLayoutPanel->setVisible(true); - } + mCallIconLayoutPanel->setVisible(visible && LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()); } void LLConversationViewSession::refresh() diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 1baa8bb5ec..8156b746b2 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -78,7 +78,7 @@ public: void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); - void showVoiceIndicator(); + void showVoiceIndicator(bool visible); virtual void refresh(); -- cgit v1.2.3 From c48f8c2b28253786ada02d0a57d3a8e005fe9101 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 19 Nov 2012 16:47:40 +0200 Subject: CHUI-487 ADD. FIX (Revised comments) --- indra/newview/app_settings/settings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 14117ee47b..be793a344c 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13145,7 +13145,7 @@ FlashCount Comment - Number of flashes of IM Well and Notification Well icons after which flashing buttons stay lit up. Requires restart. + Number of flashes of item. Requires restart. Persist 1 Type @@ -13156,7 +13156,7 @@ FlashPeriod Comment - Period at which IM Well and Notification Well icons flash (seconds). Requires restart. + Period at which item flash (seconds). Requires restart. Persist 1 Type -- cgit v1.2.3 From 48a683af70fe359f4b4b6fdf6486208fc34dc2a9 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 19 Nov 2012 17:40:46 +0200 Subject: CHUI-488 ADD. fIX Clean up code --- indra/llui/llbutton.cpp | 7 ++++--- indra/newview/skins/default/xui/en/widgets/toolbar.xml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 8a34e221b1..8ac55b2eb4 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -174,9 +174,10 @@ LLButton::LLButton(const LLButton::Params& p) { // If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be // used instead it a "default" value from gSavedSettings.getS32("FlashCount")). - // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"); - S32 flash_count = p.button_flash_count || 0; - F32 flash_rate = p.button_flash_rate || 0.0; // + // Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod"). + // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). + S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; + F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0; mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml index 0aa478ace9..55ae158c00 100644 --- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml +++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml @@ -30,8 +30,8 @@ image_overlay_alignment="left" use_ellipses="true" auto_resize="true" - button_flash_count="99999" - button_flash_rate="1.0" + button_flash_count="3" + button_flash_rate="0.25" flash_color="EmphasisColor"/> Date: Mon, 19 Nov 2012 17:14:18 -0800 Subject: CHUI-495: Ensuring that a user in do-not-disturb mode can receive voice calls from current conversations. --- indra/newview/llimview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e2b678626b..b5dc4a7967 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2808,7 +2808,7 @@ void LLIMMgr::inviteToSession( { bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); - bool isRejectDoNotDisturb = gAgent.isDoNotDisturb(); + bool isRejectDoNotDisturb = (gAgent.isDoNotDisturb() && !hasSession(session_id)); if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) { if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) -- cgit v1.2.3 From 2c2e8b83d02efcdec9ccd3216e64073b4e8e1d57 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 19 Nov 2012 19:26:00 +0200 Subject: CHUI-362 ADD. FIX (When the "Bring back" panel is there, it is not possible to collapse the right side of the conversation dialog: the toolbar is completely missing and the "<<" chevrons are not there): This was because the button "<<" belonged session's floater and not the container. Therefore, when all the floaters in the stack becomes invisible, their buttons also become invisible. Solution: Added additional button "<<" in the stub_panel of the container. --- indra/newview/llfloaterimcontainer.cpp | 7 +++++++ indra/newview/llfloaterimcontainer.h | 2 ++ .../skins/default/xui/en/floater_im_container.xml | 17 +++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 90ddeef5bb..39cd16acfa 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -205,6 +205,8 @@ BOOL LLFloaterIMContainer::postBuild() mExpandCollapseBtn = getChild("expand_collapse_btn"); mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this)); + mStubCollapseBtn = getChild("stub_collapse_btn"); + mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -335,6 +337,11 @@ void LLFloaterIMContainer::onNewMessageReceived(const LLSD& data) } } +void LLFloaterIMContainer::onStubCollapseButtonClicked() +{ + collapseMessagesPane(true); +} + void LLFloaterIMContainer::onExpandCollapseButtonClicked() { if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 9112b54018..9cd6b9bc5d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -109,6 +109,7 @@ private: void onNewMessageReceived(const LLSD& data); void onExpandCollapseButtonClicked(); + void onStubCollapseButtonClicked(); void processParticipantsStyleUpdate(); void collapseConversationsPane(bool collapse); @@ -147,6 +148,7 @@ private: void openNearbyChat(); LLButton* mExpandCollapseBtn; + LLButton* mStubCollapseBtn; LLPanel* mStubPanel; LLTextBox* mStubTextBox; LLLayoutPanel* mMessagesPane; diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1388b9e474..4aa7c88312 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -134,6 +134,19 @@ left="0" height="430" width="412"> + - - Date: Wed, 28 Nov 2012 19:40:06 -0800 Subject: CHUI-552 : Fixed : Do not update the avatars sorting when updating the speaking indicator, let the conversation list do that. --- indra/newview/llfloaterimnearbychat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7b97295703..a20fce876c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -572,7 +572,7 @@ void LLFloaterIMNearbyChat::displaySpeakingIndicator() LLUUID id; id.setNull(); - mSpeakerMgr->update(TRUE); + mSpeakerMgr->update(FALSE); mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) -- cgit v1.2.3 From 47a2a2982de98c88fbc6cd17bdb897e5ec408b88 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 29 Nov 2012 11:06:10 -0500 Subject: fix for possible crash on exit in self_av_string() --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e103bb75e..9f6586a69b 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -52,7 +52,7 @@ std::string self_av_string() { - return gAgentAvatarp->avString(); + return gAgentAvatarp ? gAgentAvatarp->avString() : std::string("self_av_string error, gAgentAvatarp null"); } // RAII thingy to guarantee that a variable gets reset when the Setter -- cgit v1.2.3 From 611797543a917f1596be73e9e79974578748086e Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 29 Nov 2012 15:03:35 -0800 Subject: CHUI-489: Removed the 'Group Messages' checkbox. This was a design change in the spec. --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/skins/default/xui/en/panel_preferences_chat.xml | 11 +---------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 253ac3b836..ece711a128 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6867,17 +6867,6 @@ Value 1 - PlaySoundGroupChatMessages - - Comment - Plays a sound when have a group chat message. - Persist - 1 - Type - Boolean - Value - 0 - PlaySoundIncomingVoiceCall Comment diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 0c94b6b223..37bfbae991 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -341,22 +341,13 @@ top_pad="6" name="incoming_voice_call" width="150" /> - Date: Thu, 29 Nov 2012 20:33:17 -0800 Subject: CHUI-552 : Fixed : Filter out participant creation with the same id than the session id --- indra/newview/llparticipantlist.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 9f89b5f809..6c838f8a45 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -366,8 +366,11 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer event void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { - // Do not add if already in there or excluded for some reason - if (findParticipant(avatar_id)) return; + // Do not add if already in there, is the session id (hence not an avatar) or excluded for some reason + if (findParticipant(avatar_id) || (avatar_id == mUUID)) + { + return; + } bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id); @@ -391,7 +394,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // *TODO : Need to update the online/offline status of the participant // Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id)) - + // Add the participant model to the session's children list addParticipant(participant); @@ -413,12 +416,12 @@ void LLParticipantList::adjustParticipant(const LLUUID& speaker_id) bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer event, const LLSD& userdata) { /** - * We need to filter speaking objects. These objects shouldn't appear in the list + * We need to filter speaking objects. These objects shouldn't appear in the list. * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy */ const LLUUID& speaker_id = event->getValue().asUUID(); LLPointer speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); - if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT) + if (speaker.isNull() || (speaker->mType == LLSpeaker::SPEAKER_OBJECT)) { return false; } -- cgit v1.2.3 From 47a1a0468156153155f5e9b6c720b9b6cb62c263 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 30 Nov 2012 14:12:46 -0800 Subject: CHUI-570 : Fixed : Take the typing state when updating the title, also make refresh update less frequent (perf). --- indra/newview/llfloaterimsession.cpp | 26 +++++++++++--------------- indra/newview/llfloaterimsession.h | 1 - indra/newview/llfloaterimsessiontab.cpp | 2 +- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index e1dc5b91d0..0162b0ecd0 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -66,7 +66,6 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) : LLFloaterIMSessionTab(session_id), mLastMessageIndex(-1), mDialog(IM_NOTHING_SPECIAL), - mSavedTitle(), mTypingStart(), mShouldSendTypingState(false), mMeTyping(false), @@ -504,9 +503,13 @@ void LLFloaterIMSession::onVoiceChannelStateChanged( void LLFloaterIMSession::updateSessionName(const std::string& name) { - LLFloaterIMSessionTab::updateSessionName(name); - setTitle(name); - mTypingStart.setArg("[NAME]", name); + if (!name.empty()) + { + LLFloaterIMSessionTab::updateSessionName(name); + mTypingStart.setArg("[NAME]", name); + setTitle (mOtherTyping ? mTypingStart.getString() : name); + } + llinfos << "Merov debug : updateSessionName, title = " << name << ", typing title = " << mTypingStart.getString() << llendl; } //static @@ -1095,14 +1098,10 @@ BOOL LLFloaterIMSession::inviteToSession(const uuid_vec_t& ids) void LLFloaterIMSession::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if ( im_info && !mOtherTyping ) + if (im_info && !mOtherTyping) { mOtherTyping = true; - // Save and set new title - mSavedTitle = getTitle(); - setTitle (mTypingStart); - // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); if ( speaker_mgr ) @@ -1114,18 +1113,15 @@ void LLFloaterIMSession::addTypingIndicator(const LLIMInfo* im_info) void LLFloaterIMSession::removeTypingIndicator(const LLIMInfo* im_info) { - if ( mOtherTyping ) + if (mOtherTyping) { mOtherTyping = false; - // Revert the title to saved one - setTitle(mSavedTitle); - - if ( im_info ) + if (im_info) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if ( speaker_mgr ) + if (speaker_mgr) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index f4ec2d457d..72a320041f 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -174,7 +174,6 @@ private: LLUUID mOtherParticipantUUID; bool mPositioned; - std::string mSavedTitle; LLUIString mTypingStart; bool mMeTyping; bool mOtherTyping; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6e58a66bcd..d43381041b 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -43,7 +43,7 @@ #include "lltoolbarview.h" #include "llfloaterimnearbychat.h" -const F32 REFRESH_INTERVAL = 0.2f; +const F32 REFRESH_INTERVAL = 1.0f; LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) : LLTransientDockableFloater(NULL, true, session_id) -- cgit v1.2.3 From eab0ec402e7ea1eb151408b913c6f4e14c9c8cbe Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 30 Nov 2012 14:34:23 -0800 Subject: CHUI-570 : Delete a stray debug comment log. --- indra/newview/llfloaterimsession.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 0162b0ecd0..212b0df712 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -509,7 +509,6 @@ void LLFloaterIMSession::updateSessionName(const std::string& name) mTypingStart.setArg("[NAME]", name); setTitle (mOtherTyping ? mTypingStart.getString() : name); } - llinfos << "Merov debug : updateSessionName, title = " << name << ", typing title = " << mTypingStart.getString() << llendl; } //static -- cgit v1.2.3 From 9934cd2e29c8ea11e0859cd881d286fd56fae96e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 30 Nov 2012 17:41:07 -0500 Subject: SH-3562 WIP - detect possible hangs in item copying --- indra/newview/llappearancemgr.cpp | 137 +++++++++++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 16 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 9f6586a69b..09b0c132d2 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -154,6 +154,123 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string } } +// Shim between inventory callback and boost function +typedef boost::function inventory_func_type; + +class LLBoostFuncInventoryCallback: public LLInventoryCallback +{ +public: + + LLBoostFuncInventoryCallback(const inventory_func_type& func): + mFunc(func) + { + } + + void fire(const LLUUID& item_id) + { + mFunc(item_id); + } + +private: + inventory_func_type mFunc; +}; + +LLPointer make_inventory_func_callback(const inventory_func_type& func) +{ + return new LLBoostFuncInventoryCallback(func); +} + +void report_fire(const LLUUID& item_id) +{ + llinfos << item_id << llendl; +} + +class LLInventoryCopyMgr: public LLEventTimer +{ +public: + LLInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, const LLUUID& dst_cat_id, + bool append, const std::string& phase): + mDstCatID(dst_cat_id), + mAppend(append), + mTrackingPhase(phase), + LLEventTimer(5.0) + { + for (LLInventoryModel::item_array_t::const_iterator it = src_items.begin(); + it != src_items.end(); + ++it) + { + LLViewerInventoryItem* item = *it; + mSrcTimes[item->getUUID()] = LLTimer(); + requestCopy(item->getUUID()); + } + if (!mTrackingPhase.empty()) + { + selfStartPhase(mTrackingPhase); + } + } + + void requestCopy(const LLUUID& item_id) + { + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (!item) + { + llwarns << "requestCopy item not found " << item_id << llendl; + return; + } + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + mDstCatID, + std::string(), + make_inventory_func_callback(boost::bind(&LLInventoryCopyMgr::onCopy,this,item->getUUID(),_1)) + ); + } + + void onCopy(const LLUUID& src_id, const LLUUID& dst_id) + { + LL_DEBUGS("Avatar") << "copied, src_id " << src_id << " to dst_id " << dst_id << " after " << mSrcTimes[src_id].getElapsedTimeF32() << " seconds" << llendl; + mSrcTimes.erase(src_id); + if (mSrcTimes.empty()) + { + onCompletion(); + } + } + + void onCompletion() + { + if (!mTrackingPhase.empty()) + { + selfStopPhase(mTrackingPhase); + } + if( LLInventoryCallbackManager::is_instantiated() ) + { + LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mDstCatID), mAppend); + } + } + + // virtual + // Will be deleted after returning true - only safe to do this if all callbacks have fired. + BOOL tick() + { + bool all_done = mSrcTimes.empty(); + + if (!all_done) + { + llwarns << "possible hang in copy, waiting on " << mSrcTimes.size() << " items" << llendl; + // TODO possibly add retry logic here. + + } + return all_done; + } + +private: + std::string mTrackingPhase; + std::map mSrcTimes; + LLUUID mDstCatID; + bool mAppend; +}; + class LLWearInventoryCategoryCallback : public LLInventoryCallback { public: @@ -1979,22 +2096,10 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap pid, LLFolderType::FT_NONE, name); - LLPointer cb = new LLWearInventoryCategoryCallback(new_cat_id, append); - it = items->begin(); - for(; it < end; ++it) - { - item = *it; - if(item) - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - new_cat_id, - std::string(), - cb); - } - } + + // Create a CopyMgr that will copy items, manage its own destruction + new LLInventoryCopyMgr(*items, new_cat_id, append, std::string("wear_inventory_category_callback")); + // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); } -- cgit v1.2.3 From f0a11b1590a8d52281683275f836ac347ccc510f Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Fri, 30 Nov 2012 16:59:15 -0600 Subject: SH-3594: Fix for crash when outfits are changed on a non server based baking region. --- indra/llvfs/llvfile.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index ca749c5eaf..03d2cc25e3 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -32,6 +32,7 @@ #include "llthread.h" #include "llstat.h" #include "llvfs.h" +#include "llmemory.h" const S32 LLVFile::READ = 0x00000001; const S32 LLVFile::WRITE = 0x00000002; @@ -134,13 +135,13 @@ U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S data = NULL; } else - { - data = new U8[file_size]; + { + data = (U8*) ll_aligned_malloc_16(file_size); file.read(data, file_size); /* Flawfinder: ignore */ if (file.getLastBytesRead() != (S32)file_size) { - delete[] data; + ll_aligned_free(data); data = NULL; file_size = 0; } -- cgit v1.2.3 From e53577c32db1a8d5e7e15cb33357c68da87acc44 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 30 Nov 2012 17:12:52 -0800 Subject: CHUI-404, CHUI-406 : Fixed : update ad-hoc conversation when participant logs off, update title of ad-hoc and P2P to be consistent with torn off and input field --- indra/newview/llconversationmodel.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0837a49095..ba92022673 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" @@ -161,8 +162,8 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) { - // We modify the session name only in the case of an ad-hoc session, exit otherwise (nothing to do) - if (getType() != CONV_SESSION_AD_HOC) + // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) + if ((getType() != CONV_SESSION_AD_HOC) && (getType() != CONV_SESSION_1_ON_1)) { return; } @@ -171,26 +172,26 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } - // Build a string containing the participants names and check if ready for display (we don't want "(waiting)" in there) - bool all_names_resolved = true; + // Build a string containing the participants names (minus own agent) and check if ready for display (we don't want "(waiting)" in there) + // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by + // onAvatarNameCache() which is itself attached to the same event. uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string child_list_t::iterator iter = mChildren.begin(); while (iter != mChildren.end()) { LLConversationItemParticipant* current_participant = dynamic_cast(*iter); - temp_uuids.push_back(current_participant->getUUID()); - LLAvatarName av_name; - if (!LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) - { - // If the name is not in the cache yet, bail out - // Note: we don't bind ourselves to the LLAvatarNameCache event as we are called by - // onAvatarNameCache() which is itself attached to the same event. - all_names_resolved = false; - break; + // Add the avatar uuid to the list (except if it's the own agent uuid) + if (current_participant->getUUID() != gAgentID) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + { + temp_uuids.push_back(current_participant->getUUID()); + } } iter++; } - if (all_names_resolved) + if (temp_uuids.size() != 0) { std::string new_session_name; LLAvatarActions::buildResidentsString(temp_uuids, new_session_name); @@ -203,6 +204,7 @@ void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* { removeChild(participant); mNeedsRefresh = true; + updateParticipantName(participant); postEvent("remove_participant", this, participant); } -- cgit v1.2.3 From d48357f54765f84a35b73bbf28e88b978bcb5013 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 30 Nov 2012 19:07:58 -0800 Subject: CHUI-406 : Fixed again : Update of the P2P session name when not initiating a session was wrong. Add getting the participant name from the session. --- indra/newview/llconversationmodel.cpp | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index ba92022673..728b1a3f4c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -31,6 +31,7 @@ #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" +#include "llfloaterimsession.h" #include "llsdutil.h" #include "llconversationmodel.h" #include "llimview.h" //For LLIMModel @@ -162,8 +163,9 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) { + EConversationType conversation_type = getType(); // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) - if ((getType() != CONV_SESSION_AD_HOC) && (getType() != CONV_SESSION_1_ON_1)) + if ((conversation_type != CONV_SESSION_AD_HOC) && (conversation_type != CONV_SESSION_1_ON_1)) { return; } @@ -172,24 +174,35 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } - // Build a string containing the participants names (minus own agent) and check if ready for display (we don't want "(waiting)" in there) - // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by - // onAvatarNameCache() which is itself attached to the same event. uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string - child_list_t::iterator iter = mChildren.begin(); - while (iter != mChildren.end()) + if (conversation_type == CONV_SESSION_AD_HOC) { - LLConversationItemParticipant* current_participant = dynamic_cast(*iter); - // Add the avatar uuid to the list (except if it's the own agent uuid) - if (current_participant->getUUID() != gAgentID) + // Build a string containing the participants UUIDs (minus own agent) and check if ready for display (we don't want "(waiting)" in there) + // Note: we don't bind ourselves to the LLAvatarNameCache event as updateParticipantName() is called by + // onAvatarNameCache() which is itself attached to the same event. + child_list_t::iterator iter = mChildren.begin(); + while (iter != mChildren.end()) { - LLAvatarName av_name; - if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + LLConversationItemParticipant* current_participant = dynamic_cast(*iter); + // Add the avatar uuid to the list (except if it's the own agent uuid) + if (current_participant->getUUID() != gAgentID) { - temp_uuids.push_back(current_participant->getUUID()); + LLAvatarName av_name; + if (LLAvatarNameCache::get(current_participant->getUUID(), &av_name)) + { + temp_uuids.push_back(current_participant->getUUID()); + } } + iter++; } - iter++; + } + else if (conversation_type == CONV_SESSION_1_ON_1) + { + // In the case of a P2P conversersation, we need to grab the name of the other participant in the session instance itself + // as we do not create participants for such a session. + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(mUUID); + LLUUID participantID = conversationFloater->getOtherParticipantUUID(); + temp_uuids.push_back(participantID); } if (temp_uuids.size() != 0) { -- cgit v1.2.3 From 168c1d5a85e8f4f4975ee4501e3dbb8f10d85334 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Mon, 3 Dec 2012 15:37:11 +0200 Subject: CHUI-432 (User that is muted in group call does not show as muted to other users in conversation list) --- indra/newview/llconversationview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..7988cd1a03 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -448,6 +448,7 @@ void LLConversationViewParticipant::draw() drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); + refresh(); LLView::draw(); } -- cgit v1.2.3 From f888a3fd00ca32275ab2da6437cb011b3ab78f89 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Mon, 3 Dec 2012 16:21:48 +0200 Subject: CHUI-556 (Tooltip on call button incorrect when call is active) --- indra/newview/llfloaterimsessiontab.cpp | 7 ++++++- indra/newview/skins/default/xui/en/floater_im_session.xml | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d43381041b..08c2b951df 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -691,8 +691,13 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) { - getChild("voice_call_btn")->setImageOverlay( + LLButton* voiceButton = getChild("voice_call_btn"); + voiceButton->setImageOverlay( callIsActive? getString("call_btn_stop") : getString("call_btn_start")); + + voiceButton->setToolTip( + callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); + enableDisableCallBtn(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 1d74f1bc25..faf54774f6 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -43,6 +43,12 @@ + + Date: Mon, 3 Dec 2012 19:20:11 +0200 Subject: CHUI-532 FIXED (Viewer crash when user in conversation is removed from participant list because they logged out or teleported away) delayed destroy of the timer --- indra/llui/llbutton.cpp | 2 +- indra/llui/llflashtimer.cpp | 9 ++++++++- indra/llui/llflashtimer.h | 6 ++++++ indra/newview/llconversationview.cpp | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 97547208ec..f82cdc64a9 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -286,7 +286,7 @@ LLButton::~LLButton() if (mFlashingTimer) { - delete mFlashingTimer; + mFlashingTimer->unset(); } } diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index de7a4ab265..e49628acd5 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -35,6 +35,7 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) , mCurrentTickCount(0) , mIsFlashingInProgress(false) , mIsCurrentlyHighlighted(false) + , mUnset(false) { mEventTimer.stop(); @@ -48,6 +49,12 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) } } +void LLFlashTimer::unset() +{ + mUnset = true; + mCallback = NULL; +} + BOOL LLFlashTimer::tick() { mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted; @@ -62,7 +69,7 @@ BOOL LLFlashTimer::tick() stopFlashing(); } - return FALSE; + return mUnset; } void LLFlashTimer::startFlashing() diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index 5c8860b097..c60f99a8ea 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -52,6 +52,11 @@ public: bool isFlashingInProgress(); bool isCurrentlyHighlighted(); + /* + * Use this instead of deleting this object. + * The next call to tick() will return true and that will destroy this object. + */ + void unset(); private: callback_t mCallback; @@ -62,6 +67,7 @@ private: S32 mCurrentTickCount; bool mIsCurrentlyHighlighted; bool mIsFlashingInProgress; + bool mUnset; }; #endif /* LL_FLASHTIMER_H */ diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..40900dce54 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -95,7 +95,7 @@ LLConversationViewSession::~LLConversationViewSession() LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); } - delete mFlashTimer; + mFlashTimer->unset(); } bool LLConversationViewSession::isHighlightAllowed() -- cgit v1.2.3 From 5c245e941ace3f52dfa3539c473e2c02f207d8a3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 3 Dec 2012 14:34:00 -0500 Subject: SH-3562 WIP --- indra/newview/llappearancemgr.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 09b0c132d2..321bf7edcb 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -239,14 +239,12 @@ public: void onCompletion() { + llinfos << "done" << llendl; if (!mTrackingPhase.empty()) { selfStopPhase(mTrackingPhase); } - if( LLInventoryCallbackManager::is_instantiated() ) - { - LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mDstCatID), mAppend); - } + LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mDstCatID), mAppend); } // virtual @@ -2116,7 +2114,12 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego // Avoid unintentionally overwriting old wearables. We have to do // this up front to avoid having to deal with the case of multiple // wearables being dirty. - if(!category) return; + if (!category) return; + + if ( !LLInventoryCallbackManager::is_instantiated() ) + { + return; + } LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName() << "'" << LL_ENDL; -- cgit v1.2.3 From 2ee6bcab371a08791bccad3a4fa072c1d60cd6c9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Mon, 3 Dec 2012 16:19:46 -0800 Subject: CHUI-571: Now when the 'Chat Preference' is set to 'Open Conversations window' the conversation line item with flash. The only time it does not flash is when the the conversation line item is already focused. Also fixed various focusing bugs when navigating between conversations and participants. --- indra/llui/llfolderviewitem.cpp | 7 ++++++- indra/newview/llconversationview.cpp | 18 ++++++++++++++---- indra/newview/llfloaterimcontainer.cpp | 26 +++++++++++++++++--------- indra/newview/llfloaterimnearbychathandler.cpp | 5 ----- indra/newview/llfloaterimsessiontab.cpp | 2 +- indra/newview/llimview.cpp | 6 ++++++ 6 files changed, 44 insertions(+), 20 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 261f53d6b6..9b54a7a467 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -501,7 +501,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) // No handler needed for focus lost since this class has no // state that depends on it. gFocusMgr.setMouseCapture( this ); - + if (!mIsSelected) { if(mask & MASK_CONTROL) @@ -518,6 +518,11 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } make_ui_sound("UISndClick"); } + //Just re-select the item since it is clicked without ctrl or shift + else if(!(mask & (MASK_CONTROL | MASK_SHIFT))) + { + getRoot()->setSelection(this, FALSE); + } else { mSelectPending = TRUE; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 1b1d61e6d6..a696fbdb47 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -218,9 +218,15 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) { LLConversationItem* item = dynamic_cast(getViewModelItem()); LLUUID session_id = item? item->getUUID() : LLUUID(); + //Will try to select a child node and then itself (if a child was not selected) BOOL result = LLFolderViewFolder::handleMouseDown(x, y, mask); - (LLFloaterReg::getTypedInstance("im_container"))-> - selectConversationPair(session_id, false); + + //This node (conversation) was selected and a child (participant) was not + if(result && getRoot()->getCurSelectedItem() == this) + { + (LLFloaterReg::getTypedInstance("im_container"))-> + selectConversationPair(session_id, false); + } return result; } @@ -548,8 +554,12 @@ BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) } LLUUID session_id = item? item->getUUID() : LLUUID(); BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); - (LLFloaterReg::getTypedInstance("im_container"))-> - selectConversationPair(session_id, false); + + if(result) + { + (LLFloaterReg::getTypedInstance("im_container"))-> + selectConversationPair(session_id, false); + } return result; } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a04b8d79d6..3a80491dae 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1165,21 +1165,16 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) selectConversation(session_id); } -// Will select only the conversation item void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { - LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); - if (widget) - { - (widget->getRoot())->setSelection(widget, FALSE, FALSE); + selectConversationPair(session_id, true); } -} - // Synchronous select the conversation item and the conversation floater BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool select_widget) { BOOL handled = TRUE; + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); /* widget processing */ if (select_widget) @@ -1198,7 +1193,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Store the active session setSelectedSession(session_id); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + if (session_floater->getHost()) { @@ -1207,13 +1202,13 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } + } // Set the focus on the selected floater if (!session_floater->hasFocus()) { session_floater->setFocus(TRUE); } - } return handled; } @@ -1627,13 +1622,26 @@ void LLFloaterIMContainer::reSelectConversation() void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { + //Finds the conversation line item to flash using the session_id LLConversationViewSession * widget = dynamic_cast(get_ptr_in_map(mConversationsWidgets,session_id)); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + if (widget) { + //Start flash if (is_flashes) { + //Only flash when conversation is not active + if(session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus + + { widget->getFlashTimer()->startFlashing(); } + } + //Stop flash else { widget->getFlashTimer()->stopFlashing(); diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index d9c461e836..903c903381 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -619,11 +619,6 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, chat["message"] = toast_msg; channel->addChat(chat); } - //Will show Conversations floater when chat preference is set - else if(gSavedSettings.getString("NotificationNearbyChatOptions") == "openconversations") - { - LLFloaterReg::showInstance("im_container"); - } } } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 6e58a66bcd..efc7be6dd6 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -306,7 +306,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance("im_container"); if (container) { - container->selectConversationPair(mSessionID, true); + container->selectConversationPair(mSessionID, ! getHost()); container->showStub(! getHost()); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e5dda7e8d8..b6fd3ec9c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -191,6 +191,12 @@ void on_new_message(const LLSD& msg) } else if("openconversations" == action) { + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); + if (im_box) + { + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + } + LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From f1155c4fa5e9a4eaa5b4d452fc46a2246fb305bd Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Tue, 4 Dec 2012 04:14:51 +0200 Subject: CHUI-573 FIXED Notification chiclet shown when object chiclets are shown --- indra/newview/llchiclet.cpp | 882 +-------------------- indra/newview/llchiclet.h | 555 +------------ indra/newview/llchicletbar.cpp | 104 +-- indra/newview/llchicletbar.h | 16 - indra/newview/llfloaterimsession.cpp | 10 +- indra/newview/llscriptfloater.cpp | 121 ++- indra/newview/llsyswellwindow.cpp | 289 +------ indra/newview/llsyswellwindow.h | 66 +- .../default/textures/bottomtray/Notices_Unread.png | Bin 3693 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl1_Dark.png | Bin 602 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl2_Dark.png | Bin 669 -> 0 bytes .../textures/bottomtray/VoicePTT_Lvl3_Dark.png | Bin 639 -> 0 bytes .../textures/bottomtray/VoicePTT_Off_Dark.png | Bin 547 -> 0 bytes .../textures/bottomtray/VoicePTT_On_Dark.png | Bin 526 -> 0 bytes indra/newview/skins/default/textures/textures.xml | 8 - .../skins/default/xui/da/menu_im_well_button.xml | 4 - .../xui/da/menu_notification_well_button.xml | 4 - .../skins/default/xui/de/menu_im_well_button.xml | 4 - .../xui/de/menu_notification_well_button.xml | 4 - .../xui/en/menu_notification_well_button.xml | 16 - .../skins/default/xui/en/panel_activeim_row.xml | 97 --- .../skins/default/xui/en/panel_chiclet_bar.xml | 44 - .../default/xui/en/widgets/chiclet_im_adhoc.xml | 55 -- .../default/xui/en/widgets/chiclet_im_group.xml | 56 -- .../default/xui/en/widgets/chiclet_im_p2p.xml | 56 -- .../skins/default/xui/es/menu_im_well_button.xml | 4 - .../xui/es/menu_notification_well_button.xml | 4 - .../skins/default/xui/fr/menu_im_well_button.xml | 4 - .../xui/fr/menu_notification_well_button.xml | 4 - .../skins/default/xui/it/menu_im_well_button.xml | 4 - .../xui/it/menu_notification_well_button.xml | 4 - .../skins/default/xui/ja/menu_im_well_button.xml | 4 - .../xui/ja/menu_notification_well_button.xml | 4 - .../skins/default/xui/pl/menu_im_well_button.xml | 4 - .../xui/pl/menu_notification_well_button.xml | 4 - .../skins/default/xui/pt/menu_im_well_button.xml | 4 - .../xui/pt/menu_notification_well_button.xml | 4 - .../skins/default/xui/ru/menu_im_well_button.xml | 4 - .../xui/ru/menu_notification_well_button.xml | 4 - .../skins/default/xui/tr/menu_im_well_button.xml | 4 - .../xui/tr/menu_notification_well_button.xml | 4 - .../skins/default/xui/zh/menu_im_well_button.xml | 4 - .../xui/zh/menu_notification_well_button.xml | 4 - 43 files changed, 100 insertions(+), 2363 deletions(-) delete mode 100644 indra/newview/skins/default/textures/bottomtray/Notices_Unread.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png delete mode 100644 indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png delete mode 100644 indra/newview/skins/default/xui/da/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/da/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/de/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/de/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/en/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/en/panel_activeim_row.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml delete mode 100644 indra/newview/skins/default/xui/es/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/es/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/fr/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/fr/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/it/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/it/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ja/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ja/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pl/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pl/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pt/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/pt/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ru/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/ru/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/tr/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/tr/menu_notification_well_button.xml delete mode 100644 indra/newview/skins/default/xui/zh/menu_im_well_button.xml delete mode 100644 indra/newview/skins/default/xui/zh/menu_notification_well_button.xml diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a665aeb6bd..1acbdd32b7 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -27,35 +27,15 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llchiclet.h" -#include "llagent.h" -#include "llavataractions.h" -#include "llchicletbar.h" -#include "lleventtimer.h" -#include "llgroupactions.h" -#include "lliconctrl.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" -#include "llimview.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" -#include "llmenugl.h" #include "llnotifications.h" -#include "llnotificationsutil.h" -#include "lloutputmonitorctrl.h" #include "llscriptfloater.h" -#include "llspeakers.h" -#include "lltextbox.h" -#include "llvoiceclient.h" -#include "llgroupmgr.h" -#include "llnotificationmanager.h" -#include "lltransientfloatermgr.h" -#include "llsyswellwindow.h" +#include "llsingleton.h" static LLDefaultChildRegistry::Register t1("chiclet_panel"); -static LLDefaultChildRegistry::Register t2("chiclet_notification"); -static LLDefaultChildRegistry::Register t3("chiclet_im_p2p"); -static LLDefaultChildRegistry::Register t4("chiclet_im_group"); -static LLDefaultChildRegistry::Register t5("chiclet_im_adhoc"); static LLDefaultChildRegistry::Register t6("chiclet_script"); static LLDefaultChildRegistry::Register t7("chiclet_offer"); @@ -66,192 +46,6 @@ boost::signals2::signal(button_params); - addChild(mButton); - - - mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); -} - -LLSysWellChiclet::~LLSysWellChiclet() -{ - delete mFlashToLitTimer; -} - -void LLSysWellChiclet::setCounter(S32 counter) -{ - // do nothing if the same counter is coming. EXT-3678. - if (counter == mCounter) return; - - // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) - std::string s_count; - if(counter != 0) - { - static std::string more_messages_exist("+"); - std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); - s_count = llformat("%d%s" - , llmin(counter, mMaxDisplayedCount) - , more_messages.c_str() - ); - } - - mButton->setLabel(s_count); - - mCounter = counter; -} - -boost::signals2::connection LLSysWellChiclet::setClickCallback( - const commit_callback_t& cb) -{ - return mButton->setClickedCallback(cb); -} - -void LLSysWellChiclet::setToggleState(BOOL toggled) { - mButton->setToggleState(toggled); -} - -void LLSysWellChiclet::changeLitState(bool blink) -{ - setNewMessagesState(!mIsNewMessagesState); -} - -void LLSysWellChiclet::setNewMessagesState(bool new_messages) -{ - /* - Emulate 4 states of button by background images, see detains in EXT-3147 - xml attribute Description - image_unselected "Unlit" - there are no new messages - image_selected "Unlit" + "Selected" - there are no new messages and the Well is open - image_pressed "Lit" - there are new messages - image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open - */ - mButton->setForcePressedState(new_messages); - - mIsNewMessagesState = new_messages; -} - -void LLSysWellChiclet::updateWidget(bool is_window_empty) -{ - mButton->setEnabled(!is_window_empty); - - if (LLChicletBar::instanceExists()) - { - LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty); - } -} -// virtual -BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - if(!mContextMenu) - { - createMenu(); - } - if (mContextMenu) - { - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); - } - return TRUE; -} - -/************************************************************************/ -/* LLNotificationChiclet implementation */ -/************************************************************************/ -LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p), - mUreadSystemNotifications(0) -{ - mNotificationChannel.reset(new ChicletNotificationChannel(this)); - // ensure that notification well window exists, to synchronously - // handle toast add/delete events. - LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); -} - -void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - if("close all" == action) - { - LLNotificationWellWindow::getInstance()->closeAll(); - } -} - -bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) -{ - std::string item = user_data.asString(); - if (item == "can close all") - { - return mUreadSystemNotifications != 0; - } - return true; -} - -void LLNotificationChiclet::createMenu() -{ - if(mContextMenu) - { - llwarns << "Menu already exists" << llendl; - return; - } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("NotificationWellChicletMenu.Action", - boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2)); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("NotificationWellChicletMenu.EnableItem", - boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); - - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile - ("menu_notification_well_button.xml", - LLMenuGL::sMenuContainer, - LLViewerMenuHolderGL::child_registry_t::instance()); -} - -/*virtual*/ -void LLNotificationChiclet::setCounter(S32 counter) -{ - LLSysWellChiclet::setCounter(counter); - updateWidget(getCounter() == 0); - -} - -bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) -{ - if( !(notification->canLogToIM() && notification->hasFormElements()) - && (!notification->getPayload().has("give_inventory_notification") - || notification->getPayload()["give_inventory_notification"])) - { - return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - LLChiclet::Params::Params() : show_counter("show_counter", true) , enable_counter("enable_counter", false) @@ -303,7 +97,9 @@ LLSD LLChiclet::getValue() const void LLChiclet::setValue(const LLSD& value) { if(value.isUUID()) + { setSessionId(value.asUUID()); + } } ////////////////////////////////////////////////////////////////////////// @@ -315,12 +111,9 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) , mShowSpeaker(false) , mDefaultWidth(p.rect().getWidth()) , mNewMessagesIcon(NULL) -, mSpeakerCtrl(NULL) -, mCounterCtrl(NULL) , mChicletButton(NULL) , mPopupMenu(NULL) { - enableCounterControl(p.enable_counter); } /* virtual*/ @@ -331,107 +124,14 @@ BOOL LLIMChiclet::postBuild() mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); return TRUE; } -void LLIMChiclet::setShowSpeaker(bool show) -{ - bool needs_resize = getShowSpeaker() != show; - if(needs_resize) - { - mShowSpeaker = show; - } - - toggleSpeakerControl(); -} - -void LLIMChiclet::enableCounterControl(bool enable) -{ - mCounterEnabled = enable; - if(!enable) - { - LLChiclet::setShowCounter(false); - } -} - -void LLIMChiclet::setShowCounter(bool show) -{ - if(!mCounterEnabled) - { - return; - } - - bool needs_resize = getShowCounter() != show; - if(needs_resize) - { - LLChiclet::setShowCounter(show); - toggleCounterControl(); - } -} - -void LLIMChiclet::initSpeakerControl() -{ - // virtual -} void LLIMChiclet::setRequiredWidth() { - bool show_speaker = getShowSpeaker(); - bool show_counter = getShowCounter(); S32 required_width = mDefaultWidth; - - if (show_counter) - { - required_width += mCounterCtrl->getRect().getWidth(); - } - if (show_speaker) - { - required_width += mSpeakerCtrl->getRect().getWidth(); - } - reshape(required_width, getRect().getHeight()); - onChicletSizeChanged(); } -void LLIMChiclet::toggleSpeakerControl() -{ - if(getShowSpeaker()) - { - // move speaker to the right of chiclet icon - LLRect speaker_rc = mSpeakerCtrl->getRect(); - speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight()); - mSpeakerCtrl->setRect(speaker_rc); - - if(getShowCounter()) - { - // move speaker to the right of counter - mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0); - } - - initSpeakerControl(); - } - - setRequiredWidth(); - mSpeakerCtrl->setSpeakerId(LLUUID::null); - mSpeakerCtrl->setVisible(getShowSpeaker()); -} - -void LLIMChiclet::setCounter(S32 counter) -{ - if (mCounterCtrl->getCounter() == counter) - { - return; - } - - mCounterCtrl->setCounter(counter); - setShowCounter(counter); - setShowNewMessagesIcon(counter); -} - -void LLIMChiclet::toggleCounterControl() -{ - setRequiredWidth(); - mCounterCtrl->setVisible(getShowCounter()); -} - void LLIMChiclet::setShowNewMessagesIcon(bool show) { if(mNewMessagesIcon) @@ -449,7 +149,6 @@ bool LLIMChiclet::getShowNewMessagesIcon() void LLIMChiclet::onMouseDown() { LLFloaterIMSession::toggle(getSessionId()); - setCounter(0); } void LLIMChiclet::setToggleState(bool toggle) @@ -457,52 +156,6 @@ void LLIMChiclet::setToggleState(bool toggle) mChicletButton->setToggleState(toggle); } -void LLIMChiclet::draw() -{ - LLUICtrl::draw(); -} - -// static -LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) -{ - EType type = TYPE_UNKNOWN; - - if(session_id.isNull()) - return type; - - EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id); - if (IM_COUNT == im_type) - { - llassert_always(0 && "IM session not found"); // should never happen - return type; - } - - switch(im_type) - { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - type = TYPE_IM; - break; - case IM_SESSION_GROUP_START: - case IM_SESSION_INVITE: - if (gAgent.isInGroup(session_id)) - { - type = TYPE_GROUP; - } - else - { - type = TYPE_AD_HOC; - } - break; - case IM_SESSION_CONFERENCE_START: - type = TYPE_AD_HOC; - default: - break; - } - - return type; -} - BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { if(!mPopupMenu) @@ -534,382 +187,6 @@ bool LLIMChiclet::canCreateMenu() return true; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLIMP2PChiclet::Params::Params() -: avatar_icon("avatar_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -{ -} - -LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) -: LLIMChiclet(p) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; - mChicletIconCtrl = LLUICtrlFactory::create(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -void LLIMP2PChiclet::initSpeakerControl() -{ - mSpeakerCtrl->setSpeakerId(getOtherParticipantId()); -} - -void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id) -{ - LLIMChiclet::setOtherParticipantId(other_participant_id); - mChicletIconCtrl->setValue(getOtherParticipantId()); -} - -void LLIMP2PChiclet::updateMenuItems() -{ - if(!mPopupMenu) - return; - if(getSessionId().isNull()) - return; - - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); - bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild("Send IM")->setEnabled(!open_window_exists); - - bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); - mPopupMenu->getChild("Add Friend")->setEnabled(!is_friend); -} - -void LLIMP2PChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile - ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID other_participant_id = getOtherParticipantId(); - - if("profile" == level) - { - LLAvatarActions::showProfile(other_participant_id); - } - else if("im" == level) - { - LLAvatarActions::startIM(other_participant_id); - } - else if("add" == level) - { - LLAvatarActions::requestFriendshipDialog(other_participant_id); - } - else if("end" == level) - { - LLAvatarActions::endIM(other_participant_id); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLAdHocChiclet::Params::Params() -: avatar_icon("avatar_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -, avatar_icon_color("avatar_icon_color", LLColor4::green) -{ -} - -LLAdHocChiclet::LLAdHocChiclet(const Params& p) -: LLIMChiclet(p) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; - mChicletIconCtrl = LLUICtrlFactory::create(avatar_params); - //Make the avatar modified - mChicletIconCtrl->setColor(p.avatar_icon_color); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -void LLAdHocChiclet::setSessionId(const LLUUID& session_id) -{ - LLChiclet::setSessionId(session_id); - LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); - mChicletIconCtrl->setValue(im_session->mOtherParticipantID); -} - -void LLAdHocChiclet::draw() -{ - switchToCurrentSpeaker(); - LLIMChiclet::draw(); -} - -void LLAdHocChiclet::initSpeakerControl() -{ - switchToCurrentSpeaker(); -} - -void LLAdHocChiclet::switchToCurrentSpeaker() -{ - LLUUID speaker_id; - LLSpeakerMgr::speaker_list_t speaker_list; - - LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - speaker_id = s->mID; - break; - } - } - - mSpeakerCtrl->setSpeakerId(speaker_id); -} - -void LLAdHocChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile - ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID group_id = getSessionId(); - - if("end" == level) - { - LLGroupActions::endIM(group_id); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLIMGroupChiclet::Params::Params() -: group_icon("group_icon") -, chiclet_button("chiclet_button") -, unread_notifications("unread_notifications") -, speaker("speaker") -, new_message_icon("new_message_icon") -, show_speaker("show_speaker") -{ -} - -LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) -: LLIMChiclet(p) -, LLGroupMgrObserver(LLUUID::null) -, mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletGroupIconCtrl::Params avatar_params = p.group_icon; - mChicletIconCtrl = LLUICtrlFactory::create(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create(speaker_params); - addChild(mSpeakerCtrl); - - sendChildToFront(mNewMessagesIcon); - setShowSpeaker(p.show_speaker); -} - -LLIMGroupChiclet::~LLIMGroupChiclet() -{ - LLGroupMgr::getInstance()->removeObserver(this); -} - -void LLIMGroupChiclet::draw() -{ - if(getShowSpeaker()) - { - switchToCurrentSpeaker(); - } - LLIMChiclet::draw(); -} - -void LLIMGroupChiclet::initSpeakerControl() -{ - switchToCurrentSpeaker(); -} - -void LLIMGroupChiclet::switchToCurrentSpeaker() -{ - LLUUID speaker_id; - LLSpeakerMgr::speaker_list_t speaker_list; - - LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); - for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) - { - LLPointer s = *i; - if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) - { - speaker_id = s->mID; - break; - } - } - - mSpeakerCtrl->setSpeakerId(speaker_id); -} - -void LLIMGroupChiclet::setSessionId(const LLUUID& session_id) -{ - LLChiclet::setSessionId(session_id); - - LLGroupMgr* grp_mgr = LLGroupMgr::getInstance(); - LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id); - if (group_data && group_data->mInsigniaID.notNull()) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - else - { - if(getSessionId() != mID) - { - grp_mgr->removeObserver(this); - mID = getSessionId(); - grp_mgr->addObserver(this); - } - grp_mgr->sendGroupPropertiesRequest(session_id); - } -} - -void LLIMGroupChiclet::changed(LLGroupChange gc) -{ - if (GC_PROPERTIES == gc) - { - LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId()); - if (group_data) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - } -} - -void LLIMGroupChiclet::updateMenuItems() -{ - if(!mPopupMenu) - return; - if(getSessionId().isNull()) - return; - - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(getSessionId()); - bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild("Chat")->setEnabled(!open_window_exists); -} - -void LLIMGroupChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile - ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string level = user_data.asString(); - LLUUID group_id = getSessionId(); - - if("group chat" == level) - { - LLGroupActions::startIM(group_id); - } - else if("info" == level) - { - LLGroupActions::show(group_id); - } - else if("end" == level) - { - LLGroupActions::endIM(group_id); - } -} - - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -964,20 +241,6 @@ void LLChicletPanel::onMessageCountChanged(const LLSD& data) { unread = 0; } - - std::list chiclets = LLIMChiclet::sFindChicletsSignal(session_id); - std::list::iterator iter; - for (iter = chiclets.begin(); iter != chiclets.end(); iter++) { - LLChiclet* chiclet = *iter; - if (chiclet != NULL) - { - chiclet->setCounter(unread); - } - else - { - llwarns << "Unable to set counter for chiclet " << session_id << llendl; - } - } } void LLChicletPanel::objectChicletCallback(const LLSD& data) @@ -992,10 +255,6 @@ void LLChicletPanel::objectChicletCallback(const LLSD& data) LLIMChiclet* chiclet = dynamic_cast(*iter); if (chiclet != NULL) { - if(data.has("unread")) - { - chiclet->setCounter(data["unread"]); - } chiclet->setShowNewMessagesIcon(new_message); } } @@ -1037,7 +296,6 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) LLIMChiclet* chiclet = dynamic_cast(*it); if(chiclet) { - chiclet->setShowSpeaker(true); if (gSavedSettings.getBOOL("OpenIMOnVoice")) { LLFloaterIMContainer::getInstance()->showConversation(session_id); @@ -1045,20 +303,6 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) } } - if(!s_previous_active_voice_session_id.isNull() && s_previous_active_voice_session_id != session_id) - { - chiclets = LLIMChiclet::sFindChicletsSignal(s_previous_active_voice_session_id); - - for(std::list::iterator it = chiclets.begin(); it != chiclets.end(); ++it) - { - LLIMChiclet* chiclet = dynamic_cast(*it); - if(chiclet) - { - chiclet->setShowSpeaker(false); - } - } - } - s_previous_active_voice_session_id = session_id; } @@ -1544,85 +788,6 @@ bool LLChicletPanel::isAnyIMFloaterDoked() return res; } -S32 LLChicletPanel::getTotalUnreadIMCount() -{ - S32 count = 0; - chiclet_list_t::const_iterator it = mChicletList.begin(); - for( ; mChicletList.end() != it; ++it) - { - LLIMChiclet* chiclet = dynamic_cast(*it); - if(chiclet) - { - count += chiclet->getCounter(); - } - } - return count; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLChicletNotificationCounterCtrl::Params::Params() -: max_displayed_count("max_displayed_count", 99) -{ -} - -LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p) - : LLTextBox(p) - , mCounter(0) - , mInitialWidth(0) - , mMaxDisplayedCount(p.max_displayed_count) -{ - mInitialWidth = getRect().getWidth(); -} - -void LLChicletNotificationCounterCtrl::setCounter(S32 counter) -{ - mCounter = counter; - - // note same code in LLSysWellChiclet::setCounter(S32 counter) - std::string s_count; - if(counter != 0) - { - static std::string more_messages_exist("+"); - std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); - s_count = llformat("%d%s" - , llmin(counter, mMaxDisplayedCount) - , more_messages.c_str() - ); - } - - if(mCounter != 0) - { - setText(s_count); - } - else - { - setText(std::string("")); - } -} - -LLRect LLChicletNotificationCounterCtrl::getRequiredRect() -{ - LLRect rc; - S32 text_width = getTextPixelWidth(); - - rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth); - - return rc; -} - -void LLChicletNotificationCounterCtrl::setValue(const LLSD& value) -{ - if(value.isInteger()) - setCounter(value.asInteger()); -} - -LLSD LLChicletNotificationCounterCtrl::getValue() const -{ - return LLSD(getCounter()); -} - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -1632,28 +797,6 @@ LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) { } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p) -: LLIconCtrl(p) -, mDefaultIcon(p.default_icon) -{ - setValue(LLUUID::null); -} - -void LLChicletGroupIconCtrl::setValue(const LLSD& value ) -{ - if(value.asUUID().isNull()) - { - LLIconCtrl::setValue(mDefaultIcon); - } - else - { - LLIconCtrl::setValue(value); - } -} ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -1681,15 +824,6 @@ void LLChicletInvOfferIconCtrl::setValue(const LLSD& value ) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) - : LLOutputMonitorCtrl(p) -{ -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - LLScriptChiclet::Params::Params() : icon("icon") , chiclet_button("chiclet_button") @@ -1725,11 +859,6 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id) setToolTip(LLScriptFloaterManager::getObjectName(session_id)); } -void LLScriptChiclet::setCounter(S32 counter) -{ - setShowNewMessagesIcon( counter > 0 ); -} - void LLScriptChiclet::onMouseDown() { LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); @@ -1808,11 +937,6 @@ void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) } } -void LLInvOfferChiclet::setCounter(S32 counter) -{ - setShowNewMessagesIcon( counter > 0 ); -} - void LLInvOfferChiclet::onMouseDown() { LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 7f72c7f9e2..bd6c1a3e71 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -29,75 +29,10 @@ #include "llavatariconctrl.h" #include "llbutton.h" -#include "llflashtimer.h" -#include "llpanel.h" -#include "lltextbox.h" -#include "lloutputmonitorctrl.h" -#include "llgroupmgr.h" -#include "llimview.h" -#include "llnotifications.h" class LLMenuGL; class LLFloaterIMSession; -/** - * Class for displaying amount of messages/notifications(unread). - */ -class LLChicletNotificationCounterCtrl : public LLTextBox -{ -public: - - struct Params : public LLInitParam::Block - { - /** - * Contains maximum displayed count of unread messages. Default value is 9. - * - * If count is less than "max_unread_count" will be displayed as is. - * Otherwise 9+ will be shown (for default value). - */ - Optional max_displayed_count; - - Params(); - }; - - /** - * Sets number of notifications - */ - virtual void setCounter(S32 counter); - - /** - * Returns number of notifications - */ - virtual S32 getCounter() const { return mCounter; } - - /** - * Returns width, required to display amount of notifications in text form. - * Width is the only valid value. - */ - /*virtual*/ LLRect getRequiredRect(); - - /** - * Sets number of notifications using LLSD - */ - /*virtual*/ void setValue(const LLSD& value); - - /** - * Returns number of notifications wrapped in LLSD - */ - /*virtual*/ LLSD getValue() const; - -protected: - - LLChicletNotificationCounterCtrl(const Params& p); - friend class LLUICtrlFactory; - -private: - - S32 mCounter; - S32 mInitialWidth; - S32 mMaxDisplayedCount; -}; - /** * Class for displaying avatar's icon in P2P chiclet. */ @@ -121,35 +56,6 @@ protected: friend class LLUICtrlFactory; }; -/** - * Class for displaying group's icon in Group chiclet. - */ -class LLChicletGroupIconCtrl : public LLIconCtrl -{ -public: - - struct Params : public LLInitParam::Block - { - Optional default_icon; - - Params() - : default_icon("default_icon", "Generic_Group") - {} - }; - - /** - * Sets icon, if value is LLUUID::null - default icon will be set. - */ - virtual void setValue(const LLSD& value ); - -protected: - - LLChicletGroupIconCtrl(const Params& p); - friend class LLUICtrlFactory; - - std::string mDefaultIcon; -}; - /** * Class for displaying icon in inventory offer chiclet. */ @@ -183,23 +89,6 @@ private: std::string mDefaultIcon; }; -/** - * Class for displaying of speaker's voice indicator - */ -class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl -{ -public: - - struct Params : public LLInitParam::Block - { - Params(){}; - }; -protected: - - LLChicletSpeakerCtrl(const Params&p); - friend class LLUICtrlFactory; -}; - /** * Base class for all chiclets. */ @@ -227,26 +116,6 @@ public: */ virtual const LLUUID& getSessionId() const { return mSessionId; } - /** - * Sets number of unread notifications. - */ - virtual void setCounter(S32 counter) = 0; - - /** - * Returns number of unread notifications. - */ - virtual S32 getCounter() = 0; - - /** - * Sets show counter state. - */ - virtual void setShowCounter(bool show) { mShowCounter = show; } - - /** - * Returns show counter state. - */ - virtual bool getShowCounter() {return mShowCounter;}; - /** * Connects chiclet clicked event with callback. */ @@ -324,62 +193,6 @@ public: * It is used for default setting up of chicklet:click handler, etc. */ BOOL postBuild(); - /** - * Sets IM session name. This name will be displayed in chiclet tooltip. - */ - virtual void setIMSessionName(const std::string& name) { setToolTip(name); } - - /** - * Sets id of person/group user is chatting with. - * Session id should be set before calling this - */ - virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; } - - /** - * Gets id of person/group user is chatting with. - */ - virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; } - - /** - * Init Speaker Control with speaker's ID - */ - virtual void initSpeakerControl(); - - /** - * set status (Shows/Hide) for voice control. - */ - virtual void setShowSpeaker(bool show); - - /** - * Returns voice chat status control visibility. - */ - virtual bool getShowSpeaker() {return mShowSpeaker;}; - - /** - * Shows/Hides for voice control for a chiclet. - */ - virtual void toggleSpeakerControl(); - - /** - * Sets number of unread messages. Will update chiclet's width if number text - * exceeds size of counter and notify it's parent about size change. - */ - virtual void setCounter(S32); - - /** - * Enables/disables the counter control for a chiclet. - */ - virtual void enableCounterControl(bool enable); - - /** - * Sets show counter state. - */ - virtual void setShowCounter(bool show); - - /** - * Shows/Hides for counter control for a chiclet. - */ - virtual void toggleCounterControl(); /** * Sets required width for a chiclet according to visible controls. @@ -396,21 +209,6 @@ public: */ virtual bool getShowNewMessagesIcon(); - virtual void draw(); - - /** - * Determine whether given ID refers to a group or an IM chat session. - * - * This is used when we need to chose what IM chiclet (P2P/group) - * class to instantiate. - * - * @param session_id session ID. - * @return TYPE_GROUP in case of group chat session, - * TYPE_IM in case of P2P session, - * TYPE_UNKNOWN otherwise. - */ - static EType getIMSessionType(const LLUUID& session_id); - /** * The action taken on mouse down event. * @@ -452,8 +250,6 @@ protected: S32 mDefaultWidth; LLIconCtrl* mNewMessagesIcon; - LLChicletNotificationCounterCtrl* mCounterCtrl; - LLChicletSpeakerCtrl* mSpeakerCtrl; LLButton* mChicletButton; /** the id of another participant, either an avatar id or a group id*/ @@ -481,137 +277,6 @@ public: sFindChicletsSignal; }; -/** - * Implements P2P chiclet. - */ -class LLIMP2PChiclet : public LLIMChiclet -{ -public: - struct Params : public LLInitParam::Block - { - Optional chiclet_button; - - Optional avatar_icon; - - Optional unread_notifications; - - Optional speaker; - - Optional new_message_icon; - - Optional show_speaker; - - Params(); - }; - - /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - -protected: - LLIMP2PChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Creates chiclet popup menu. Will create P2P or Group IM Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables/disables menus based on relationship with other participant. - * Enables/disables "show session" menu item depending on visible IM floater existence. - */ - virtual void updateMenuItems(); - -private: - - LLChicletAvatarIconCtrl* mChicletIconCtrl; -}; - -/** - * Implements AD-HOC chiclet. - */ -class LLAdHocChiclet : public LLIMChiclet -{ -public: - struct Params : public LLInitParam::Block - { - Optional chiclet_button; - - Optional avatar_icon; - - Optional unread_notifications; - - Optional speaker; - - Optional new_message_icon; - - Optional show_speaker; - - Optional avatar_icon_color; - - Params(); - }; - - /** - * Sets session id. - * Session ID for group chat is actually Group ID. - */ - /*virtual*/ void setSessionId(const LLUUID& session_id); - - /** - * Keep Speaker Control with actual speaker's ID - */ - /*virtual*/ void draw(); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - -protected: - LLAdHocChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Creates chiclet popup menu. Will create AdHoc Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Finds a current speaker and resets the SpeakerControl with speaker's ID - */ - /*virtual*/ void switchToCurrentSpeaker(); - -private: - - LLChicletAvatarIconCtrl* mChicletIconCtrl; -}; /** * Chiclet for script floaters. @@ -633,10 +298,6 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter); - - /*virtual*/ S32 getCounter() { return 0; } - /** * Toggle script floater */ @@ -682,10 +343,6 @@ public: /*virtual*/ void setSessionId(const LLUUID& session_id); - /*virtual*/ void setCounter(S32 counter); - - /*virtual*/ S32 getCounter() { return 0; } - /** * Toggle script floater */ @@ -709,214 +366,6 @@ private: LLChicletInvOfferIconCtrl* mChicletIconCtrl; }; -/** - * Implements Group chat chiclet. - */ -class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver -{ -public: - - struct Params : public LLInitParam::Block - { - Optional chiclet_button; - - Optional group_icon; - - Optional unread_notifications; - - Optional speaker; - - Optional new_message_icon; - - Optional show_speaker; - - Params(); - }; - - /** - * Sets session id. - * Session ID for group chat is actually Group ID. - */ - /*virtual*/ void setSessionId(const LLUUID& session_id); - - /** - * Keep Speaker Control with actual speaker's ID - */ - /*virtual*/ void draw(); - - /** - * Callback for LLGroupMgrObserver, we get this when group data is available or changed. - * Sets group icon. - */ - /*virtual*/ void changed(LLGroupChange gc); - - /** - * Init Speaker Control with speaker's ID - */ - /*virtual*/ void initSpeakerControl(); - - /** - * Returns number of unread messages. - */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } - - ~LLIMGroupChiclet(); - -protected: - LLIMGroupChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Finds a current speaker and resets the SpeakerControl with speaker's ID - */ - /*virtual*/ void switchToCurrentSpeaker(); - - /** - * Creates chiclet popup menu. Will create P2P or Group IM Chat menu - * based on other participant's id. - */ - virtual void createPopupMenu(); - - /** - * Processes clicks on chiclet popup menu. - */ - virtual void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables/disables "show session" menu item depending on visible IM floater existence. - */ - virtual void updateMenuItems(); - -private: - - LLChicletGroupIconCtrl* mChicletIconCtrl; -}; - -/** - * Implements notification chiclet. Used to display total amount of unread messages - * across all IM sessions, total amount of system notifications. See EXT-3147 for details - */ -class LLSysWellChiclet : public LLChiclet -{ -public: - - struct Params : public LLInitParam::Block - { - Optional button; - - Optional unread_notifications; - - /** - * Contains maximum displayed count of unread messages. Default value is 9. - * - * If count is less than "max_unread_count" will be displayed as is. - * Otherwise 9+ will be shown (for default value). - */ - Optional max_displayed_count; - - Params(); - }; - - /*virtual*/ void setCounter(S32 counter); - - // *TODO: mantipov: seems getCounter is not necessary for LLNotificationChiclet - // but inherited interface requires it to implement. - // Probably it can be safe removed. - /*virtual*/S32 getCounter() { return mCounter; } - - boost::signals2::connection setClickCallback(const commit_callback_t& cb); - - /*virtual*/ ~LLSysWellChiclet(); - - void setToggleState(BOOL toggled); - - void setNewMessagesState(bool new_messages); - //this method should change a widget according to state of the SysWellWindow - virtual void updateWidget(bool is_window_empty); - -protected: - - LLSysWellChiclet(const Params& p); - friend class LLUICtrlFactory; - - /** - * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa. - * - * There is an assumption that it will be called 2*N times to do not change its start state. - * @see FlashToLitTimer - */ - void changeLitState(bool blink); - - /** - * Displays menu. - */ - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - - virtual void createMenu() = 0; - -protected: - class FlashToLitTimer; - LLButton* mButton; - S32 mCounter; - S32 mMaxDisplayedCount; - bool mIsNewMessagesState; - - LLFlashTimer* mFlashToLitTimer; - LLContextMenu* mContextMenu; -}; - -class LLNotificationChiclet : public LLSysWellChiclet -{ - LOG_CLASS(LLNotificationChiclet); - - friend class LLUICtrlFactory; -public: - struct Params : public LLInitParam::Block{}; - -protected: - struct ChicletNotificationChannel : public LLNotificationChannel - { - ChicletNotificationChannel(LLNotificationChiclet* chiclet) - : LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), - mChiclet(chiclet) - { - // connect counter handlers to the signals - connectToChannel("Group Notifications"); - connectToChannel("Offer"); - connectToChannel("Notifications"); - } - - static bool filterNotification(LLNotificationPtr notify); - // connect counter updaters to the corresponding signals - /*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } - /*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } - - LLNotificationChiclet* const mChiclet; - }; - - boost::scoped_ptr mNotificationChannel; - - LLNotificationChiclet(const Params& p); - - /** - * Processes clicks on chiclet menu. - */ - void onMenuItemClicked(const LLSD& user_data); - - /** - * Enables chiclet menu items. - */ - bool enableMenuItem(const LLSD& user_data); - - /** - * Creates menu. - */ - /*virtual*/ void createMenu(); - - /*virtual*/ void setCounter(S32 counter); - S32 mUreadSystemNotifications; -}; - /** * Storage class for all IM chiclets. Provides mechanism to display, * scroll, create, remove chiclets. @@ -1018,9 +467,7 @@ public: S32 getMinWidth() const { return mMinWidth; } - S32 getTotalUnreadIMCount(); - - S32 notifyParent(const LLSD& info); + /*virtual*/ S32 notifyParent(const LLSD& info); /** * Toggle chiclet by session id ON and toggle OFF all other chiclets. diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index cfcde64e7b..fde7764129 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -25,18 +25,11 @@ */ #include "llviewerprecompiledheaders.h" // must be first include - #include "llchicletbar.h" -// library includes -#include "llfloaterreg.h" -#include "lllayoutstack.h" - -// newview includes #include "llchiclet.h" -#include "llfloaterimsession.h" // for LLFloaterIMSession +#include "lllayoutstack.h" #include "llpaneltopinfobar.h" -#include "llsyswellwindow.h" namespace { @@ -60,106 +53,11 @@ LLChicletBar::LLChicletBar(const LLSD&) buildFromFile("panel_chiclet_bar.xml"); } -LLChicletBar::~LLChicletBar() -{ -} - -LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) -{ - LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id); - - switch (im_chiclet_type) - { - case LLIMChiclet::TYPE_IM: - return getChicletPanel()->createChiclet(session_id); - case LLIMChiclet::TYPE_GROUP: - return getChicletPanel()->createChiclet(session_id); - case LLIMChiclet::TYPE_AD_HOC: - return getChicletPanel()->createChiclet(session_id); - case LLIMChiclet::TYPE_UNKNOWN: - break; - } - - return NULL; -} - -//virtual -void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) -{ - if (!getChicletPanel()) return; - - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (!session) return; - - // no need to spawn chiclets for participants in P2P calls called through Avaline - if (session->isP2P() && session->isOtherParticipantAvaline()) return; - - // Do not spawn chiclet when using the new multitab conversation UI - if (LLFloaterIMSessionTab::isChatMultiTab()) - { - LLFloaterIMSessionTab::addToHost(session_id); - return; - } - - if (getChicletPanel()->findChiclet(session_id)) return; - - LLIMChiclet* chiclet = createIMChiclet(session_id); - if(chiclet) - { - chiclet->setIMSessionName(name); - chiclet->setOtherParticipantId(other_participant_id); - - LLFloaterIMSession::onIMChicletCreated(session_id); - - } - else - { - llwarns << "Could not create chiclet" << llendl; - } -} - -//virtual -void LLChicletBar::sessionRemoved(const LLUUID& session_id) -{ - if(getChicletPanel()) - { - // IM floater should be closed when session removed and associated chiclet closed - LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance("impanel", session_id); - if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater()) - { - // Close the IM floater only if we are not planning to close the P2P chat - // and start a new conference in the same floater. - im_floater->closeFloater(); - } - - getChicletPanel()->removeChiclet(session_id); - } -} - -void LLChicletBar::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ - //this is only needed in case of outgoing ad-hoc/group chat sessions - LLChicletPanel* chiclet_panel = getChicletPanel(); - if (chiclet_panel) - { - //it should be ad-hoc im chiclet or group im chiclet - LLChiclet* chiclet = chiclet_panel->findChiclet(old_session_id); - if (chiclet) chiclet->setSessionId(new_session_id); - } -} - -S32 LLChicletBar::getTotalUnreadIMCount() -{ - return getChicletPanel()->getTotalUnreadIMCount(); -} - BOOL LLChicletBar::postBuild() { mToolbarStack = getChild("toolbar_stack"); mChicletPanel = getChild("chiclet_list"); - showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty()); - LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this)); diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index dc991ca772..956c82cb77 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -28,7 +28,6 @@ #define LL_LLCHICLETBAR_H #include "llpanel.h" -#include "llimview.h" class LLChicletPanel; class LLIMChiclet; @@ -38,32 +37,17 @@ class LLLayoutStack; class LLChicletBar : public LLSingleton , public LLPanel - , public LLIMSessionObserver { LOG_CLASS(LLChicletBar); friend class LLSingleton; public: - ~LLChicletBar(); BOOL postBuild(); LLChicletPanel* getChicletPanel() { return mChicletPanel; } - // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; - /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - - S32 getTotalUnreadIMCount(); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); - /** - * Creates IM Chiclet based on session type (IM chat or Group chat) - */ - LLIMChiclet* createIMChiclet(const LLUUID& session_id); /** * Shows/hides panel with specified well button (IM or Notification) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 212b0df712..9829ae713c 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -616,10 +616,14 @@ void LLFloaterIMSession::setVisible(BOOL visible) if(!visible) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet(mSessionID); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - chiclet->setToggleState(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(mSessionID); + if(NULL != chicletp) + { + chicletp->setToggleState(false); + } } } diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index dc12192697..0e0da6bdc7 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -95,7 +95,12 @@ bool LLScriptFloater::toggle(const LLUUID& notification_id) show(notification_id); } - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(notification_id, true); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(notification_id, true); + } + return true; } @@ -206,10 +211,14 @@ void LLScriptFloater::setVisible(BOOL visible) if(!visible) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet(getNotificationId()); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - chiclet->setToggleState(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + if(NULL != chicletp) + { + chicletp->setToggleState(false); + } } } } @@ -218,15 +227,19 @@ void LLScriptFloater::onMouseDown() { if(getNotificationId().notNull()) { - // Remove new message icon - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet(getNotificationId()); - if (chiclet == NULL) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); - } - else - { - chiclet->setShowNewMessagesIcon(false); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + // Remove new message icon + if (NULL == chicletp) + { + llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); + } + else + { + chicletp->setShowNewMessagesIcon(false); + } } } } @@ -262,7 +275,11 @@ void LLScriptFloater::onFocusLost() { if(getNotificationId().notNull()) { - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), false); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), false); + } } } @@ -271,7 +288,11 @@ void LLScriptFloater::onFocusReceived() // first focus will be received before setObjectId() call - don't toggle chiclet if(getNotificationId().notNull()) { - LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(getNotificationId(), true); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->setChicletToggleState(getNotificationId(), true); + } } } @@ -279,28 +300,30 @@ void LLScriptFloater::dockToChiclet(bool dock) { if (getDockControl() == NULL) { - LLChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet(getNotificationId()); - if (chiclet == NULL) - { - llwarns << "Dock chiclet for LLScriptFloater doesn't exist" << llendl; - return; - } - else + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); - } + LLChiclet * chicletp = chiclet_panelp->findChiclet(getNotificationId()); + if (NULL == chicletp) + { + llwarns << "Dock chiclet for LLScriptFloater doesn't exist" << llendl; + return; + } - // Stop saving position while we dock floater - bool save = getSavePosition(); - setSavePosition(false); + chiclet_panelp->scrollToChiclet(chicletp); - setDockControl(new LLDockControl(chiclet, this, getDockTongue(), - LLDockControl::BOTTOM)); + // Stop saving position while we dock floater + bool save = getSavePosition(); + setSavePosition(false); - setDocked(dock); + setDockControl(new LLDockControl(chicletp, this, getDockTongue(), + LLDockControl::BOTTOM)); - // Restore saving - setSavePosition(save); + setDocked(dock); + + // Restore saving + setSavePosition(save); + } } } @@ -347,11 +370,15 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) script_notification_map_t::const_iterator it = findUsingObjectId(object_id); if(it != mNotifications.end()) { - LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet(it->first); - if(chiclet) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - // Pass the new_message icon state further. - set_new_message = chiclet->getShowNewMessagesIcon(); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(it->first); + if(NULL != chicletp) + { + // Pass the new_message icon state further. + set_new_message = chicletp->getShowNewMessagesIcon(); + } } LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", it->first); @@ -367,14 +394,18 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) mNotifications.insert(std::make_pair(notification_id, object_id)); - // Create inventory offer chiclet for offer type notifications - if( OBJ_GIVE_INVENTORY == obj_type ) + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) { - LLChicletBar::instance().getChicletPanel()->createChiclet(notification_id); - } - else - { - LLChicletBar::getInstance()->getChicletPanel()->createChiclet(notification_id); + // Create inventory offer chiclet for offer type notifications + if( OBJ_GIVE_INVENTORY == obj_type ) + { + chiclet_panelp->createChiclet(notification_id); + } + else + { + chiclet_panelp->createChiclet(notification_id); + } } LLIMWellWindow::getInstance()->addObjectRow(notification_id, set_new_message); @@ -410,7 +441,11 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) // remove related chiclet if (LLChicletBar::instanceExists()) { - LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id); + LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); + if (NULL != chiclet_panelp) + { + chiclet_panelp->removeChiclet(notification_id); + } } LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 3605129d48..8a43855a7d 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -23,35 +23,23 @@ * $/LicenseInfo$ */ - #include "llviewerprecompiledheaders.h" // must be first include - #include "llsyswellwindow.h" -#include "llagent.h" -#include "llavatarnamecache.h" - -#include "llflatlistview.h" -#include "llfloaterreg.h" -#include "llnotifications.h" - -#include "llscriptfloater.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" - #include "llchiclet.h" #include "llchicletbar.h" -#include "lltoastpanel.h" +#include "llflatlistview.h" +#include "llfloaterreg.h" #include "llnotificationmanager.h" #include "llnotificationsutil.h" +#include "llscriptfloater.h" #include "llspeakers.h" -#include "lltoolbarview.h" +#include "lltoastpanel.h" //--------------------------------------------------------------------------------- LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), mChannel(NULL), mMessageList(NULL), - mSysWellChiclet(NULL), NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), IM_WELL_ANCHOR_NAME("im_well_panel"), mIsReshapedByUser(false) @@ -68,10 +56,6 @@ BOOL LLSysWellWindow::postBuild() // get a corresponding channel initChannel(); - // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147. - // mouse up callback is not called in this case. - setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); - return LLTransientDockableFloater::postBuild(); } @@ -95,14 +79,6 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) setVisible(TRUE); } -void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) -{ - mSysWellChiclet = chiclet; - if(NULL != mSysWellChiclet) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } -} //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() { @@ -113,10 +89,6 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) { if(mMessageList->removeItemByValue(id)) { - if (NULL != mSysWellChiclet) - { - mSysWellChiclet->updateWidget(isWindowEmpty()); - } reshapeWindow(); } else @@ -170,11 +142,6 @@ void LLSysWellWindow::setVisible(BOOL visible) mChannel->updateShowToastsState(); mChannel->redrawToasts(); } - - if (visible) - { - releaseNewMessagesState(); - } } //--------------------------------------------------------------------------------- @@ -224,135 +191,12 @@ void LLSysWellWindow::reshapeWindow() } } -void LLSysWellWindow::releaseNewMessagesState() -{ - if (NULL != mSysWellChiclet) - { - mSysWellChiclet->setNewMessagesState(false); - } -} - //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { return mMessageList->size() == 0; } -/************************************************************************/ -/* RowPanel implementation */ -/************************************************************************/ - -//--------------------------------------------------------------------------------- -LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, - S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : - LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) -{ - buildFromFile( "panel_activeim_row.xml"); - - // Choose which of the pre-created chiclets (IM/group) to use. - // The other one gets hidden. - - LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId); - switch (im_chiclet_type) - { - case LLIMChiclet::TYPE_GROUP: - mChiclet = getChild("group_chiclet"); - break; - case LLIMChiclet::TYPE_AD_HOC: - mChiclet = getChild("adhoc_chiclet"); - break; - case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway - case LLIMChiclet::TYPE_IM: - mChiclet = getChild("p2p_chiclet"); - break; - } - - // Initialize chiclet. - mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2)); - mChiclet->enableCounterControl(true); - mChiclet->setCounter(chicletCounter); - mChiclet->setSessionId(sessionId); - mChiclet->setIMSessionName(name); - mChiclet->setOtherParticipantId(otherParticipantId); - mChiclet->setVisible(true); - - if (im_chiclet_type == LLIMChiclet::TYPE_IM) - { - LLAvatarNameCache::get(otherParticipantId, - boost::bind(&LLIMWellWindow::RowPanel::onAvatarNameCache, - this, _1, _2)); - } - else - { - LLTextBox* contactName = getChild("contact_name"); - contactName->setValue(name); - } - - mCloseBtn = getChild("hide_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this)); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) -{ - LLTextBox* contactName = getChild("contact_name"); - contactName->setValue( av_name.getCompleteName() ); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) -{ - LLTextBox* text = getChild("contact_name"); - S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD; - LLRect text_rect = text->getRect(); - text_rect.mLeft = new_text_left; - text->setShape(text_rect); -} - -//--------------------------------------------------------------------------------- -LLIMWellWindow::RowPanel::~RowPanel() -{ -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onClosePanel() -{ - gIMMgr->leaveSession(mChiclet->getSessionId()); - // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) -{ - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) -{ - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); -} - -//--------------------------------------------------------------------------------- -// virtual -BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) -{ - // Pass the mouse down event to the chiclet (EXT-596). - if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() - { - mChiclet->onMouseDown(); - return TRUE; - } - - return LLPanel::handleMouseDown(x, y, mask); -} - -// virtual -BOOL LLIMWellWindow::RowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - return mChiclet->handleRightMouseDown(x, y, mask); -} /************************************************************************/ /* ObjectRowPanel implementation */ /************************************************************************/ @@ -490,9 +334,7 @@ void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) LLSysWellItem* new_item = new LLSysWellItem(p); if (mMessageList->addItem(new_item, value, ADD_TOP)) { - mSysWellChiclet->updateWidget(isWindowEmpty()); reshapeWindow(); - new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); } @@ -576,9 +418,6 @@ void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) removeItemByID(notify->getID()); } - - - /************************************************************************/ /* LLIMWellWindow implementation */ /************************************************************************/ @@ -588,12 +427,10 @@ void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) LLIMWellWindow::LLIMWellWindow(const LLSD& key) : LLSysWellWindow(key) { - LLIMMgr::getInstance()->addSessionObserver(this); } LLIMWellWindow::~LLIMWellWindow() { - LLIMMgr::getInstance()->removeSessionObserver(this); } // static @@ -614,47 +451,11 @@ BOOL LLIMWellWindow::postBuild() BOOL rv = LLSysWellWindow::postBuild(); setTitle(getString("title_im_well_window")); - LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1)); return rv; } -//virtual -void LLIMWellWindow::sessionAdded(const LLUUID& session_id, - const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) -{ - LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (!session) return; - - // no need to spawn chiclets for participants in P2P calls called through Avaline - if (session->isP2P() && session->isOtherParticipantAvaline()) return; - - if (mMessageList->getItemByValue(session_id)) return; - - addIMRow(session_id, 0, name, other_participant_id); - reshapeWindow(); -} - -//virtual -void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId) -{ - delIMRow(sessionId); - reshapeWindow(); -} - -//virtual -void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ - //for outgoing ad-hoc and group im sessions only - LLChiclet* chiclet = findIMChiclet(old_session_id); - if (chiclet) - { - chiclet->setSessionId(new_session_id); - mMessageList->updateValue(old_session_id, new_session_id); - } -} - LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) { if (!mMessageList) return NULL; @@ -671,66 +472,6 @@ LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS -LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) -{ - if (!mMessageList) return NULL; - - LLChiclet* res = NULL; - RowPanel* panel = mMessageList->getTypedItemByValue(sessionId); - if (panel != NULL) - { - res = panel->mChiclet; - } - - return res; -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, - const std::string& name, const LLUUID& otherParticipantId) -{ - RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); - if (!mMessageList->addItem(item, sessionId)) - { - llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId - << ", name: " << name - << ", other participant ID: " << otherParticipantId - << llendl; - - item->die(); - } -} - -//--------------------------------------------------------------------------------- -void LLIMWellWindow::delIMRow(const LLUUID& sessionId) -{ - //fix for EXT-3252 - //without this line LLIMWellWindow receive onFocusLost - //and hide itself. It was becaue somehow LLIMChicklet was in focus group for - //LLIMWellWindow... - //But I didn't find why this happen.. - gFocusMgr.clearLastFocusForGroup(this); - - if (!mMessageList->removeItemByValue(sessionId)) - { - llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId - << llendl; - } - - // remove all toasts that belong to this session from a screen - if(mChannel) - mChannel->removeToastsBySessionID(sessionId); - - // hide chiclet window if there are no items left - if(isWindowEmpty()) - { - setVisible(FALSE); - } - else - { - setFocus(true); - } -} void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_message/* = false*/) { @@ -761,21 +502,6 @@ void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id) } } - -void LLIMWellWindow::addIMRow(const LLUUID& session_id) -{ - if (hasIMRow(session_id)) return; - - LLIMModel* im_model = LLIMModel::getInstance(); - addIMRow(session_id, 0, im_model->getName(session_id), im_model->getOtherParticipantID(session_id)); - reshapeWindow(); -} - -bool LLIMWellWindow::hasIMRow(const LLUUID& session_id) -{ - return mMessageList->getItemByValue(session_id); -} - void LLIMWellWindow::closeAll() { // Generate an ignorable alert dialog if there is an active voice IM sesion @@ -820,13 +546,6 @@ void LLIMWellWindow::closeAllImpl() { LLPanel* panel = mMessageList->getItemByValue(*iter); - RowPanel* im_panel = dynamic_cast (panel); - if (im_panel) - { - gIMMgr->leaveSession(*iter); - continue; - } - ObjectRowPanel* obj_panel = dynamic_cast (panel); if (obj_panel) { diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d6480f1fc6..406ab1b59e 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -27,32 +27,26 @@ #ifndef LL_LLSYSWELLWINDOW_H #define LL_LLSYSWELLWINDOW_H -#include "llsyswellitem.h" - -#include "lltransientdockablefloater.h" -#include "llbutton.h" -#include "llscreenchannel.h" -#include "llscrollcontainer.h" #include "llimview.h" #include "llnotifications.h" - -#include "boost/shared_ptr.hpp" +#include "llscreenchannel.h" +#include "llsyswellitem.h" +#include "lltransientdockablefloater.h" class LLAvatarName; -class LLFlatListView; class LLChiclet; +class LLFlatListView; class LLIMChiclet; class LLScriptChiclet; class LLSysWellChiclet; - class LLSysWellWindow : public LLTransientDockableFloater { public: LOG_CLASS(LLSysWellWindow); LLSysWellWindow(const LLSD& key); - ~LLSysWellWindow(); + virtual ~LLSysWellWindow(); BOOL postBuild(); // other interface functions @@ -72,8 +66,6 @@ public: void onStartUpToastClick(S32 x, S32 y, MASK mask); - void setSysWellChiclet(LLSysWellChiclet* chiclet); - // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; static const S32 MIN_WINDOW_WIDTH = 318; @@ -87,17 +79,11 @@ protected: virtual const std::string& getAnchorViewName() = 0; void reshapeWindow(); - void releaseNewMessagesState(); // pointer to a corresponding channel's instance LLNotificationsUI::LLScreenChannel* mChannel; LLFlatListView* mMessageList; - /** - * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147 - */ - LLSysWellChiclet* mSysWellChiclet; - bool mIsReshapedByUser; }; @@ -157,7 +143,7 @@ private: * * It contains a list list of all active IM sessions. */ -class LLIMWellWindow : public LLSysWellWindow, LLIMSessionObserver, LLInitClass +class LLIMWellWindow : public LLSysWellWindow, LLInitClass { public: LLIMWellWindow(const LLSD& key); @@ -169,59 +155,19 @@ public: /*virtual*/ BOOL postBuild(); - // LLIMSessionObserver observe triggers - /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg); - /*virtual*/ void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} - /*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; - /*virtual*/ void sessionRemoved(const LLUUID& session_id); - /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - void addObjectRow(const LLUUID& notification_id, bool new_message = false); void removeObjectRow(const LLUUID& notification_id); - - void addIMRow(const LLUUID& session_id); - bool hasIMRow(const LLUUID& session_id); - void closeAll(); protected: /*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; } private: - LLChiclet * findIMChiclet(const LLUUID& sessionId); LLChiclet* findObjectChiclet(const LLUUID& notification_id); - void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); - void delIMRow(const LLUUID& sessionId); bool confirmCloseAll(const LLSD& notification, const LLSD& response); void closeAllImpl(); - /** - * Scrolling row panel. - */ - class RowPanel: public LLPanel - { - public: - RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, - const std::string& name, const LLUUID& otherParticipantId); - virtual ~RowPanel(); - void onMouseEnter(S32 x, S32 y, MASK mask); - void onMouseLeave(S32 x, S32 y, MASK mask); - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - - private: - static const S32 CHICLET_HPAD = 10; - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param); - void onClosePanel(); - public: - LLIMChiclet* mChiclet; - private: - LLButton* mCloseBtn; - const LLSysWellWindow* mParent; - }; - class ObjectRowPanel: public LLPanel { public: diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png deleted file mode 100644 index 0ac5b72b8f..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png deleted file mode 100644 index 857fa1e047..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png deleted file mode 100644 index 453bb53673..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png deleted file mode 100644 index 135a66ca0d..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png deleted file mode 100644 index a63aec5e6d..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png deleted file mode 100644 index 1719eb3e84..0000000000 Binary files a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8d9fa52309..bf6e933dfd 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -365,8 +365,6 @@ with the same filename but different name - - @@ -654,12 +652,6 @@ with the same filename but different name - - - - - - diff --git a/indra/newview/skins/default/xui/da/menu_im_well_button.xml b/indra/newview/skins/default/xui/da/menu_im_well_button.xml deleted file mode 100644 index 4889230919..0000000000 --- a/indra/newview/skins/default/xui/da/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/da/menu_notification_well_button.xml b/indra/newview/skins/default/xui/da/menu_notification_well_button.xml deleted file mode 100644 index 40b35b5fdd..0000000000 --- a/indra/newview/skins/default/xui/da/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/de/menu_im_well_button.xml b/indra/newview/skins/default/xui/de/menu_im_well_button.xml deleted file mode 100644 index f464b71f4a..0000000000 --- a/indra/newview/skins/default/xui/de/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/de/menu_notification_well_button.xml b/indra/newview/skins/default/xui/de/menu_notification_well_button.xml deleted file mode 100644 index 0f2784f160..0000000000 --- a/indra/newview/skins/default/xui/de/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml deleted file mode 100644 index 263ac40f4e..0000000000 --- a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml deleted file mode 100644 index 9369d1b5cf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - TestString PleaseIgnore - - - - diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml deleted file mode 100644 index 0e29ed0d0b..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml deleted file mode 100644 index 77011139bf..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml deleted file mode 100644 index 8b56a8f0f6..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - diff --git a/indra/newview/skins/default/xui/es/menu_im_well_button.xml b/indra/newview/skins/default/xui/es/menu_im_well_button.xml deleted file mode 100644 index c8f6c217cc..0000000000 --- a/indra/newview/skins/default/xui/es/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml deleted file mode 100644 index 0562d35be7..0000000000 --- a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/fr/menu_im_well_button.xml b/indra/newview/skins/default/xui/fr/menu_im_well_button.xml deleted file mode 100644 index 8ef1529e6b..0000000000 --- a/indra/newview/skins/default/xui/fr/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml deleted file mode 100644 index 323bfdbf16..0000000000 --- a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/it/menu_im_well_button.xml b/indra/newview/skins/default/xui/it/menu_im_well_button.xml deleted file mode 100644 index 9e471b771c..0000000000 --- a/indra/newview/skins/default/xui/it/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml deleted file mode 100644 index 8c82e30f0e..0000000000 --- a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/ja/menu_im_well_button.xml b/indra/newview/skins/default/xui/ja/menu_im_well_button.xml deleted file mode 100644 index 3397004bd7..0000000000 --- a/indra/newview/skins/default/xui/ja/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml deleted file mode 100644 index 913bae8958..0000000000 --- a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/pl/menu_im_well_button.xml b/indra/newview/skins/default/xui/pl/menu_im_well_button.xml deleted file mode 100644 index 207bc2211b..0000000000 --- a/indra/newview/skins/default/xui/pl/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml deleted file mode 100644 index bd3d42f9b1..0000000000 --- a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/pt/menu_im_well_button.xml b/indra/newview/skins/default/xui/pt/menu_im_well_button.xml deleted file mode 100644 index 2d37cefd6f..0000000000 --- a/indra/newview/skins/default/xui/pt/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml deleted file mode 100644 index 43ad4134ec..0000000000 --- a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/ru/menu_im_well_button.xml b/indra/newview/skins/default/xui/ru/menu_im_well_button.xml deleted file mode 100644 index 5a5bde61b9..0000000000 --- a/indra/newview/skins/default/xui/ru/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml deleted file mode 100644 index 4d067e232a..0000000000 --- a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/tr/menu_im_well_button.xml b/indra/newview/skins/default/xui/tr/menu_im_well_button.xml deleted file mode 100644 index c3e559a723..0000000000 --- a/indra/newview/skins/default/xui/tr/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml deleted file mode 100644 index 39c66268f5..0000000000 --- a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/zh/menu_im_well_button.xml b/indra/newview/skins/default/xui/zh/menu_im_well_button.xml deleted file mode 100644 index 4b9b4b2758..0000000000 --- a/indra/newview/skins/default/xui/zh/menu_im_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml deleted file mode 100644 index b629f73584..0000000000 --- a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - -- cgit v1.2.3 From 60c72c85e2360284ecc3326871dcc76fcce0e945 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Mon, 3 Dec 2012 19:06:52 -0800 Subject: Cleaning up some unreferenced member variables and related types from LLNotifications. --- indra/llui/CMakeLists.txt | 2 - indra/llui/llnotifications.cpp | 3 - indra/llui/llnotifications.h | 4 - indra/llui/llnotificationslistener.cpp | 354 --------------------------------- indra/llui/llnotificationslistener.h | 69 ------- indra/llui/llnotificationtemplate.h | 1 - 6 files changed, 433 deletions(-) delete mode 100644 indra/llui/llnotificationslistener.cpp delete mode 100644 indra/llui/llnotificationslistener.h diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index ccc7aa8cec..9c961d67d6 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -71,7 +71,6 @@ set(llui_SOURCE_FILES llmultislider.cpp llmultisliderctrl.cpp llnotifications.cpp - llnotificationslistener.cpp llnotificationsutil.cpp llpanel.cpp llprogressbar.cpp @@ -181,7 +180,6 @@ set(llui_HEADER_FILES llmultislider.h llnotificationptr.h llnotifications.h - llnotificationslistener.h llnotificationsutil.h llnotificationtemplate.h llnotificationvisibilityrule.h diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 66144671c9..61d5dcf12c 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -39,7 +39,6 @@ #include "lldir.h" #include "llsdserialize.h" #include "lltrans.h" -#include "llnotificationslistener.h" #include "llstring.h" #include "llsdparam.h" #include "llsdutil.h" @@ -1167,8 +1166,6 @@ LLNotifications::LLNotifications() mIgnoreAllNotifications(false) { LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); - - mListener.reset(new LLNotificationsListener(*this)); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 088931858a..a41e9fa5a3 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,7 +92,6 @@ #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" -#include "llnotificationslistener.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" @@ -672,7 +671,6 @@ namespace LLNotificationComparators }; typedef boost::function LLNotificationFilter; -typedef boost::function LLNotificationComparator; typedef std::set LLNotificationSet; typedef std::multimap LLNotificationMap; @@ -822,7 +820,6 @@ public: private: std::string mName; std::string mParent; - LLNotificationComparator mComparator; }; // An interface class to provide a clean linker seam to the LLNotifications class. @@ -942,7 +939,6 @@ private: bool mIgnoreAllNotifications; - boost::scoped_ptr mListener; std::vector mDefaultChannels; }; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp deleted file mode 100644 index e4e127336b..0000000000 --- a/indra/llui/llnotificationslistener.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/** - * @file llnotificationslistener.cpp - * @author Brad Kittenbrink - * @date 2009-07-08 - * @brief Implementation for llnotificationslistener. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llnotificationslistener.h" -#include "llnotifications.h" -#include "llnotificationtemplate.h" -#include "llsd.h" -#include "llui.h" - -LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : - LLEventAPI("LLNotifications", - "LLNotifications listener to (e.g.) pop up a notification"), - mNotifications(notifications) -{ - add("requestAdd", - "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" - "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", - &LLNotificationsListener::requestAdd); - add("listChannels", - "Post to [\"reply\"] a map of info on existing channels", - &LLNotificationsListener::listChannels, - LLSD().with("reply", LLSD())); - add("listChannelNotifications", - "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", - &LLNotificationsListener::listChannelNotifications, - LLSD().with("reply", LLSD()).with("channel", LLSD())); - add("respond", - "Respond to notification [\"uuid\"] with data in [\"response\"]", - &LLNotificationsListener::respond, - LLSD().with("uuid", LLSD())); - add("cancel", - "Cancel notification [\"uuid\"]", - &LLNotificationsListener::cancel, - LLSD().with("uuid", LLSD())); - add("ignore", - "Ignore future notification [\"name\"]\n" - "(from in notifications.xml)\n" - "according to boolean [\"ignore\"].\n" - "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" - "Note that ignored notifications are not forwarded unless intercepted before\n" - "the \"Ignore\" channel.", - &LLNotificationsListener::ignore); - add("forward", - "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" - "according to boolean [\"forward\"]. When enabled, only types matching\n" - "[\"types\"] are forwarded, as follows:\n" - "omitted or undefined: forward all notifications\n" - "string: forward only the specific named [sig]type\n" - "array of string: forward any notification matching any named [sig]type.\n" - "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" - "notification.", - &LLNotificationsListener::forward, - LLSD().with("channel", LLSD())); -} - -// This is here in the .cpp file so we don't need the definition of class -// Forwarder in the header file. -LLNotificationsListener::~LLNotificationsListener() -{ -} - -void LLNotificationsListener::requestAdd(const LLSD& event_data) const -{ - if(event_data.has("reply")) - { - mNotifications.add(event_data["name"], - event_data["substitutions"], - event_data["payload"], - boost::bind(&LLNotificationsListener::NotificationResponder, - this, - event_data["reply"].asString(), - _1, _2 - ) - ); - } - else - { - mNotifications.add(event_data["name"], - event_data["substitutions"], - event_data["payload"]); - } -} - -void LLNotificationsListener::NotificationResponder(const std::string& reply_pump, - const LLSD& notification, - const LLSD& response) const -{ - LLSD reponse_event; - reponse_event["notification"] = notification; - reponse_event["response"] = response; - LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); -} - -void LLNotificationsListener::listChannels(const LLSD& params) const -{ - LLReqID reqID(params); - LLSD response(reqID.makeResponse()); - for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), - cmend(LLNotificationChannel::endInstances()); - cmi != cmend; ++cmi) - { - LLSD channelInfo; - //channelInfo["parent"] = cmi->second->getParentChannelName(); - response[cmi->getName()] = channelInfo; - } - LLEventPumps::instance().obtain(params["reply"]).post(response); -} - -void LLNotificationsListener::listChannelNotifications(const LLSD& params) const -{ - LLReqID reqID(params); - LLSD response(reqID.makeResponse()); - LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); - if (channel) - { - LLSD notifications(LLSD::emptyArray()); - for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); - ni != nend; ++ni) - { - notifications.append(asLLSD(*ni)); - } - response["notifications"] = notifications; - } - LLEventPumps::instance().obtain(params["reply"]).post(response); -} - -void LLNotificationsListener::respond(const LLSD& params) const -{ - LLNotificationPtr notification(mNotifications.find(params["uuid"])); - if (notification) - { - notification->respond(params["response"]); - } -} - -void LLNotificationsListener::cancel(const LLSD& params) const -{ - LLNotificationPtr notification(mNotifications.find(params["uuid"])); - if (notification) - { - mNotifications.cancel(notification); - } -} - -void LLNotificationsListener::ignore(const LLSD& params) const -{ - // Calling a method named "ignore", but omitting its "ignore" Boolean - // argument, should by default cause something to be ignored. Explicitly - // pass ["ignore"] = false to cancel ignore. - bool ignore = true; - if (params.has("ignore")) - { - ignore = params["ignore"].asBoolean(); - } - // This method can be used to affect either a single notification name or - // all future notifications. The two use substantially different mechanisms. - if (params["name"].isDefined()) - { - // ["name"] was passed: ignore just that notification - LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]); - if (templatep) - { - templatep->mForm->setIgnored(ignore); - } - } - else - { - // no ["name"]: ignore all future notifications - mNotifications.setIgnoreAllNotifications(ignore); - } -} - -class LLNotificationsListener::Forwarder: public LLEventTrackable -{ - LOG_CLASS(LLNotificationsListener::Forwarder); -public: - Forwarder(LLNotifications& llnotifications, const std::string& channel): - mNotifications(llnotifications), - mRespond(false) - { - // Connect to the specified channel on construction. Because - // LLEventTrackable is a base, we should automatically disconnect when - // destroyed. - LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); - if (channelptr) - { - // Insert our processing as a "passed filter" listener. This way - // we get to run before all the "changed" listeners, and we get to - // swipe it (hide it from the other listeners) if desired. - channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1)); - } - } - - void setPumpName(const std::string& name) { mPumpName = name; } - void setTypes(const LLSD& types) { mTypes = types; } - void setRespond(bool respond) { mRespond = respond; } - -private: - bool handle(const LLSD& notification) const; - bool matchType(const LLSD& filter, const std::string& type) const; - - LLNotifications& mNotifications; - std::string mPumpName; - LLSD mTypes; - bool mRespond; -}; - -void LLNotificationsListener::forward(const LLSD& params) -{ - std::string channel(params["channel"]); - // First decide whether we're supposed to start forwarding or stop it. - // Default to true. - bool forward = true; - if (params.has("forward")) - { - forward = params["forward"].asBoolean(); - } - if (! forward) - { - // This is a request to stop forwarding notifications on the specified - // channel. The rest of the params don't matter. - // Because mForwarders contains scoped_ptrs, erasing the map entry - // DOES delete the heap Forwarder object. Because Forwarder derives - // from LLEventTrackable, destroying it disconnects it from the - // channel. - mForwarders.erase(channel); - return; - } - // From here on, we know we're being asked to start (or modify) forwarding - // on the specified channel. Find or create an appropriate Forwarder. - ForwarderMap::iterator - entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); - if (! entry->second) - { - entry->second.reset(new Forwarder(mNotifications, channel)); - } - // Now, whether this Forwarder is brand-new or not, update it with the new - // request info. - Forwarder& fwd(*entry->second); - fwd.setPumpName(params["pump"]); - fwd.setTypes(params["types"]); - fwd.setRespond(params["respond"]); -} - -bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const -{ - LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; - if (notification["sigtype"].asString() == "delete") - { - LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; - // let other listeners see the "delete" operation - return false; - } - LLNotificationPtr note(mNotifications.find(notification["id"])); - if (! note) - { - LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; - return false; - } - if (! matchType(mTypes, note->getType())) - { - LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; - // We're not supposed to intercept this particular notification. Let - // other listeners process it. - return false; - } - LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; - // This is a notification we care about. Forward it through specified - // LLEventPump. - LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); - // Are we also being asked to auto-respond? - if (mRespond) - { - LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; - note->respond(LLSD::emptyMap()); - // Did that succeed in removing the notification? Only cancel() if - // it's still around -- otherwise we get an LL_ERRS crash! - note = mNotifications.find(notification["id"]); - if (note) - { - LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; - mNotifications.cancel(note); - } - } - // If we've auto-responded to this notification, then it's going to be - // deleted. Other listeners would get the change operation, try to look it - // up and be baffled by lookup failure. So when we auto-respond, suppress - // this notification: don't pass it to other listeners. - return mRespond; -} - -bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const -{ - // Decide whether this notification matches filter: - // undefined: forward all notifications - if (filter.isUndefined()) - { - return true; - } - // array of string: forward any notification matching any named type - if (filter.isArray()) - { - for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); - ti != tend; ++ti) - { - if (ti->asString() == type) - { - return true; - } - } - // Didn't match any entry in the array - return false; - } - // string: forward only the specific named type - return (filter.asString() == type); -} - -LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) -{ - LLSD notificationInfo(note->asLLSD()); - // For some reason the following aren't included in LLNotification::asLLSD(). - notificationInfo["summary"] = note->summarize(); - notificationInfo["id"] = note->id(); - notificationInfo["type"] = note->getType(); - notificationInfo["message"] = note->getMessage(); - notificationInfo["label"] = note->getLabel(); - return notificationInfo; -} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h deleted file mode 100644 index f9f7641de6..0000000000 --- a/indra/llui/llnotificationslistener.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file llnotificationslistener.h - * @author Brad Kittenbrink - * @date 2009-07-08 - * @brief Wrap subset of LLNotifications API in event API for test scripts. - * - * $LicenseInfo:firstyear=2009&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_LLNOTIFICATIONSLISTENER_H -#define LL_LLNOTIFICATIONSLISTENER_H - -#include "lleventapi.h" -#include "llnotificationptr.h" -#include -#include -#include - -class LLNotifications; -class LLSD; - -class LLNotificationsListener : public LLEventAPI -{ -public: - LLNotificationsListener(LLNotifications & notifications); - ~LLNotificationsListener(); - -private: - void requestAdd(LLSD const & event_data) const; - - void NotificationResponder(const std::string& replypump, - const LLSD& notification, - const LLSD& response) const; - - void listChannels(const LLSD& params) const; - void listChannelNotifications(const LLSD& params) const; - void respond(const LLSD& params) const; - void cancel(const LLSD& params) const; - void ignore(const LLSD& params) const; - void forward(const LLSD& params); - - static LLSD asLLSD(LLNotificationPtr); - - class Forwarder; - typedef std::map > ForwarderMap; - ForwarderMap mForwarders; - LLNotifications & mNotifications; -}; - -#endif // LL_LLNOTIFICATIONSLISTENER_H diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 906b83a400..18a82190b5 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -49,7 +49,6 @@ //#include "llfunctorregistry.h" //#include "llpointer.h" #include "llinitparam.h" -//#include "llnotificationslistener.h" //#include "llnotificationptr.h" //#include "llcachename.h" #include "llnotifications.h" -- cgit v1.2.3 From 8c24cc8e3635888b766e30001749966eddc0dc7e Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Tue, 4 Dec 2012 14:38:19 +0200 Subject: CHUI-527 FIXED Changed term to "Multi-person chat" --- indra/newview/skins/default/xui/en/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a884ac94d6..c75bd98c38 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3400,7 +3400,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Connecting... - Ad-hoc Conference + Multi-person chat Conference with [AGENT_NAME] -- cgit v1.2.3 From ed9e48bf6bd440a004c0d82da79503de34261610 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Tue, 4 Dec 2012 14:48:59 +0200 Subject: CHUI-530 FIXED Using selectConversationPair will show appropriate session floater. --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3a80491dae..c1daea0aeb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1162,7 +1162,7 @@ bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_ve void LLFloaterIMContainer::showConversation(const LLUUID& session_id) { setVisibleAndFrontmost(false); - selectConversation(session_id); + selectConversationPair(session_id, true); } void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) -- cgit v1.2.3 From 7527431bedce5529d33add21ec53336800f48fd0 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 5 Dec 2012 13:54:55 +0200 Subject: CHUI-572 FIXED Changed initial position for floaters according to description. --- indra/newview/skins/default/xui/en/floater_camera.xml | 2 +- indra/newview/skins/default/xui/en/floater_destinations.xml | 7 ++++--- indra/newview/skins/default/xui/en/floater_im_container.xml | 9 +++++---- indra/newview/skins/default/xui/en/floater_moveview.xml | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 22bc488a92..4b4821a383 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,7 +1,7 @@ + width="550"> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 4aa7c88312..152c897120 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -3,7 +3,7 @@ can_close="true" can_minimize="true" can_resize="true" - height="430" + height="230" layout="topleft" min_height="50" name="floater_im_box" @@ -13,7 +13,8 @@ single_instance="true" reuse_instance="true" title="CONVERSATIONS" - width="680"> + bottom="-80" + width="450"> @@ -23,13 +24,13 @@ + width="450"> Date: Tue, 4 Dec 2012 20:49:42 +0200 Subject: CHUI-504 FIXED Open Conversation floater on first login. added toggleInstanceOrBringToFront("im_container") to LLStartup; typo corr. --- indra/newview/llstartup.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1704ad9055..34259658ea 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1520,7 +1520,7 @@ bool idle_startup() } //--------------------------------------------------------------------- - // Agent Send + // World Wait //--------------------------------------------------------------------- if(STATE_WORLD_WAIT == LLStartUp::getStartupState()) { @@ -1846,6 +1846,10 @@ bool idle_startup() // Set the show start location to true, now that the user has logged // on with this install. gSavedSettings.setBOOL("ShowStartLocation", TRUE); + + // Open Conversation floater on first login. + LLFloaterReg::toggleInstanceOrBringToFront("im_container"); + } display_startup(); @@ -2167,7 +2171,6 @@ bool idle_startup() LLStartUp::setStartupState( STATE_STARTED ); display_startup(); - // Unmute audio if desired and setup volumes. // Unmute audio if desired and setup volumes. // This is a not-uncommon crash site, so surround it with // llinfos output to aid diagnosis. -- cgit v1.2.3 From 6735d40d9a0e03007f6f7aef954022d770c0165d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 4 Dec 2012 17:45:01 -0500 Subject: SH-3604 WIP --- indra/newview/llappearancemgr.cpp | 108 +++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 30 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 79106318a4..8e5f4b3684 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -186,49 +186,59 @@ void report_fire(const LLUUID& item_id) llinfos << item_id << llendl; } -class LLInventoryCopyMgr: public LLEventTimer +class LLCallAfterInventoryBatchMgr: public LLEventTimer { public: - LLInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, const LLUUID& dst_cat_id, - bool append, const std::string& phase): + LLCallAfterInventoryBatchMgr(const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func, + F32 check_period = 5.0, + F32 retry_after = 30.0, + S32 max_retries = 2 + ): mDstCatID(dst_cat_id), - mAppend(append), - mTrackingPhase(phase), - LLEventTimer(5.0) + mTrackingPhase(phase_name), + mOnCompletionFunc(on_completion_func), + mRetryAfter(retry_after), + mMaxRetries(max_retries), + LLEventTimer(check_period) + { + if (!mTrackingPhase.empty()) + { + selfStartPhase(mTrackingPhase); + } + } + + void addItems(LLInventoryModel::item_array_t& src_items) { for (LLInventoryModel::item_array_t::const_iterator it = src_items.begin(); it != src_items.end(); ++it) { LLViewerInventoryItem* item = *it; - mSrcTimes[item->getUUID()] = LLTimer(); - requestCopy(item->getUUID()); - } - if (!mTrackingPhase.empty()) - { - selfStartPhase(mTrackingPhase); + llassert(item); + addItem(item); } } - void requestCopy(const LLUUID& item_id) + void addItem(LLViewerInventoryItem *item) { - LLViewerInventoryItem *item = gInventory.getItem(item_id); + const LLUUID& item_id = item->getUUID(); if (!item) { - llwarns << "requestCopy item not found " << item_id << llendl; + llwarns << "item not found for " << item_id << llendl; return; } - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - mDstCatID, - std::string(), - make_inventory_func_callback(boost::bind(&LLInventoryCopyMgr::onCopy,this,item->getUUID(),_1)) - ); + if (mSrcTimes.find(item_id) == mSrcTimes.end()) + { + mSrcTimes[item->getUUID()] = LLTimer(); + } + requestOperation(item); } - - void onCopy(const LLUUID& src_id, const LLUUID& dst_id) + + virtual void requestOperation(LLViewerInventoryItem *item) = 0; + + void onOp(const LLUUID& src_id, const LLUUID& dst_id) { LL_DEBUGS("Avatar") << "copied, src_id " << src_id << " to dst_id " << dst_id << " after " << mSrcTimes[src_id].getElapsedTimeF32() << " seconds" << llendl; mSrcTimes.erase(src_id); @@ -245,7 +255,7 @@ public: { selfStopPhase(mTrackingPhase); } - LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mDstCatID), mAppend); + mOnCompletionFunc(); } // virtual @@ -256,18 +266,51 @@ public: if (!all_done) { - llwarns << "possible hang in copy, waiting on " << mSrcTimes.size() << " items" << llendl; + llwarns << "possible hang in operation, waiting on " << mSrcTimes.size() << " items" << llendl; // TODO possibly add retry logic here. } return all_done; } -private: + virtual ~LLCallAfterInventoryBatchMgr() + { + LL_DEBUGS("Avatar") << "ending" << llendl; + } + +protected: std::string mTrackingPhase; std::map mSrcTimes; LLUUID mDstCatID; - bool mAppend; + nullary_func_t mOnCompletionFunc; + F32 mRetryAfter; + S32 mMaxRetries; +}; + +class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr +{ +public: + LLCallAfterInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, + const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func + ): + LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func) + { + addItems(src_items); + } + + virtual void requestOperation(LLViewerInventoryItem *item) + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + mDstCatID, + std::string(), + make_inventory_func_callback(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item->getUUID(),_1)) + ); + } }; class LLWearInventoryCategoryCallback : public LLInventoryCallback @@ -2097,7 +2140,12 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap name); // Create a CopyMgr that will copy items, manage its own destruction - new LLInventoryCopyMgr(*items, new_cat_id, append, std::string("wear_inventory_category_callback")); + new LLCallAfterInventoryCopyMgr( + *items, new_cat_id, std::string("wear_inventory_category_callback"), + boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, + LLAppearanceMgr::getInstance(), + gInventory.getCategory(new_cat_id), + append)); // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); -- cgit v1.2.3 From b43c8afc36a11c34fa76443be85430cac6c72c42 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 4 Dec 2012 14:51:33 -0800 Subject: CHUI-550, CHUI-551 : Fixed : Changed conversation sorting according to designer's desires. --- indra/newview/llconversationmodel.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 728b1a3f4c..0b7c3939df 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -528,12 +528,8 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL { // If both are sessions U32 sort_order = getSortOrderSessions(); - if ((type_a == LLConversationItem::CONV_SESSION_NEARBY) || (type_b == LLConversationItem::CONV_SESSION_NEARBY)) - { - // If one is the nearby session, put nearby session *always* first - return (type_a == LLConversationItem::CONV_SESSION_NEARBY); - } - else if (sort_order == LLConversationFilter::SO_DATE) + + if (sort_order == LLConversationFilter::SO_DATE) { // Sort by time F64 time_a = 0.0; @@ -552,14 +548,22 @@ bool LLConversationSort::operator()(const LLConversationItem* const& a, const LL } // If no time available, we'll default to sort by name at the end of this method } - else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) + else { - if (type_a != type_b) + if ((type_a == LLConversationItem::CONV_SESSION_NEARBY) || (type_b == LLConversationItem::CONV_SESSION_NEARBY)) { - // Lowest types come first. See LLConversationItem definition of types - return (type_a < type_b); + // If one is the nearby session, put nearby session *always* last + return (type_b == LLConversationItem::CONV_SESSION_NEARBY); } + else if (sort_order == LLConversationFilter::SO_SESSION_TYPE) + { + if (type_a != type_b) + { + // Lowest types come first. See LLConversationItem definition of types + return (type_a < type_b); + } // If types are identical, we'll default to sort by name at the end of this method + } } } else -- cgit v1.2.3 From 8642088d65ec340b50661e2a3bf74820ec595010 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 4 Dec 2012 19:23:36 -0800 Subject: CHUI-571: Fixed bug where when the converation floater was torn off and a new im received, the incorrect conversation would be displayed and focused. In order to do this removed the conversation floater panels from being focused immediately when set visible. Also there was a bug when showing the stub panel for torn off conversations. The tab container was not setting the stub panel index properly to 0, which is where the stub panel existed in the tab container's list. This is post code review submit. Will submit another with minor code review changes. --- indra/llui/lltabcontainer.cpp | 3 ++- indra/newview/llfloaterimcontainer.cpp | 14 +++----------- indra/newview/llfloaterimnearbychat.cpp | 1 - indra/newview/llfloaterimsession.cpp | 1 - indra/newview/llfloaterimsessiontab.cpp | 2 +- indra/newview/llimview.cpp | 20 ++++++++++++++++---- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 3c1dfc1184..0dd63c2632 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1559,7 +1559,8 @@ BOOL LLTabContainer::setTab(S32 which) void LLTabContainer::hideAllTabs() { - setCurrentPanelIndex(-1); + + setCurrentPanelIndex(0); for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { (* iter)->mTabPanel->setVisible(FALSE); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..d50581a314 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -546,8 +546,10 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); + setSelectedSession(LLUUID(NULL)); } openNearbyChat(); + selectConversationPair(getSelectedSession(), false); } nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); @@ -571,7 +573,6 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // Now, do the normal multifloater show/hide LLMultiFloater::setVisible(visible); - } void LLFloaterIMContainer::collapseMessagesPane(bool collapse) @@ -1624,22 +1625,13 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, { //Finds the conversation line item to flash using the session_id LLConversationViewSession * widget = dynamic_cast(get_ptr_in_map(mConversationsWidgets,session_id)); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); if (widget) { //Start flash if (is_flashes) { - //Only flash when conversation is not active - if(session_floater - && (!session_floater->isInVisibleChain()) //conversation floater not displayed - || - (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus - - { - widget->getFlashTimer()->startFlashing(); - } + widget->getFlashTimer()->startFlashing(); } //Stop flash else diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a20fce876c..80a41e2f37 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -228,7 +228,6 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible) { removeScreenChat(); } - setFocus(visible); } // virtual diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 212b0df712..cb730c6237 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -629,7 +629,6 @@ void LLFloaterIMSession::setVisible(BOOL visible) } - setFocus(visible); } BOOL LLFloaterIMSession::getVisible() diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d04fa2674d..da25f95ffe 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -60,6 +60,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) { + setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mCommitCallbackRegistrar.add("IMSession.Menu.Action", @@ -124,7 +125,6 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible) { LLFloaterIMSessionTab::addToHost(mSessionID); } - setFocus(visible); } /*virtual*/ diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b6fd3ec9c8..821e62c4e6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -192,12 +192,24 @@ void on_new_message(const LLSD& msg) else if("openconversations" == action) { LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); - if (im_box) + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + //Don't flash and show conversation floater when conversation already active (has focus) + if(session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus + { - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + //Flash line item + if (im_box) + { + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item + } + + //Surface conversations floater + LLFloaterReg::showInstance("im_container"); } - - LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From e1b7153b4782ec4d1f8b028b435e7e4f0cf98dc2 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 5 Dec 2012 17:08:38 +0200 Subject: CHUI-530 Additional fix --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..36eb9435e9 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1599,6 +1599,7 @@ void LLFloaterIMContainer::openNearbyChat() LLConversationViewSession* nearby_chat = dynamic_cast(get_ptr_in_map(mConversationsWidgets,LLUUID())); if (nearby_chat) { + selectConversation(LLUUID()); nearby_chat->setOpen(TRUE); } } -- cgit v1.2.3 From e0b1b063c14081a7c53ab5620db20385e1f2bbbd Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 5 Dec 2012 20:03:15 +0200 Subject: CHUI-577 FIXED "Mute text" and "Block voice" items are added to context menu instead of "Block\unblock" --- indra/newview/llconversationmodel.cpp | 1 + indra/newview/llfloaterimcontainer.cpp | 29 ++++++++++++++++++++-- indra/newview/llfloaterimcontainer.h | 1 + .../skins/default/xui/en/menu_conversation.xml | 11 ++++++-- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0b7c3939df..4328c60b1a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -115,6 +115,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) items.push_back(std::string("share")); items.push_back(std::string("pay")); items.push_back(std::string("block_unblock")); + items.push_back(std::string("MuteText")); if(this->getType() != CONV_SESSION_1_ON_1) { diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8e7edba0c0..a5b93f3692 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -926,7 +926,11 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec } else if ("block_unblock" == command) { - LLAvatarActions::toggleBlock(userID); + toggleMute(userID, LLMute::flagVoiceChat); + } + else if ("mute_unmute" == command) + { + toggleMute(userID, LLMute::flagTextChat); } else if ("selected" == command || "mute_all" == command || "unmute_all" == command) { @@ -1144,8 +1148,12 @@ bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_ve { if ("is_blocked" == item) { - return LLAvatarActions::isBlocked(uuids.front()); + return LLMuteList::getInstance()->isMuted(uuids.front(), LLMute::flagVoiceChat); } + else if (item == "is_muted") + { + return LLMuteList::getInstance()->isMuted(uuids.front(), LLMute::flagTextChat); + } else if ("is_allowed_text_chat" == item) { const LLSpeaker * speakerp = getSpeakerOfSelectedParticipant(getSpeakerMgrForSelectedParticipant()); @@ -1591,6 +1599,23 @@ void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) } } +void LLFloaterIMContainer::toggleMute(const LLUUID& participant_id, U32 flags) +{ + BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); + std::string name; + gCacheName->getFullName(participant_id, name); + LLMute mute(participant_id, name, LLMute::AGENT); + + if (!is_muted) + { + LLMuteList::getInstance()->add(mute, flags); + } + else + { + LLMuteList::getInstance()->remove(mute, flags); + } +} + void LLFloaterIMContainer::openNearbyChat() { // If there's only one conversation in the container and that conversation is the nearby chat diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 1badce0d2d..c9987bffe8 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -150,6 +150,7 @@ private: void moderateVoiceAllParticipants(bool unmute); void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); void toggleAllowTextChat(const LLUUID& participant_uuid); + void toggleMute(const LLUUID& participant_id, U32 flags); void openNearbyChat(); LLButton* mExpandCollapseBtn; diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 908b2c174f..e8265fe482 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -105,14 +105,21 @@ - + + + + -- cgit v1.2.3 From fc000880b40143534c47c475a7a0aba6ab75039e Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 5 Dec 2012 20:47:21 +0200 Subject: CHUI-519 FIXED Do not put offered items into the trash while in Busy / DND mode --- indra/llui/llnotifications.cpp | 3 ++- indra/llui/llnotifications.h | 13 +++++++++++-- indra/newview/llnotificationofferhandler.cpp | 1 + indra/newview/llviewermessage.cpp | 5 ++++- indra/newview/skins/default/xui/en/menu_conversation.xml | 3 ++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 66144671c9..fd9bfec203 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -475,7 +475,8 @@ LLNotification::LLNotification(const LLSDParamAdapter& p) : mCancelled(false), mIgnored(false), mResponderObj(NULL), - mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()) + mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), + mOfferFromAgent(p.offer_from_agent) { if (p.functor.name.isChosen()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 088931858a..372b9ce46f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -316,6 +316,7 @@ public: expiry; Optional context; Optional responder; + Optional offer_from_agent; struct Functor : public LLInitParam::ChoiceBlock { @@ -339,7 +340,8 @@ public: payload("payload"), form_elements("form"), substitutions("substitutions"), - expiry("expiry") + expiry("expiry"), + offer_from_agent("offer_from_agent", false) { time_stamp = LLDate::now(); responder = NULL; @@ -352,7 +354,8 @@ public: payload("payload"), form_elements("form"), substitutions("substitutions"), - expiry("expiry") + expiry("expiry"), + offer_from_agent("offer_from_agent", false) { functor.name = _name; name = _name; @@ -378,6 +381,7 @@ private: LLNotificationFormPtr mForm; void* mResponderObj; // TODO - refactor/remove this field LLNotificationResponderPtr mResponder; + bool mOfferFromAgent; // a reference to the template LLNotificationTemplatePtr mTemplatep; @@ -513,6 +517,11 @@ public: return mTimestamp; } + bool getOfferFromAgent() const + { + return mOfferFromAgent; + } + std::string getType() const; std::string getMessage() const; std::string getFooter() const; diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 91003c7d53..ff5b5e21f7 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -113,6 +113,7 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) p.panel = notify_box; // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; + p.force_show = notification->getOfferFromAgent(); LLScreenChannel* channel = dynamic_cast(mChannel.get()); if(channel) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dc8192105f..ea804508c8 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1971,6 +1971,7 @@ void inventory_offer_handler(LLOfferInfo* info) p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info)); info->mPersist = true; p.name = "UserGiveItem"; + p.offer_from_agent = true; // Prefetch the item into your local inventory. LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); @@ -2738,7 +2739,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Same as closing window info->forceResponse(IOR_DECLINE); } - else if (is_do_not_disturb && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565) + // old logic: busy mode must not affect interaction with objects (STORM-565) + // new logic: inventory offers from in-world objects should be auto-declined (CHUI-519) + else if (is_do_not_disturb && dialog == IM_TASK_INVENTORY_OFFERED) { // Until throttling is implemented, do not disturb mode should reject inventory instead of silently // accepting it. SEE SL-39554 diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index e8265fe482..01ef8ebdb5 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -116,9 +116,10 @@ label="Block Text" layout="topleft" name="MuteText"> - + + Date: Wed, 5 Dec 2012 14:33:30 -0500 Subject: Added back in mesa package for linux builds --- autobuild.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/autobuild.xml b/autobuild.xml index f5ea967b32..82344ebc90 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1452,6 +1452,30 @@ windows + + mesa + + license + mesa + license_file + LICENSES/mesa.txt + name + mesa + platforms + + linux + + archive + + hash + 1f600840463c7327ea17486821425750 + url + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/mesa-7.0-linux-20100930.tar.bz2 + + name + linux + + ndofdev -- cgit v1.2.3 From ffe80818064572a19b52d4f39f0e14538f701275 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 5 Dec 2012 12:40:44 -0800 Subject: CHUI 571: Code review changes, now LLFloaterIMContainer::showStub inlines code for hiding all tab panels and then showing the stub panel. Before the function would call hideAllTabs() --- indra/llui/lltabcontainer.cpp | 12 ------------ indra/llui/lltabcontainer.h | 4 +--- indra/newview/llfloaterimcontainer.cpp | 27 +++++++++++++++++++++++---- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0dd63c2632..91527c68f2 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1556,18 +1556,6 @@ BOOL LLTabContainer::setTab(S32 which) return is_visible; } - -void LLTabContainer::hideAllTabs() -{ - - setCurrentPanelIndex(0); - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - (* iter)->mTabPanel->setVisible(FALSE); - } -} - - BOOL LLTabContainer::selectTabByName(const std::string& name) { LLPanel* panel = getPanelByName(name); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index a9cdf22b16..57862fc626 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -192,7 +192,7 @@ public: BOOL selectTabPanel( LLPanel* child ); BOOL selectTab(S32 which); BOOL selectTabByName(const std::string& title); - void hideAllTabs(); + void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; } BOOL getTabPanelFlashing(LLPanel* child); void setTabPanelFlashing(LLPanel* child, BOOL state); @@ -243,8 +243,6 @@ private: void setTabsHidden(BOOL hidden) { mTabsHidden = hidden; } BOOL getTabsHidden() const { return mTabsHidden; } - - void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; } void scrollPrev() { mScrollPos = llmax(0, mScrollPos-1); } // No wrap void scrollNext() { mScrollPos = llmin(mScrollPos+1, mMaxScrollPos); } // No wrap diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a5b93f3692..23c21d5309 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -516,13 +516,32 @@ void LLFloaterIMContainer::tabClose() } } +//Shows/hides the stub panel when a conversation floater is torn off void LLFloaterIMContainer::showStub(bool stub_is_visible) { - if (stub_is_visible) - { - mTabContainer->hideAllTabs(); - } + S32 tabCount = 0; + LLPanel * tabPanel = NULL; + + if(stub_is_visible) + { + tabCount = mTabContainer->getTabCount(); + + //Hide all tabs even stub + for(S32 i = 0; i < tabCount; ++i) + { + tabPanel = mTabContainer->getPanelByIndex(i); + + if(tabPanel) + { + tabPanel->setVisible(false); + } + } + + //Set the index to the stub panel since we will be showing the stub + mTabContainer->setCurrentPanelIndex(0); + } + //Now show/hide the stub mStubPanel->setVisible(stub_is_visible); } -- cgit v1.2.3 From 480569677cb0cd6b03d2a38a613561d6ef6be059 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Dec 2012 16:38:21 -0500 Subject: SH-3604 WIP - retry mechanism for batch inventory ops, handle either completion or failure --- indra/newview/app_settings/logcontrol.xml | 2 +- indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llappearancemgr.cpp | 196 ++++++++++++++++++++---------- 3 files changed, 147 insertions(+), 62 deletions(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 64122bbb6c..1259039010 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index efb1ccc1cc..4a69e5b356 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4315,6 +4315,17 @@ Value 1.0 + InventoryDebugSimulateOpFailureRate + + Comment + Rate at which we simulate failures of copy/link requests in some operations + Persist + 1 + Type + F32 + Value + 0.0 + InventoryDisplayInbox Comment diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8e5f4b3684..c149f38fcd 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -192,15 +192,20 @@ public: LLCallAfterInventoryBatchMgr(const LLUUID& dst_cat_id, const std::string& phase_name, nullary_func_t on_completion_func, + nullary_func_t on_failure_func, F32 check_period = 5.0, - F32 retry_after = 30.0, + F32 retry_after = 10.0, S32 max_retries = 2 ): mDstCatID(dst_cat_id), mTrackingPhase(phase_name), mOnCompletionFunc(on_completion_func), + mOnFailureFunc(on_failure_func), mRetryAfter(retry_after), mMaxRetries(max_retries), + mPendingRequests(0), + mFailCount(0), + mRetryCount(0), LLEventTimer(check_period) { if (!mTrackingPhase.empty()) @@ -221,6 +226,7 @@ public: } } + // Request or re-request operation for specified item. void addItem(LLViewerInventoryItem *item) { const LLUUID& item_id = item->getUUID(); @@ -229,10 +235,24 @@ public: llwarns << "item not found for " << item_id << llendl; return; } - if (mSrcTimes.find(item_id) == mSrcTimes.end()) + mPendingRequests++; + // On a re-request, this will reset the timer. + mWaitTimes[item_id] = LLTimer(); + if (mRetryCounts.find(item_id) == mRetryCounts.end()) { - mSrcTimes[item->getUUID()] = LLTimer(); + mRetryCounts[item_id] = 0; } + else + { + mRetryCounts[item_id]++; + } + + if (ll_frand()::const_iterator it = mWaitTimes.begin(); + it != mWaitTimes.end();) + { + // Use a copy of iterator because it may be erased/invalidated. + std::map::const_iterator curr_it = it; + ++it; + + F32 time_waited = curr_it->second.getElapsedTimeF32(); + S32 retries = mRetryCounts[curr_it->first]; + if (time_waited > mRetryAfter) + { + if (retries < mMaxRetries) + { + LL_DEBUGS("Avatar") << "Waited " << time_waited << + " for " << curr_it->first << ", retrying" << llendl; + mRetryCount++; + addItem(gInventory.getItem(curr_it->first)); + } + else + { + llwarns << "Giving up on " << curr_it->first << " after too many retries" << llendl; + mWaitTimes.erase(curr_it); + mFailCount++; + } + } + if (mWaitTimes.empty()) + { + onCompletionOrFailure(); + } + } } return all_done; } + void reportStats() + { + LL_DEBUGS("Avatar") << "mFailCount: " << mFailCount << llendl; + LL_DEBUGS("Avatar") << "mRetryCount: " << mRetryCount << llendl; + LL_DEBUGS("Avatar") << "Times: n " << mTimeStats.getCount() << " min " << mTimeStats.getMinValue() << " max " << mTimeStats.getMaxValue() << llendl; + LL_DEBUGS("Avatar") << "Mean " << mTimeStats.getMean() << " stddev " << mTimeStats.getStdDev() << llendl; + } + virtual ~LLCallAfterInventoryBatchMgr() { - LL_DEBUGS("Avatar") << "ending" << llendl; + LL_DEBUGS("Avatar") << "deleting" << llendl; } protected: std::string mTrackingPhase; - std::map mSrcTimes; + std::map mWaitTimes; + std::map mRetryCounts; LLUUID mDstCatID; nullary_func_t mOnCompletionFunc; + nullary_func_t mOnFailureFunc; F32 mRetryAfter; S32 mMaxRetries; + S32 mPendingRequests; + S32 mFailCount; + S32 mRetryCount; + LLViewerStats::StatsAccumulator mTimeStats; }; class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr @@ -293,9 +388,10 @@ public: LLCallAfterInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, const LLUUID& dst_cat_id, const std::string& phase_name, - nullary_func_t on_completion_func + nullary_func_t on_completion_func, + nullary_func_t on_failure_func ): - LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func) + LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) { addItems(src_items); } @@ -313,56 +409,32 @@ public: } }; -class LLWearInventoryCategoryCallback : public LLInventoryCallback +class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr { -public: - LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append) - { - mCatID = cat_id; - mAppend = append; - - LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; - - selfStartPhase("wear_inventory_category_callback"); - } - void fire(const LLUUID& item_id) + LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, + const LLUUID& dst_cat_id, + const std::string& phase_name, + nullary_func_t on_completion_func, + nullary_func_t on_failure_func + ): + LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) { - /* - * Do nothing. We only care about the destructor - * - * The reason for this is that this callback is used in a hack where the - * same callback is given to dozens of items, and the destructor is called - * after the last item has fired the event and dereferenced it -- if all - * the events actually fire! - */ - LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL; + addItems(src_items); } - -protected: - ~LLWearInventoryCategoryCallback() + + virtual void requestOperation(LLViewerInventoryItem *item) { - LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL; - - selfStopPhase("wear_inventory_category_callback"); - - // Is the destructor called by ordinary dereference, or because the app's shutting down? - // If the inventory callback manager goes away, we're shutting down, no longer want the callback. - if( LLInventoryCallbackManager::is_instantiated() ) - { - LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend); - } - else - { - llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; - } + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + mDstCatID, + item->getName(), + item->LLInventoryItem::getDescription(), + LLAssetType::AT_LINK, + make_inventory_func_callback( + boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item->getUUID(),_1))); } - -private: - LLUUID mCatID; - bool mAppend; }; - //Inventory callback updating "dirty" state when destroyed class LLUpdateDirtyState: public LLInventoryCallback { @@ -2145,7 +2217,8 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, LLAppearanceMgr::getInstance(), gInventory.getCategory(new_cat_id), - append)); + append), + boost::function()); // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); @@ -2167,6 +2240,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego if ( !LLInventoryCallbackManager::is_instantiated() ) { + // shutting down, ignore. return; } -- cgit v1.2.3 From 7d419d59009d429c8d9480adf3ae163d5c688126 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Dec 2012 16:39:23 -0500 Subject: SH-3604 WIP - backed out logcontrol.xml change --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 1259039010..64122bbb6c 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - Avatar -- cgit v1.2.3 From 1004eff4a29371719f98eae378f6ecd7dc6be225 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Wed, 5 Dec 2012 17:29:52 -0500 Subject: Linux Viewer build fixes. * Removed no longer used unpack_bufsize from bitpack_test.cpp * Added llviewertexture_stub.cpp to the newview tests directory to fix llworldmap_test.cpp and llworldmipmap_test.cpp linker errors. --- indra/llcommon/tests/bitpack_test.cpp | 1 - indra/newview/CMakeLists.txt | 9 ++++++++ indra/newview/tests/llviewertexture_stub.cpp | 32 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 indra/newview/tests/llviewertexture_stub.cpp diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp index 49cae16400..afc0c18cd0 100644 --- a/indra/llcommon/tests/bitpack_test.cpp +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -94,7 +94,6 @@ namespace tut ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]); bitunpack.bitUnpack(unpackbuffer, 8*4); // Life ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); - ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize); } // U32 packing diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85060a140..e64697982f 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2060,6 +2060,15 @@ if (LL_TESTS) llworldmipmap.cpp ) + set_source_files_properties( + llworldmap.cpp + llworldmipmap.cpp + PROPERTIES + LL_TEST_ADDITIONAL_SOURCE_FILES + tests/llviewertexture_stub.cpp + #llviewertexturelist.cpp + ) + set_source_files_properties( lltranslate.cpp PROPERTIES diff --git a/indra/newview/tests/llviewertexture_stub.cpp b/indra/newview/tests/llviewertexture_stub.cpp new file mode 100644 index 0000000000..90e76a8f83 --- /dev/null +++ b/indra/newview/tests/llviewertexture_stub.cpp @@ -0,0 +1,32 @@ +/** + * @file llviewertexture_stub.cpp + * @brief stub class to allow unit testing + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../llviewertexture.h" + +void LLViewerTexture::setBoostLevel(int level) +{ +} -- cgit v1.2.3 From bfa3bc0059eef269ac7a77cd28443898cea1fb19 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Dec 2012 17:58:35 -0500 Subject: Possible fix for TC build failure --- indra/newview/app_settings/logcontrol.xml | 2 +- indra/newview/llappearancemgr.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 64122bbb6c..1259039010 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c149f38fcd..656949a9bb 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -319,11 +319,11 @@ public: if (!mWaitTimes.empty()) { llwarns << "still waiting on " << mWaitTimes.size() << " items" << llendl; - for (std::map::const_iterator it = mWaitTimes.begin(); + for (std::map::iterator it = mWaitTimes.begin(); it != mWaitTimes.end();) { // Use a copy of iterator because it may be erased/invalidated. - std::map::const_iterator curr_it = it; + std::map::iterator curr_it = it; ++it; F32 time_waited = curr_it->second.getElapsedTimeF32(); -- cgit v1.2.3 From 2af1f6dbdfdef0a7b7b7c4f40ac33c8d93869b1f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 5 Dec 2012 18:04:33 -0500 Subject: removed yet another unintended commit of logcontrol.xml --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 1259039010..64122bbb6c 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - Avatar -- cgit v1.2.3 From a4a2cc62c3411f0391b90d9720a13b49b0e123ef Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 5 Dec 2012 16:08:17 -0800 Subject: CHUI-509 : Fixed : Add params to inventory widgets to control font colors (required for library items and links). --- indra/llui/llfolderviewitem.cpp | 39 ++++++++++++++++++------------------- indra/llui/llfolderviewitem.h | 10 +++++++--- indra/newview/llinventorybridge.cpp | 5 +++++ indra/newview/llinventorybridge.h | 1 + indra/newview/llinventorypanel.cpp | 24 +++++++++++++++++++++++ indra/newview/llinventorypanel.h | 7 +++++++ 6 files changed, 63 insertions(+), 23 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9b54a7a467..60a6d3e3ea 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -47,16 +47,14 @@ static LLDefaultChildRegistry::Register r("folder_view_item"); // statics std::map LLFolderViewItem::sFonts; // map of styles to fonts +bool LLFolderViewItem::sColorSetInitialized = false; LLUIColor LLFolderViewItem::sFgColor; LLUIColor LLFolderViewItem::sHighlightBgColor; -LLUIColor LLFolderViewItem::sHighlightFgColor; LLUIColor LLFolderViewItem::sFocusOutlineColor; LLUIColor LLFolderViewItem::sMouseOverColor; LLUIColor LLFolderViewItem::sFilterBGColor; LLUIColor LLFolderViewItem::sFilterTextColor; LLUIColor LLFolderViewItem::sSuffixColor; -LLUIColor LLFolderViewItem::sLibraryColor; -LLUIColor LLFolderViewItem::sLinkColor; LLUIColor LLFolderViewItem::sSearchStatusColor; // only integers can be initialized in header @@ -106,6 +104,8 @@ LLFolderViewItem::Params::Params() item_top_pad("item_top_pad"), creation_date(), allow_open("allow_open", true), + font_color("font_color"), + font_highlight_color("font_highlight_color"), left_pad("left_pad", 0), icon_pad("icon_pad", 0), icon_width("icon_width", 0), @@ -113,7 +113,7 @@ LLFolderViewItem::Params::Params() text_pad_right("text_pad_right", 0), arrow_size("arrow_size", 0), max_folder_item_overlap("max_folder_item_overlap", 0) -{} +{ } // Default constructor LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) @@ -137,6 +137,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mViewModelItem(p.listener), mIsMouseOverTitle(false), mAllowOpen(p.allow_open), + mFontColor(p.font_color), + mFontHighlightColor(p.font_highlight_color), mLeftPad(p.left_pad), mIconPad(p.icon_pad), mIconWidth(p.icon_width), @@ -145,17 +147,18 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mArrowSize(p.arrow_size), mMaxFolderItemOverlap(p.max_folder_item_overlap) { - sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); - sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); - sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); - sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + if (!sColorSetInitialized) + { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } if (mViewModelItem) { @@ -785,10 +788,6 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x) { - //TODO RN: implement this in terms of getColor() - //if (highlight_link) color = sLinkColor; - //if (gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; - //--------------------------------------------------------------------------------// // Draw the actual label text // @@ -857,7 +856,7 @@ void LLFolderViewItem::draw() box_image->draw(box_rect, sFilterBGColor); } - LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; + LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; drawLabel(font, text_left, y, color, right_x); //--------------------------------------------------------------------------------// diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 2e633a39e5..f33f21c8f8 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -61,6 +61,9 @@ public: Optional creation_date; Optional allow_open; + Optional font_color; + Optional font_highlight_color; + Optional left_pad, icon_pad, icon_width, @@ -116,19 +119,20 @@ protected: mIsMouseOverTitle, mAllowOpen, mSelectPending; + + LLUIColor mFontColor; + LLUIColor mFontHighlightColor; // For now assuming all colors are the same in derived classes. + static bool sColorSetInitialized; static LLUIColor sFgColor; static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; - static LLUIColor sHighlightFgColor; static LLUIColor sFocusOutlineColor; static LLUIColor sMouseOverColor; static LLUIColor sFilterBGColor; static LLUIColor sFilterTextColor; static LLUIColor sSuffixColor; - static LLUIColor sLibraryColor; - static LLUIColor sLinkColor; static LLUIColor sSearchStatusColor; // this is an internal method used for adding items to folders. A diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 73631f4ba8..cf8253ca4d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -255,6 +255,11 @@ BOOL LLInvFVBridge::isLink() const return mIsLink; } +BOOL LLInvFVBridge::isLibraryItem() const +{ + return gInventory.isObjectDescendentOf(getUUID(),gInventory.getLibraryRootFolderID()); +} + /*virtual*/ /** * @brief Adds this item into clipboard storage diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 5e96f00920..5c6cf0f0f0 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -107,6 +107,7 @@ public: virtual BOOL isItemMovable() const; virtual BOOL isItemInTrash() const; virtual BOOL isLink() const; + virtual BOOL isLibraryItem() const; //virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector& batch); virtual void move(LLFolderViewModelItem* new_parent_bridge) {} diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 098a44b9d8..81e7f166e1 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -57,6 +57,15 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER; +// statics +bool LLInventoryPanel::sColorSetInitialized = false; +LLUIColor LLInventoryPanel::sDefaultColor; +LLUIColor LLInventoryPanel::sDefaultHighlightColor; +LLUIColor LLInventoryPanel::sLibraryColor; +LLUIColor LLInventoryPanel::sLinkColor; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver // @@ -140,6 +149,15 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; + if (!sColorSetInitialized) + { + sDefaultColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sDefaultHighlightColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); + sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } + // context menu callbacks mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); @@ -705,6 +723,9 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br params.listener = bridge; params.tool_tip = params.name; + params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); + params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); + return LLUICtrlFactory::create(params); } @@ -718,6 +739,9 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; + + params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); + params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); return LLUICtrlFactory::create(params); } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index c4f3c1b47d..9639086c11 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -275,6 +275,13 @@ protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); + // Specific inventory colors + static bool sColorSetInitialized; + static LLUIColor sDefaultColor; + static LLUIColor sDefaultHighlightColor; + static LLUIColor sLibraryColor; + static LLUIColor sLinkColor; + LLFolderViewItem* buildNewViews(const LLUUID& id); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; -- cgit v1.2.3 From 3a49beed0e96a797a6d663bcae5e932437ca3661 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 5 Dec 2012 20:25:46 -0800 Subject: CHUI-580 : WIP : Change the display name cache system, deprecating the old protocol and using the cap (People API) whenever available. Still has occurence of Resident as last name to clean up. --- indra/llcommon/llavatarname.cpp | 69 ++++++++++++++++++++++++++++++- indra/llcommon/llavatarname.h | 57 ++++++++++++++++++------- indra/llmessage/llavatarnamecache.cpp | 56 ++++++++----------------- indra/llmessage/llavatarnamecache.h | 2 + indra/llmessage/llcachename.cpp | 6 ++- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llurlentry.cpp | 4 +- indra/newview/llavataractions.cpp | 16 +++---- indra/newview/llavatariconctrl.cpp | 2 +- indra/newview/llavatarlist.cpp | 9 ++-- indra/newview/llavatarlistitem.cpp | 4 +- indra/newview/llcallingcard.cpp | 6 +-- indra/newview/llchathistory.cpp | 14 +++---- indra/newview/llconversationmodel.cpp | 4 +- indra/newview/llfavoritesbar.cpp | 10 ++--- indra/newview/llfloateravatarpicker.cpp | 12 ++---- indra/newview/llfloaterdisplayname.cpp | 10 ++--- indra/newview/llfloaterimnearbychat.cpp | 2 +- indra/newview/llfloaterscriptlimits.cpp | 15 +------ indra/newview/llfloatersellland.cpp | 2 +- indra/newview/llfloatertopobjects.cpp | 14 ++----- indra/newview/llfloatervoicevolume.cpp | 2 +- indra/newview/llfriendcard.cpp | 2 +- indra/newview/llimview.cpp | 20 +++------ indra/newview/llinspectavatar.cpp | 6 +-- indra/newview/llinventorybridge.cpp | 5 +-- indra/newview/llnamelistctrl.cpp | 4 +- indra/newview/llpanelblockedlist.cpp | 2 +- indra/newview/llpanelgroupinvite.cpp | 4 +- indra/newview/llpanelgroupnotices.cpp | 5 +-- indra/newview/llpanelgrouproles.cpp | 4 +- indra/newview/llparticipantlist.cpp | 2 +- indra/newview/lltoastgroupnotifypanel.cpp | 6 +-- indra/newview/lltoolpie.cpp | 3 +- indra/newview/llviewerdisplayname.cpp | 6 +-- indra/newview/llviewermenu.cpp | 6 +-- indra/newview/llviewermessage.cpp | 15 ++----- indra/newview/llvoavatar.cpp | 24 +++++------ indra/newview/llvoicevivox.cpp | 4 +- 39 files changed, 224 insertions(+), 212 deletions(-) diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 3206843bf4..b49e6a7aac 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -30,6 +30,7 @@ #include "llavatarname.h" #include "lldate.h" +#include "llframetimer.h" #include "llsd.h" // Store these in pre-built std::strings to avoid memory allocations in @@ -42,6 +43,8 @@ static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default"); static const std::string DISPLAY_NAME_EXPIRES("display_name_expires"); static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update"); +bool LLAvatarName::sUseDisplayNames = true; + LLAvatarName::LLAvatarName() : mUsername(), mDisplayName(), @@ -61,6 +64,17 @@ bool LLAvatarName::operator<(const LLAvatarName& rhs) const return mUsername < rhs.mUsername; } +//static +void LLAvatarName::setUseDisplayNames(bool use) +{ + sUseDisplayNames = use; +} +//static +bool LLAvatarName::useDisplayNames() +{ + return sUseDisplayNames; +} + LLSD LLAvatarName::asLLSD() const { LLSD sd; @@ -85,6 +99,33 @@ void LLAvatarName::fromLLSD(const LLSD& sd) mExpires = expires.secondsSinceEpoch(); LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE]; mNextUpdate = next_update.secondsSinceEpoch(); + + // Some avatars don't have explicit display names set. Force a legible display name here. + if (mDisplayName.empty()) + { + mDisplayName = mUsername; + } +} + +void LLAvatarName::fromString(const std::string& full_name, F64 expires) +{ + mDisplayName = full_name; + std::string::size_type index = full_name.find(' '); + if (index != std::string::npos) + { + mLegacyFirstName = full_name.substr(0, index); + mLegacyLastName = full_name.substr(index+1); + mUsername = mLegacyFirstName + " " + mLegacyLastName; + } + else + { + mLegacyFirstName = full_name; + mLegacyLastName = ""; + mUsername = full_name; + } + mIsDisplayNameDefault = true; + mIsTemporaryName = true; + mExpires = LLFrameTimer::getTotalSeconds() + expires; } std::string LLAvatarName::getCompleteName() const @@ -104,9 +145,22 @@ std::string LLAvatarName::getCompleteName() const return name; } -std::string LLAvatarName::getLegacyName() const +std::string LLAvatarName::getDisplayName() const +{ + if (sUseDisplayNames) + { + return mDisplayName; + } + else + { + return getUserName(); + } +} + +std::string LLAvatarName::getUserName() const { - if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled? + // If we cannot create a user name from the legacy strings, use the display name + if (mLegacyFirstName.empty() && mLegacyLastName.empty()) { return mDisplayName; } @@ -118,3 +172,14 @@ std::string LLAvatarName::getLegacyName() const name += mLegacyLastName; return name; } + +void LLAvatarName::dump() const +{ + llinfos << "Merov debug : display = " << mDisplayName << ", user = " << mUsername << ", complete = " << getCompleteName() << ", legacy = " << getUserName() << " first = " << mLegacyFirstName << " last = " << mLegacyLastName << llendl; + LL_DEBUGS("AvNameCache") << "LLAvatarName: " + << "user '" << mUsername << "' " + << "display '" << mDisplayName << "' " + << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds" + << LL_ENDL; +} + diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index ba258d6d52..cf9eb27b03 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -43,19 +43,50 @@ public: void fromLLSD(const LLSD& sd); + // Used only in legacy mode when the display name capability is not provided server side + void fromString(const std::string& full_name, F64 expires = 0.0f); + + static void setUseDisplayNames(bool use); + static bool useDisplayNames(); + + // Name is valid if not temporary and not yet expired + bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); } + + // + bool isDisplayNameDefault() const { return mIsDisplayNameDefault; } + // For normal names, returns "James Linden (james.linden)" // When display names are disabled returns just "James Linden" std::string getCompleteName() const; - - // Returns "James Linden" or "bobsmith123 Resident" for backwards - // compatibility with systems like voice and muting - // *TODO: Eliminate this in favor of username only - std::string getLegacyName() const; - + + // "José Sanchez" or "James Linden", UTF-8 encoded Unicode + // Takes the display name preference into account. This is truly the name that should + // be used for all UI where an avatar name has to be used unless we truly want something else (rare) + std::string getDisplayName() const; + + // Returns "James Linden" or "bobsmith123 Resident" + // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name + // Also used for backwards compatibility with systems like voice and muting + std::string getUserName() const; + + // Debug print of the object + void dump() const; + + // Names can change, so need to keep track of when name was + // last checked. + // Unix time-from-epoch seconds for efficiency + F64 mExpires; + + // You can only change your name every N hours, so record + // when the next update is allowed + // Unix time-from-epoch seconds + F64 mNextUpdate; + +private: // "bobsmith123" or "james.linden", US-ASCII only std::string mUsername; - // "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode + // "José Sanchez" or "James Linden", UTF-8 encoded Unicode // Contains data whether or not user has explicitly set // a display name; may duplicate their username. std::string mDisplayName; @@ -81,15 +112,9 @@ public: // shown in UI, but are not serialized. bool mIsTemporaryName; - // Names can change, so need to keep track of when name was - // last checked. - // Unix time-from-epoch seconds for efficiency - F64 mExpires; - - // You can only change your name every N hours, so record - // when the next update is allowed - // Unix time-from-epoch seconds - F64 mNextUpdate; + // Global flag indicating if display name should be used or not + // This will affect the output of the high level "get" methods + static bool sUseDisplayNames; }; #endif diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 700525e1fa..329871d8eb 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -43,10 +43,6 @@ namespace LLAvatarNameCache { use_display_name_signal_t mUseDisplayNamesSignal; - // Manual override for display names - can disable even if the region - // supports it. - bool sUseDisplayNames = true; - // Cache starts in a paused state until we can determine if the // current region supports display names. bool sRunning = false; @@ -209,17 +205,8 @@ public: // Use expiration time from header av_name.mExpires = expires; - // Some avatars don't have explicit display names set - if (av_name.mDisplayName.empty()) - { - av_name.mDisplayName = av_name.mUsername; - } - - LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << " " - << "user '" << av_name.mUsername << "' " - << "display '" << av_name.mDisplayName << "' " - << "expires in " << expires - now << " seconds" - << LL_ENDL; + LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL; + av_name.dump(); // cache it and fire signals LLAvatarNameCache::processName(agent_id, av_name, true); @@ -291,12 +278,9 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) LLAvatarNameCache::sPendingQueue.erase(agent_id); LLAvatarName& av_name = existing->second; - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " - << agent_id - << "user '" << av_name.mUsername << "' " - << "display '" << av_name.mDisplayName << "' " - << "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds" - << LL_ENDL; + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL; + av_name.dump(); + av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest. } } @@ -476,7 +460,7 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr) const LLUUID& agent_id = it->first; const LLAvatarName& av_name = it->second; // Do not write temporary or expired entries to the stored cache - if (!av_name.mIsTemporaryName && av_name.mExpires >= max_unrefreshed) + if (av_name.isValidName(max_unrefreshed)) { // key must be a string agents[agent_id.asString()] = av_name.asLLSD(); @@ -513,7 +497,7 @@ void LLAvatarNameCache::idle() if (!sAskQueue.empty()) { - if (useDisplayNames()) + if (hasNameLookupURL()) { requestNamesViaCapability(); } @@ -565,7 +549,7 @@ void LLAvatarNameCache::eraseUnrefreshed() { const LLUUID& agent_id = it->first; LL_DEBUGS("AvNameCache") << agent_id - << " user '" << av_name.mUsername << "' " + << " user '" << av_name.getUserName() << "' " << "expired " << now - av_name.mExpires << " secs ago" << LL_ENDL; sCache.erase(it++); @@ -583,14 +567,12 @@ void LLAvatarNameCache::buildLegacyName(const std::string& full_name, LLAvatarName* av_name) { llassert(av_name); - av_name->mUsername = ""; - av_name->mDisplayName = full_name; - av_name->mIsDisplayNameDefault = true; - av_name->mIsTemporaryName = true; - av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; + av_name->fromString(full_name,TEMP_CACHE_ENTRY_LIFETIME); LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName " << full_name << LL_ENDL; + // DEBUG ONLY!!! DO NOT COMMIT!!! + av_name->dump(); } // fills in av_name if it has it in the cache, even if expired (can check expiry time) @@ -600,7 +582,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (sRunning) { // ...only do immediate lookups when cache is running - if (useDisplayNames()) + if (hasNameLookupURL()) { // ...use display names cache std::map::iterator it = sCache.find(agent_id); @@ -662,7 +644,7 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag if (sRunning) { // ...only do immediate lookups when cache is running - if (useDisplayNames()) + if (hasNameLookupURL()) { // ...use new cache std::map::iterator it = sCache.find(agent_id); @@ -720,20 +702,16 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag void LLAvatarNameCache::setUseDisplayNames(bool use) { - if (use != sUseDisplayNames) + if (use != LLAvatarName::useDisplayNames()) { - sUseDisplayNames = use; - // flush our cache - sCache.clear(); - + LLAvatarName::setUseDisplayNames(use); mUseDisplayNamesSignal(); } } -bool LLAvatarNameCache::useDisplayNames() +void LLAvatarNameCache::flushCache() { - // Must be both manually set on and able to look up names. - return sUseDisplayNames && !sNameLookupURL.empty(); + sCache.clear(); } void LLAvatarNameCache::erase(const LLUUID& agent_id) diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 79f170f7c8..e172601432 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -81,6 +81,8 @@ namespace LLAvatarNameCache void setUseDisplayNames(bool use); bool useDisplayNames(); + void flushCache(); + void erase(const LLUUID& agent_id); /// Provide some fallback for agents that return errors diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 479efabb5f..da07c9ae42 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -524,6 +524,7 @@ std::string LLCacheName::cleanFullName(const std::string& full_name) } //static +// Transform hard-coded name provided by server to a more legible username std::string LLCacheName::buildUsername(const std::string& full_name) { // rare, but handle hard-coded error names returned from server @@ -549,8 +550,9 @@ std::string LLCacheName::buildUsername(const std::string& full_name) return username; } - // if the input wasn't a correctly formatted legacy name just return it unchanged - return full_name; + // if the input wasn't a correctly formatted legacy name, just return it + // cleaned up from a potential terminal "Resident" + return cleanFullName(full_name); } //static diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 3e0653e9a4..7ed7042aff 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1832,7 +1832,7 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) { LLAvatarName av_name; LLAvatarNameCache::get(LLUUID(id), &av_name); - name = av_name.getLegacyName(); + name = av_name.getUserName(); } LLUrlAction::copyURLToClipboard(name); } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index a9e8fbb4e4..fd2635c73a 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -597,7 +597,7 @@ LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName() std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name) { - return avatar_name.mDisplayName; + return avatar_name.getDisplayName(); } // @@ -613,7 +613,7 @@ LLUrlEntryAgentUserName::LLUrlEntryAgentUserName() std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name) { - return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername; + return avatar_name.getUserName(); } // diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 1969a0bc5f..59b862503c 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -135,7 +135,7 @@ void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids) LLAvatarName av_name; if(LLAvatarNameCache::get(agent_id, &av_name)) { - args["NAME"] = av_name.mDisplayName; + args["NAME"] = av_name.getDisplayName(); } msgType = "RemoveFromFriends"; @@ -180,7 +180,7 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids) static void on_avatar_name_cache_start_im(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.mDisplayName; + std::string name = av_name.getDisplayName(); LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id); if (session_id != LLUUID::null) { @@ -215,7 +215,7 @@ void LLAvatarActions::endIM(const LLUUID& id) static void on_avatar_name_cache_start_call(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string name = av_name.mDisplayName; + std::string name = av_name.getDisplayName(); LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true); if (session_id != LLUUID::null) { @@ -315,11 +315,7 @@ static const char* get_profile_floater_name(const LLUUID& avatar_id) static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string username = av_name.mUsername; - if (username.empty()) - { - username = LLCacheName::buildUsername(av_name.mDisplayName); - } + std::string username = av_name.getUserName(); llinfos << "opening web profile for " << username << llendl; std::string url = getProfileURL(username); @@ -379,7 +375,7 @@ void LLAvatarActions::showOnMap(const LLUUID& id) return; } - gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName); + gFloaterWorldMap->trackAvatar(id, av_name.getDisplayName()); LLFloaterReg::showInstance("world_map"); } @@ -709,7 +705,7 @@ void LLAvatarActions::buildResidentsString(std::vector avatar_name const std::string& separator = LLTrans::getString("words_separator"); for (std::vector::const_iterator it = avatar_names.begin(); ; ) { - residents_string.append((*it).mDisplayName); + residents_string.append((*it).getDisplayName()); if (++it == avatar_names.end()) { break; diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b7278d4a3a..0db38c947c 100755 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -318,7 +318,7 @@ void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarN { // Most avatar icon controls are next to a UI element that shows // a display name, so only show username. - mFullName = av_name.mUsername; + mFullName = av_name.getUserName(); if (mDrawTooltip) { diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 771419f60a..e54e47180f 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -278,7 +278,7 @@ void LLAvatarList::refresh() LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!have_filter || findInsensitive(av_name.mDisplayName, mNameFilter)) + if (!have_filter || findInsensitive(av_name.getDisplayName(), mNameFilter)) { if (nadded >= ADD_LIMIT) { @@ -296,8 +296,9 @@ void LLAvatarList::refresh() } else { + std::string display_name = av_name.getDisplayName(); addNewItem(buddy_id, - av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName, + display_name.empty() ? waiting_str : display_name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); } @@ -325,7 +326,7 @@ void LLAvatarList::refresh() const LLUUID& buddy_id = it->asUUID(); LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!findInsensitive(av_name.mDisplayName, mNameFilter)) + if (!findInsensitive(av_name.getDisplayName(), mNameFilter)) { removeItemByUUID(buddy_id); modified = true; @@ -398,7 +399,7 @@ bool LLAvatarList::filterHasMatches() // If name has not been loaded yet we consider it as a match. // When the name will be loaded the filter will be applied again(in refresh()). - if (have_name && !findInsensitive(av_name.mDisplayName, mNameFilter)) + if (have_name && !findInsensitive(av_name.getDisplayName(), mNameFilter)) { continue; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 7ff1b39573..84e177d4a4 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -449,8 +449,8 @@ void LLAvatarListItem::setNameInternal(const std::string& name, const std::strin void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name) { - setAvatarName(av_name.mDisplayName); - setAvatarToolTip(av_name.mUsername); + setAvatarName(av_name.getDisplayName()); + setAvatarToolTip(av_name.getUserName()); //requesting the list to resort notifyParent(LLSD().with("sort", LLSD())); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 60d60abd45..9a295faa73 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -723,7 +723,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Popup a notify box with online status of this agent // Use display name only because this user is your friend LLSD args; - args["NAME"] = av_name.mDisplayName; + args["NAME"] = av_name.getDisplayName(); args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); LLNotificationPtr notification; @@ -869,7 +869,7 @@ bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship { LLAvatarName av_name; LLAvatarNameCache::get( buddy_id, &av_name); - buddy_map_t::value_type value(av_name.mDisplayName, buddy_id); + buddy_map_t::value_type value(av_name.getDisplayName(), buddy_id); if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) { mMappable.insert(value); @@ -892,7 +892,7 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud { LLAvatarName av_name; LLAvatarNameCache::get(buddy_id, &av_name); - mFullName = av_name.mDisplayName; + mFullName = av_name.getDisplayName(); buddy_map_t::value_type value(mFullName, buddy_id); if(buddy->isOnline()) { diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index a33bd88273..3e25d9c457 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -553,15 +553,15 @@ private: void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - mFrom = av_name.mDisplayName; + mFrom = av_name.getDisplayName(); LLTextBox* user_name = getChild("user_name"); - user_name->setValue( LLSD(av_name.mDisplayName ) ); - user_name->setToolTip( av_name.mUsername ); + user_name->setValue( LLSD(av_name.getDisplayName() ) ); + user_name->setToolTip( av_name.getUserName() ); if (gSavedSettings.getBOOL("NameTagShowUsernames") && - LLAvatarNameCache::useDisplayNames() && - !av_name.mIsDisplayNameDefault) + av_name.useDisplayNames() && + !av_name.isDisplayNameDefault()) { LLStyle::Params style_params_name; LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor"); @@ -569,9 +569,9 @@ private: style_params_name.font.name("SansSerifSmall"); style_params_name.font.style("NORMAL"); style_params_name.readonly_color(userNameColor); - user_name->appendText(" - " + av_name.mUsername, FALSE, style_params_name); + user_name->appendText(" - " + av_name.getUserName(), FALSE, style_params_name); } - setToolTip( av_name.mUsername ); + setToolTip( av_name.getUserName() ); // name might have changed, update width updateMinUserNameWidth(); } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 728b1a3f4c..76c422f34d 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -443,8 +443,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); - mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + mName = av_name.getUserName(); + mDisplayName = av_name.getDisplayName(); mNeedsRefresh = true; if(mParent != NULL) { diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index c68577db75..ff0e01a200 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1520,8 +1520,8 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; - fav_llsd[av_name.getLegacyName()] = user_llsd; + lldebugs << "Saved favorites for " << av_name.getUserName() << llendl; + fav_llsd[av_name.getUserName()] = user_llsd; llofstream file; file.open(filename); @@ -1539,10 +1539,10 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() LLAvatarName av_name; LLAvatarNameCache::get( gAgentID, &av_name ); - lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; - if (fav_llsd.has(av_name.getLegacyName())) + lldebugs << "Removed favorites for " << av_name.getUserName() << llendl; + if (fav_llsd.has(av_name.getUserName())) { - fav_llsd.erase(av_name.getLegacyName()); + fav_llsd.erase(av_name.getUserName()); } llofstream out_file; diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 6ada809cdb..f7dd4a4a6b 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -307,9 +307,9 @@ void LLFloaterAvatarPicker::populateNearMe() else { element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = av_name.mDisplayName; + element["columns"][0]["value"] = av_name.getDisplayName(); element["columns"][1]["column"] = "username"; - element["columns"][1]["value"] = av_name.mUsername; + element["columns"][1]["value"] = av_name.getUserName(); sAvatarNameMap[av] = av_name; } @@ -505,9 +505,7 @@ void LLFloaterAvatarPicker::find() LLViewerRegion* region = gAgent.getRegion(); url = region->getCapability("AvatarPickerSearch"); // Prefer use of capabilities to search on both SLID and display name - // but allow display name search to be manually turned off for test - if (!url.empty() - && LLAvatarNameCache::useDisplayNames()) + if (!url.empty()) { // capability urls don't end in '/', but we need one to parse // query parameters correctly @@ -679,9 +677,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* found_one = TRUE; LLAvatarName av_name; - av_name.mLegacyFirstName = first_name; - av_name.mLegacyLastName = last_name; - av_name.mDisplayName = avatar_name; + av_name.fromString(avatar_name); const LLUUID& agent_id = avatar_id; sAvatarNameMap[agent_id] = av_name; diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp index ac8f107928..be1ee77152 100644 --- a/indra/newview/llfloaterdisplayname.cpp +++ b/indra/newview/llfloaterdisplayname.cpp @@ -164,10 +164,9 @@ void LLFloaterDisplayName::onCancel() void LLFloaterDisplayName::onReset() { - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarNameCache::hasNameLookupURL()) { - LLViewerDisplayName::set("", - boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); + LLViewerDisplayName::set("",boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); } else { @@ -199,10 +198,9 @@ void LLFloaterDisplayName::onSave() return; } - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarNameCache::hasNameLookupURL()) { - LLViewerDisplayName::set(display_name_utf8, - boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); + LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); } else { diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index a20fce876c..24b0355fca 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -545,7 +545,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS LLAvatarName av_name; LLAvatarNameCache::get(chat.mFromID, &av_name); - if (!av_name.mIsDisplayNameDefault) + if (!av_name.isDisplayNameDefault()) { from_name = av_name.getCompleteName(); } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index a50907601c..8d8bba7b17 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -602,15 +602,7 @@ void LLPanelScriptLimitsRegionMemory::onNameCache( return; } - std::string name; - if (LLAvatarNameCache::useDisplayNames()) - { - name = LLCacheName::buildUsername(full_name); - } - else - { - name = full_name; - } + std::string name = LLCacheName::buildUsername(full_name); std::vector::iterator id_itor; for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) @@ -713,10 +705,7 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) else { name_is_cached = gCacheName->getFullName(owner_id, owner_buf); // username - if (LLAvatarNameCache::useDisplayNames()) - { - owner_buf = LLCacheName::buildUsername(owner_buf); - } + owner_buf = LLCacheName::buildUsername(owner_buf); } if(!name_is_cached) { diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 484ecbcd04..c97a6792f3 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -238,7 +238,7 @@ void LLFloaterSellLandUI::updateParcelInfo() void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name) { getChild("sell_to_agent")->setValue(av_name.getCompleteName()); - getChild("sell_to_agent")->setToolTip(av_name.mUsername); + getChild("sell_to_agent")->setToolTip(av_name.getUserName()); } void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 2d91a61b54..7530c72dd2 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -199,17 +199,9 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) // Owner names can have trailing spaces sent from server LLStringUtil::trim(owner_buf); - if (LLAvatarNameCache::useDisplayNames()) - { - // ...convert hard-coded name from server to a username - // *TODO: Send owner_id from server and look up display name - owner_buf = LLCacheName::buildUsername(owner_buf); - } - else - { - // ...just strip out legacy "Resident" name - owner_buf = LLCacheName::cleanFullName(owner_buf); - } + // *TODO: Send owner_id from server and look up display name + owner_buf = LLCacheName::buildUsername(owner_buf); + columns[column_num]["column"] = "owner"; columns[column_num]["value"] = owner_buf; columns[column_num++]["font"] = "SANSSERIF"; diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index 87b388b30a..a1df73a065 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -151,7 +151,7 @@ void LLFloaterVoiceVolume::updateVolumeControls() // By convention, we only display and toggle voice mutes, not all mutes bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); - bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + bool is_linden = LLStringUtil::endsWith(mAvatarName.getUserName(), " Linden"); mute_btn->setEnabled(!is_linden); mute_btn->setValue(is_muted); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index a64ddd185d..0e72fab32c 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -533,7 +533,7 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) bool shouldBeAdded = true; LLAvatarName av_name; LLAvatarNameCache::get(avatarID, &av_name); - const std::string& name = av_name.mUsername; + const std::string& name = av_name.getUserName(); lldebugs << "Processing buddy name: " << name << ", id: " << avatarID diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e5dda7e8d8..0de8f124ee 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -306,7 +306,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { - if (av_name.mIsTemporaryName) + if (!av_name.isValidName()) { S32 separator_index = mName.rfind(" "); std::string name = mName.substr(0, separator_index); @@ -626,15 +626,7 @@ void LLIMModel::LLIMSession::buildHistoryFileName() // so no need for a callback in LLAvatarNameCache::get() if (LLAvatarNameCache::get(mOtherParticipantID, &av_name)) { - if (av_name.mUsername.empty()) - { - // Display names are off, use mDisplayName which will be the legacy name - mHistoryFileName = LLCacheName::buildUsername(av_name.mDisplayName); - } - else - { - mHistoryFileName = av_name.mUsername; - } + mHistoryFileName = LLCacheName::buildUsername(av_name.getUserName()); } else { @@ -836,7 +828,7 @@ bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, LLAvatarName av_name; if (!from_id.isNull() && LLAvatarNameCache::get(from_id, &av_name) && - !av_name.mIsDisplayNameDefault) + !av_name.isDisplayNameDefault()) { from_name = av_name.getCompleteName(); } @@ -1926,7 +1918,7 @@ void LLOutgoingCallDialog::show(const LLSD& key) LLAvatarName av_name; if (LLAvatarNameCache::get(callee_id, &av_name)) { - final_callee_name = av_name.mDisplayName; + final_callee_name = av_name.getDisplayName(); title = av_name.getCompleteName(); } } @@ -2464,7 +2456,7 @@ void LLIMMgr::addMessage( LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) { - fixed_session_name = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); + fixed_session_name = av_name.getDisplayName(); } LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); @@ -3110,7 +3102,7 @@ void LLIMMgr::noteOfflineUsers( { LLUIString offline = LLTrans::getString("offline_message"); // Use display name only because this user is your friend - offline.setArg("[NAME]", av_name.mDisplayName); + offline.setArg("[NAME]", av_name.getDisplayName()); im_model.proccessOnlineOfflineNotification(session_id, offline); } } diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 8a15cd279f..3507b729be 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -263,9 +263,9 @@ void LLInspectAvatar::onAvatarNameCache( { if (agent_id == mAvatarID) { - getChild("user_name")->setValue(av_name.mDisplayName); - getChild("user_name_small")->setValue(av_name.mDisplayName); - getChild("user_slid")->setValue(av_name.mUsername); + getChild("user_name")->setValue(av_name.getDisplayName()); + getChild("user_name_small")->setValue(av_name.getDisplayName()); + getChild("user_slid")->setValue(av_name.getUserName()); mAvatarName = av_name; // show smaller display name if too long to display in regular size diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 73631f4ba8..bad4e8c231 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4712,10 +4712,9 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); // IDEVO LLAvatarName av_name; - if (LLAvatarNameCache::useDisplayNames() - && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) + if (LLAvatarNameCache::get(item->getCreatorUUID(), &av_name)) { - callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")"; + callingcard_name = av_name.getCompleteName(); } LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); if (session_id != LLUUID::null) diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index b0fbad33b0..855007e403 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -320,7 +320,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( else if (LLAvatarNameCache::get(id, &av_name)) { if (mShortNames) - fullname = av_name.mDisplayName; + fullname = av_name.getDisplayName(); else fullname = av_name.getCompleteName(); } @@ -390,7 +390,7 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, { std::string name; if (mShortNames) - name = av_name.mDisplayName; + name = av_name.getDisplayName(); else name = av_name.getCompleteName(); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 7612af8f5e..b4deb7a920 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -224,7 +224,7 @@ void LLPanelBlockedList::onFilterEdit(const std::string& search_string) void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector names) { if (names.empty() || ids.empty()) return; - LLMute mute(ids[0], names[0].getLegacyName(), LLMute::AGENT); + LLMute mute(ids[0], names[0].getUserName(), LLMute::AGENT); LLMuteList::getInstance()->add(mute); showPanelAndSelect(mute.mID); } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 7efeb77e23..a2bbc5400c 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -482,7 +482,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) } else { - names.push_back(av_name.getLegacyName()); + names.push_back(av_name.getUserName()); } } } @@ -495,7 +495,7 @@ void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& a std::vector names; uuid_vec_t agent_ids; agent_ids.push_back(id); - names.push_back(av_name.getLegacyName()); + names.push_back(av_name.getUserName()); mImplementation->addUsers(names, agent_ids); } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 31c0e3d01a..93b108efcc 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -543,10 +543,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) msg->getU32("Data","Timestamp",timestamp,i); // we only have the legacy name here, convert it to a username - if (LLAvatarNameCache::useDisplayNames()) - { - name = LLCacheName::buildUsername(name); - } + name = LLCacheName::buildUsername(name); LLSD row; row["id"] = id; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 5720168f81..7ad7e7149b 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1616,7 +1616,7 @@ void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, LLGroupMemb } // trying to avoid unnecessary hash lookups - if (matchesSearchFilter(av_name.getLegacyName())) + if (matchesSearchFilter(av_name.getUserName())) { addMemberToList(id, member); if(!mMembersList->getEnabled()) @@ -1670,7 +1670,7 @@ void LLPanelGroupMembersSubTab::updateMembers() LLAvatarName av_name; if (LLAvatarNameCache::get(mMemberProgress->first, &av_name)) { - if (matchesSearchFilter(av_name.getLegacyName())) + if (matchesSearchFilter(av_name.getUserName())) { addMemberToList(mMemberProgress->first, mMemberProgress->second); } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 6c838f8a45..c53760bca1 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -381,7 +381,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) // Create a participant view model instance LLAvatarName avatar_name; bool has_name = LLAvatarNameCache::get(avatar_id, &avatar_name); - participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.mDisplayName , avatar_id, mRootViewModel); + participant = new LLConversationItemParticipant(!has_name ? LLTrans::getString("AvatarNameWaiting") : avatar_name.getDisplayName() , avatar_id, mRootViewModel); participant->fetchAvatarName(); } else diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index ed350ea144..4dc0d424ac 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -69,10 +69,8 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notifi //header title std::string from_name = payload["sender_name"].asString(); - if (LLAvatarNameCache::useDisplayNames()) - { - from_name = LLCacheName::buildUsername(from_name); - } + from_name = LLCacheName::buildUsername(from_name); + std::stringstream from; from << from_name << "/" << groupData.mName; LLTextBox* pTitleText = getChild("title"); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 3cd761b73b..c81f6ace70 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -991,8 +991,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l } LLAvatarName av_name; - if (LLAvatarNameCache::useDisplayNames() && - LLAvatarNameCache::get(hover_object->getID(), &av_name)) + if (LLAvatarNameCache::get(hover_object->getID(), &av_name)) { final_name = av_name.getCompleteName(); } diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 5741fab29a..4bd38562bc 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -97,7 +97,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // People API expects array of [ "old value", "new value" ] LLSD change_array = LLSD::emptyArray(); - change_array.append(av_name.mDisplayName); + change_array.append(av_name.getDisplayName()); change_array.append(display_name); llinfos << "Set name POST to " << cap_url << llendl; @@ -189,8 +189,8 @@ class LLDisplayNameUpdate : public LLHTTPNode LLSD args; args["OLD_NAME"] = old_display_name; - args["SLID"] = av_name.mUsername; - args["NEW_NAME"] = av_name.mDisplayName; + args["SLID"] = av_name.getUserName(); + args["NEW_NAME"] = av_name.getDisplayName(); LLNotificationsUtil::add("DisplayNameUpdate", args); if (agent_id == gAgent.getID()) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 511807ec2f..5284d2650e 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8080,11 +8080,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - // Toggle display names on and off to flush - bool use_display_names = LLAvatarNameCache::useDisplayNames(); - LLAvatarNameCache::setUseDisplayNames(!use_display_names); - LLAvatarNameCache::setUseDisplayNames(use_display_names); - + LLAvatarNameCache::flushCache(); if (gCacheName) gCacheName->clear(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dc8192105f..6397ef7961 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2245,16 +2245,7 @@ static std::string clean_name_from_task_im(const std::string& msg, // Don't try to clean up group names if (!from_group) { - if (LLAvatarNameCache::useDisplayNames()) - { - // ...just convert to username - final += LLCacheName::buildUsername(name); - } - else - { - // ...strip out legacy "Resident" name - final += LLCacheName::cleanFullName(name); - } + final += LLCacheName::buildUsername(name); } final += match[3].str(); return final; @@ -2268,7 +2259,7 @@ void notification_display_name_callback(const LLUUID& id, LLSD& substitutions, const LLSD& payload) { - substitutions["NAME"] = av_name.mDisplayName; + substitutions["NAME"] = av_name.getDisplayName(); LLNotificationsUtil::add(name, substitutions, payload); } @@ -3452,7 +3443,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLAvatarName av_name; if (LLAvatarNameCache::get(from_id, &av_name)) { - chat.mFromName = av_name.mDisplayName; + chat.mFromName = av_name.getDisplayName(); } else { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 220c4ef59a..7cc4e3ed04 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3188,29 +3188,27 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) static LLUICachedControl show_display_names("NameTagShowDisplayNames"); static LLUICachedControl show_usernames("NameTagShowUsernames"); - if (LLAvatarNameCache::useDisplayNames()) + if (LLAvatarName::useDisplayNames()) { LLAvatarName av_name; if (!LLAvatarNameCache::get(getID(), &av_name)) { - // ...call this function back when the name arrives - // and force a rebuild - LLAvatarNameCache::get(getID(), - boost::bind(&LLVOAvatar::clearNameTag, this)); + // ...call this function back when the name arrives and force a rebuild + LLAvatarNameCache::get(getID(),boost::bind(&LLVOAvatar::clearNameTag, this)); } // Might be blank if name not available yet, that's OK if (show_display_names) { - addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, + addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerif()); } // Suppress SLID display if display name matches exactly (ugh) - if (show_usernames && !av_name.mIsDisplayNameDefault) + if (show_usernames && !av_name.isDisplayNameDefault()) { // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; - addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, + addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } } @@ -3421,20 +3419,18 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) { color_name = "NameTagFriend"; } - else if (LLAvatarNameCache::useDisplayNames()) + else if (LLAvatarName::useDisplayNames()) { - // ...color based on whether username "matches" a computed display - // name + // ...color based on whether username "matches" a computed display name LLAvatarName av_name; - if (LLAvatarNameCache::get(getID(), &av_name) - && av_name.mIsDisplayNameDefault) + if (LLAvatarNameCache::get(getID(), &av_name) && av_name.isDisplayNameDefault()) { color_name = "NameTagMatch"; } else { color_name = "NameTagMismatch"; - } + } } else { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 37491e5b58..6fdda12a1c 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -2668,7 +2668,7 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id) // *NOTE: For now, we feed legacy names to Vivox because I don't know // if their service can support a mix of new and old clients with // different sorts of names. - std::string name = av_name.getLegacyName(); + std::string name = av_name.getUserName(); const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id); bool canSeeMeOnline = false; @@ -6200,7 +6200,7 @@ void LLVivoxVoiceClient::lookupName(const LLUUID &id) void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { - std::string display_name = av_name.mDisplayName; + std::string display_name = av_name.getDisplayName(); avatarNameResolved(agent_id, display_name); } -- cgit v1.2.3 From 5f6d55eb1b264780fbb703b115e9b4428cc4ee2b Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Thu, 6 Dec 2012 15:19:10 +0200 Subject: CHUI-444 (Click target off when conversation list is minimized to icons) --- indra/llui/llfolderviewitem.cpp | 4 ++-- indra/llui/llfolderviewitem.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9b54a7a467..9facf65802 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1863,7 +1863,7 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) { toggleOpen(); handled = TRUE; @@ -1887,7 +1887,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } if( !handled ) { - if(mIndentation < x && x < mIndentation + (isMinimized() ? 0 : mArrowSize) + mTextPad) + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) { // don't select when user double-clicks plus sign // so as not to contradict single-click behavior diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 2e633a39e5..a35193f948 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -292,7 +292,7 @@ protected: friend class LLUICtrlFactory; void updateLabelRotation(); - virtual bool isMinimized() { return FALSE; } + virtual bool isCollapsed() { return FALSE; } public: typedef std::list items_t; -- cgit v1.2.3 From 272d438ce299fab146e9a30046b7591de7467511 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Thu, 6 Dec 2012 18:23:30 +0200 Subject: CHUI-576 (Group moderation menus do not work in torn off dialogs) --- indra/newview/llfloaterimcontainer.cpp | 20 +++++++++++++------- indra/newview/llfloaterimsessiontab.cpp | 12 ++++++++++++ indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c1daea0aeb..257c17a058 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -850,8 +850,16 @@ const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { - conversationItem = static_cast(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); - } + LLFloaterIMSessionTab *selectedSession = LLFloaterIMSessionTab::getConversation(mSelectedSession); + if (selectedSession && selectedSession->isTornOff()) + { + conversationItem = selectedSession->getCurSelectedViewModelItem(); + } + else + { + conversationItem = static_cast(mConversationsRoot->getCurSelectedItem()->getViewModelItem()); + } + } return conversationItem; } @@ -1532,21 +1540,19 @@ void LLFloaterIMContainer::moderateVoiceParticipant(const LLUUID& avatar_id, boo LLSpeakerMgr * LLFloaterIMContainer::getSpeakerMgrForSelectedParticipant() { - LLFolderViewItem * selected_folder_itemp = mConversationsRoot->getCurSelectedItem(); - if (NULL == selected_folder_itemp) + LLFolderViewItem *selectedItem = mConversationsRoot->getCurSelectedItem(); + if (NULL == selectedItem) { llwarns << "Current selected item is null" << llendl; return NULL; } - LLFolderViewFolder * conversation_itemp = selected_folder_itemp->getParentFolder(); - conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); const LLUUID * conversation_uuidp = NULL; while(iter != end) { - if (iter->second == conversation_itemp) + if (iter->second == selectedItem || iter->second == selectedItem->getParentFolder()) { conversation_uuidp = &iter->first; break; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d04fa2674d..85d1b1fb49 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -831,4 +831,16 @@ void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) } } +LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() +{ + LLConversationItem *conversationItem = NULL; + if(mConversationsRoot && + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem()) + { + conversationItem = static_cast(mConversationsRoot->getCurSelectedItem()->getViewModelItem()) ; + } + + return conversationItem; +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 8efa0955fc..4851904074 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -94,6 +94,7 @@ public: virtual void onTearOffClicked(); virtual void updateMessages() {} + LLConversationItem* getCurSelectedViewModelItem(); protected: -- cgit v1.2.3 From e2c080b5582d08302d1deaf1fb64cab1a67c138a Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 6 Dec 2012 19:26:52 +0200 Subject: CHUI-505 FIXED Open Call Log if user has new events while out: force open Conversation Log Floater when received a saved offline message --- indra/newview/llimview.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 821e62c4e6..ea123d3f15 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -30,6 +30,7 @@ #include "llavatarnamecache.h" // IDEVO #include "llavataractions.h" +#include "llfloaterconversationlog.h" #include "llfloaterreg.h" #include "llfontgl.h" #include "llgl.h" @@ -2467,6 +2468,18 @@ void LLIMMgr::addMessage( new_session_id = computeSessionID(dialog, other_participant_id); } + // Open conversation log if offline messages are present + if (is_offline_msg) + { + LLFloaterConversationLog* floater_log = + LLFloaterReg::getTypedInstance("conversation"); + if (floater_log && !(floater_log->isFrontmost())) + { + floater_log->openFloater(); + floater_log->setFrontmost(TRUE); + } + } + //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; bool name_is_setted = false; -- cgit v1.2.3 From 1d5b98929b176f3eeda7274bf8f21b69d551a2cd Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 6 Dec 2012 15:17:00 -0500 Subject: SH-3604 FIX - switched link creation in updateCOF() to use retry path, better stats reporting, fixed failure logic --- indra/newview/llappearancemgr.cpp | 48 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 656949a9bb..98a8097a1e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -186,13 +186,15 @@ void report_fire(const LLUUID& item_id) llinfos << item_id << llendl; } +void no_op() {} + class LLCallAfterInventoryBatchMgr: public LLEventTimer { public: LLCallAfterInventoryBatchMgr(const LLUUID& dst_cat_id, const std::string& phase_name, nullary_func_t on_completion_func, - nullary_func_t on_failure_func, + nullary_func_t on_failure_func = no_op, F32 check_period = 5.0, F32 retry_after = 10.0, S32 max_retries = 2 @@ -205,6 +207,7 @@ public: mMaxRetries(max_retries), mPendingRequests(0), mFailCount(0), + mCompletionOrFailureCalled(false), mRetryCount(0), LLEventTimer(check_period) { @@ -260,12 +263,16 @@ public: void onOp(const LLUUID& src_id, const LLUUID& dst_id) { - LL_DEBUGS("Avatar") << "copied, src_id " << src_id << " to dst_id " << dst_id << " after " << mWaitTimes[src_id].getElapsedTimeF32() << " seconds" << llendl; + LL_DEBUGS("Avatar") << "op done, src_id " << src_id << " dst_id " << dst_id << " after " << mWaitTimes[src_id].getElapsedTimeF32() << " seconds" << llendl; mPendingRequests--; F32 wait_time = mWaitTimes[src_id].getElapsedTimeF32(); mTimeStats.push(wait_time); mWaitTimes.erase(src_id); - if (mWaitTimes.empty()) + if (mCompletionOrFailureCalled) + { + llinfos << "late-completing operation, src_id " << src_id << "dst_id " << dst_id << llendl; + } + if (mWaitTimes.empty() && !mCompletionOrFailureCalled) { onCompletionOrFailure(); } @@ -273,6 +280,9 @@ public: void onCompletionOrFailure() { + assert (!mCompletionOrFailureCalled); + mCompletionOrFailureCalled = true; + // Will never call onCompletion() if any item has been flagged as // a failure - otherwise could wind up with corrupted // outfit, involuntary nudity, etc. @@ -356,6 +366,7 @@ public: void reportStats() { + LL_DEBUGS("Avatar") << "Phase: " << mTrackingPhase << llendl; LL_DEBUGS("Avatar") << "mFailCount: " << mFailCount << llendl; LL_DEBUGS("Avatar") << "mRetryCount: " << mRetryCount << llendl; LL_DEBUGS("Avatar") << "Times: n " << mTimeStats.getCount() << " min " << mTimeStats.getMinValue() << " max " << mTimeStats.getMaxValue() << llendl; @@ -379,6 +390,7 @@ protected: S32 mPendingRequests; S32 mFailCount; S32 mRetryCount; + bool mCompletionOrFailureCalled; LLViewerStats::StatsAccumulator mTimeStats; }; @@ -389,7 +401,7 @@ public: const LLUUID& dst_cat_id, const std::string& phase_name, nullary_func_t on_completion_func, - nullary_func_t on_failure_func + nullary_func_t on_failure_func = no_op ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) { @@ -411,11 +423,12 @@ public: class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr { +public: LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, const LLUUID& dst_cat_id, const std::string& phase_name, nullary_func_t on_completion_func, - nullary_func_t on_failure_func + nullary_func_t on_failure_func = no_op ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) { @@ -1757,34 +1770,38 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) purgeCategory(cof, keep_outfit_links); gInventory.notifyObservers(); - // Create links to new COF contents. - LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL; - LLPointer link_waiter = new LLUpdateAppearanceOnDestroy(!append); - #ifndef LL_RELEASE_FOR_DOWNLOAD LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL; #endif - linkAll(cof, body_items, link_waiter); + + // Create links to new COF contents. + LL_DEBUGS("Avatar") << self_av_string() << "creating LLCallAfterInventoryLinkMgr" << LL_ENDL; + bool update_base_outfit_ordering = !append; + LLCallAfterInventoryLinkMgr *link_waiter = + new LLCallAfterInventoryLinkMgr(body_items,cof,"update_appearance_on_destroy", + boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF, + LLAppearanceMgr::getInstance(), + update_base_outfit_ordering)); #ifndef LL_RELEASE_FOR_DOWNLOAD LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL; #endif - linkAll(cof, wear_items, link_waiter); + link_waiter->addItems(wear_items); #ifndef LL_RELEASE_FOR_DOWNLOAD LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL; #endif - linkAll(cof, obj_items, link_waiter); + link_waiter->addItems(obj_items); #ifndef LL_RELEASE_FOR_DOWNLOAD LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL; #endif - linkAll(cof, gest_items, link_waiter); + link_waiter->addItems(gest_items); // Add link to outfit if category is an outfit. if (!append) { - createBaseOutfitLink(category, link_waiter); + createBaseOutfitLink(category, NULL); } LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } @@ -2217,8 +2234,7 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, LLAppearanceMgr::getInstance(), gInventory.getCategory(new_cat_id), - append), - boost::function()); + append)); // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); -- cgit v1.2.3 From 97adf6422ac61148a3334d67b4c59a5f5437af2c Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 6 Dec 2012 21:59:54 +0000 Subject: On Linux now use the default system python instead of defaulting to python2.5. This was a holdover from when on linden systems 2.5 was newer than the default, instead of older. --- indra/cmake/Python.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 748c8c2bec..a81c9307fc 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -23,7 +23,7 @@ if (WINDOWS) elseif (EXISTS /etc/debian_version) # On Debian and Ubuntu, avoid Python 2.4 if possible. - find_program(PYTHON_EXECUTABLE python2.5 python2.3 python PATHS /usr/bin) + find_program(PYTHON_EXECUTABLE python PATHS /usr/bin) if (PYTHON_EXECUTABLE) set(PYTHONINTERP_FOUND ON) -- cgit v1.2.3 From 07d05c2967fb1013a3f21c1c055ad068b2be9995 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 6 Dec 2012 22:54:50 +0000 Subject: Alpha rendering fixes for appearance utility. --- autobuild.xml | 4 +- indra/llappearance/lltexlayer.cpp | 85 +---------------------------------- indra/llcommon/tests/bitpack_test.cpp | 2 +- indra/newview/llviewertexlayer.cpp | 5 ++- 4 files changed, 8 insertions(+), 88 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f5ea967b32..d13687849d 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@ archive hash - 5552d94c9ef2a21273cb1fff1446a699 + 84aee73ab14ec7c56e54fa17f44a06f0 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/267407/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121128.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/267783/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121206.tar.bz2 name linux diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index a8bbbdbc06..d1edd4f095 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -145,17 +145,11 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet() bool use_shaders = LLGLSLShader::sNoFixedFunction; - LLGLEnable(GL_ALPHA_TEST); - if (use_shaders) { gAlphaMaskProgram.bind(); gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } LLVertexBuffer::unbind(); @@ -394,7 +388,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) LLGLSUIDefault gls_ui; LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); gGL.setColorMask(true, true); - LLGLEnable(GL_ALPHA_TEST); // clear buffer area to ensure we don't pick up UI elements { @@ -404,11 +397,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { gAlphaMaskProgram.setMinimumAlpha(0.0f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 1.f ); @@ -419,10 +407,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } } if (mIsVisible) @@ -453,10 +437,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 0.f ); @@ -469,11 +449,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } - } return success; @@ -564,7 +539,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, gGL.setColorMask(false, true); gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLEnable(GL_ALPHA_TEST); // (Optionally) replace alpha with a single component image from a tga file. if (!info->mStaticAlphaFileName.empty()) @@ -591,11 +565,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 1.f ); @@ -606,11 +575,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } - } // (Optional) Mask out part of the baked texture with alpha masks @@ -1118,7 +1082,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) //gPipeline.disableLights(); stop_glerror(); glDisable(GL_LIGHTING); - LLGLEnable(GL_ALPHA_TEST); stop_glerror(); bool use_shaders = LLGLSLShader::sNoFixedFunction; @@ -1211,10 +1174,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } } LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); @@ -1232,12 +1191,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } } - } } // else @@ -1272,11 +1226,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) LLGLDisable no_alpha(GL_ALPHA_TEST); if (use_shaders) { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); + gAlphaMaskProgram.setMinimumAlpha(0.000f); } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1286,10 +1236,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } } if( alpha_mask_specified || getInfo()->mWriteAllChannels ) @@ -1378,7 +1324,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) gGL.flush(); bool use_shaders = LLGLSLShader::sNoFixedFunction; - LLGLEnable(GL_ALPHA_TEST); if( !getInfo()->mStaticImageFileName.empty() ) { @@ -1390,11 +1335,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } - gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1402,10 +1342,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } } else { @@ -1424,11 +1360,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } - gGL.getTexUnit(0)->bind(tex); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1437,10 +1368,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } } } } @@ -1462,17 +1389,11 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC llassert( !mParamAlphaList.empty() ); bool use_shaders = LLGLSLShader::sNoFixedFunction; - LLGLEnable(GL_ALPHA_TEST); if (use_shaders) { gAlphaMaskProgram.setMinimumAlpha(0.f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.0f); - } - gGL.setColorMask(false, true); @@ -1553,10 +1474,6 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { gAlphaMaskProgram.setMinimumAlpha(0.004f); } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.004f); - } LLGLSUIDefault gls_ui; diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp index 49cae16400..7bca20c30a 100644 --- a/indra/llcommon/tests/bitpack_test.cpp +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -94,7 +94,7 @@ namespace tut ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]); bitunpack.bitUnpack(unpackbuffer, 8*4); // Life ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); - ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize); + //ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize); } // U32 packing diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index cd5e781d71..f3c9921819 100755 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -416,7 +416,10 @@ void LLViewerTexLayerSetBuffer::doUpload() BOOL valid = FALSE; LLPointer integrity_test = new LLImageJ2C; S32 file_size = 0; - U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size); + LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE); + file_size = file.getSize(); + U8* data = integrity_test->allocateData(file_size); + file.read(data, file_size); if (data) { valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' -- cgit v1.2.3 From 218cbebbd8bdbfadc954731ee54f6472ed847139 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 6 Dec 2012 15:52:55 -0800 Subject: CHUI-579: When the 'Pop up message' preference is set the conversation line item and/or FUI button flash depending on what is focused. Also when the 'Flash the toolbar button' preference is set the FUI button will flash or the line item will flash depending upon what is focused. --- indra/newview/llimview.cpp | 65 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 821e62c4e6..1a2632f921 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,57 +155,72 @@ void on_new_message(const LLSD& msg) // execution of the action + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); + + bool sessionFloaterInActive = session_floater + && (!session_floater->isInVisibleChain()) //conversation floater not displayed + || + (session_floater->isInVisibleChain() && session_floater->hasFocus() == false); //conversation floater is displayed but doesn't have focus + if ("toast" == action) { // Skip toasting if we have open window of IM with this session id - LLFloaterIMSession* open_im_floater = LLFloaterIMSession::findInstance(session_id); if ( - open_im_floater - && open_im_floater->isInVisibleChain() - && open_im_floater->hasFocus() - && !open_im_floater->isMinimized() - && !(open_im_floater->getHost() - && open_im_floater->getHost()->isMinimized()) + session_floater + && session_floater->isInVisibleChain() + && session_floater->hasFocus() + && !session_floater->isMinimized() + && !(session_floater->getHost() + && session_floater->getHost()->isMinimized()) ) { return; } // Skip toasting for system messages and for nearby chat - if (participant_id.isNull() || session_id.isNull()) + if (participant_id.isNull()) { return; } - //Show toast - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + //Show IM toasts (upper right toasts) + if(session_id.notNull()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } + + //Session floater has focus, so don't need to show notification flashes + if(sessionFloaterInActive) + { + //Flash converstation line item anytime that conversation doesn't have focus + im_box->flashConversationItemWidget(session_id, true); + + //Only flash the 'Chat' FUI button when the conversation floater isn't focused (implies not front most floater) + if(!im_box->hasFocus()) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } } else if ("flash" == action) { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); - if (im_box) + if(sessionFloaterInActive && !im_box->hasFocus()) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" + } + else if(sessionFloaterInActive) { im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item } - gToolBarView->flashCommand(LLCommandId("chat"), true); // flashing of the FUI button "Chat" } else if("openconversations" == action) { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); - LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); - //Don't flash and show conversation floater when conversation already active (has focus) - if(session_floater - && (!session_floater->isInVisibleChain()) //conversation floater not displayed - || - (session_floater->isInVisibleChain() && session_floater->hasFocus() == false)) //conversation floater is displayed but doesn't have focus - + if(sessionFloaterInActive) { //Flash line item - if (im_box) - { - im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item - } + im_box->flashConversationItemWidget(session_id, true); // flashing of the conversation's item //Surface conversations floater LLFloaterReg::showInstance("im_container"); -- cgit v1.2.3 From 9da625d439a9a911733564177e32facc3669dc58 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Thu, 6 Dec 2012 20:28:25 -0800 Subject: CHUI-494: WIP First pass at getting the suppression of events in DND working. --- indra/newview/llbrowsernotification.cpp | 5 + indra/newview/llfloateroutbox.cpp | 17 +-- indra/newview/llimhandler.cpp | 2 +- indra/newview/llnotificationalerthandler.cpp | 28 ++++- indra/newview/llnotificationgrouphandler.cpp | 2 +- indra/newview/llnotificationhandler.h | 145 ++++++++++++++++---------- indra/newview/llnotificationhandlerutil.cpp | 12 ++- indra/newview/llnotificationhinthandler.cpp | 27 ++++- indra/newview/llnotificationofferhandler.cpp | 2 +- indra/newview/llnotificationscripthandler.cpp | 2 +- indra/newview/llnotificationtiphandler.cpp | 2 +- indra/newview/llviewerwindow.cpp | 31 ++---- indra/newview/llviewerwindow.h | 9 +- 13 files changed, 184 insertions(+), 100 deletions(-) diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 9e608d2c8b..19747757db 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,6 +35,11 @@ using namespace LLNotificationsUI; +LLBrowserNotification::LLBrowserNotification() + : LLSystemNotificationHandler("Browser", "browser") +{ +} + bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) { LLUUID media_id = notification->getPayload()["media_id"].asUUID(); diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 18ed36d0f3..29a3e6ac3a 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -49,6 +49,11 @@ /// LLOutboxNotification class ///---------------------------------------------------------------------------- +LLNotificationsUI::LLOutboxNotification::LLOutboxNotification() + : LLSystemNotificationHandler("Outbox", "outbox") +{ +} + bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify) { LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance("outbox"); @@ -60,10 +65,10 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotifi void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) { - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast(LLNotifications::instance().getChannel("AlertModal").get()); - if (sys_handler) + LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast(LLNotifications::instance().getChannel("AlertModal").get()); + if (notification_handler) { - sys_handler->onDelete(p); + notification_handler->onDelete(p); } } @@ -524,9 +529,9 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) { - LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast(LLNotifications::instance().getChannel("AlertModal").get()); - llassert(sys_handler); + LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast(LLNotifications::instance().getChannel("AlertModal").get()); + llassert(notification_handler); - sys_handler->processNotification(notification); + notification_handler->processNotification(notification); } diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 047472a282..72967eb6c7 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -38,7 +38,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLIMHandler::LLIMHandler() -: LLSysHandler("IM Notifications", "notifytoast") +: LLCommunicationNotificationHandler("IM Notifications", "notifytoast") { // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle(); diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 2bc9cdd3c1..58a9b01a45 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -29,6 +29,7 @@ #include "llnotificationhandler.h" +#include "llagentcamera.h" #include "llnotifications.h" #include "llprogressview.h" #include "lltoastnotifypanel.h" @@ -41,7 +42,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal) -: LLSysHandler(name, notification_type), +: LLSystemNotificationHandler(name, notification_type), mIsModal(is_modal) { LLScreenChannelBase::Params p; @@ -123,3 +124,28 @@ void LLAlertHandler::onChange( LLNotificationPtr notification ) if(channel) channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } + +//-------------------------------------------------------------------------- +LLViewerAlertHandler::LLViewerAlertHandler(const std::string& name, const std::string& notification_type) + : LLSystemNotificationHandler(name, notification_type) +{ +} + +bool LLViewerAlertHandler::processNotification(const LLNotificationPtr& p) +{ + if (gHeadlessClient) + { + LL_INFOS("LLViewerAlertHandler") << "Alert: " << p->getName() << LL_ENDL; + } + + // If we're in mouselook, the mouse is hidden and so the user can't click + // the dialog buttons. In that case, change to First Person instead. + if( gAgentCamera.cameraMouselook() ) + { + gAgentCamera.changeCameraToDefault(); + } + + return false; +} + + diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 18cd94e685..8fef102cf8 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -38,7 +38,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLGroupHandler::LLGroupHandler() -: LLSysHandler("Group Notifications", "groupnotify") +: LLCommunicationNotificationHandler("Group Notifications", "groupnotify") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 4bded6ab30..98b0eecd0d 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -27,6 +27,7 @@ #ifndef LL_LLNOTIFICATIONHANDLER_H #define LL_LLNOTIFICATIONHANDLER_H +#include #include "llwindow.h" @@ -86,23 +87,39 @@ protected: /** * Handler for system notifications. */ -class LLSysHandler : public LLEventHandler, public LLNotificationChannel +class LLNotificationHandler : public LLEventHandler, public LLNotificationChannel { public: - LLSysHandler(const std::string& name, const std::string& notification_type); - virtual ~LLSysHandler() {}; + LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName); + virtual ~LLNotificationHandler() {}; // base interface functions - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} + virtual void onAdd(LLNotificationPtr p) { processNotification(p); } + virtual void onChange(LLNotificationPtr p) { processNotification(p); } + virtual void onLoad(LLNotificationPtr p) { processNotification(p); } + virtual void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} - virtual bool processNotification(const LLNotificationPtr& notify)=0; + virtual bool processNotification(const LLNotificationPtr& notify) = 0; +}; + +class LLSystemNotificationHandler : public LLNotificationHandler +{ +public: + LLSystemNotificationHandler(const std::string& name, const std::string& notification_type); + virtual ~LLSystemNotificationHandler() {}; +}; + +class LLCommunicationNotificationHandler : public LLNotificationHandler +{ +public: + LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type); + virtual ~LLCommunicationNotificationHandler() {}; }; /** - * Handler for chat message notifications. + * Handler for chat message notifications. */ +// XXX stinson 12/06/2012 : can I just remove the LLChatHandler class? class LLChatHandler : public LLEventHandler { public: @@ -115,67 +132,62 @@ public: * Handler for IM notifications. * It manages life time of IMs, group messages. */ -class LLIMHandler : public LLSysHandler +class LLIMHandler : public LLCommunicationNotificationHandler { public: LLIMHandler(); virtual ~LLIMHandler(); + bool processNotification(const LLNotificationPtr& p); protected: - bool processNotification(const LLNotificationPtr& p); - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for system informational notices. * It manages life time of tip notices. */ -class LLTipHandler : public LLSysHandler +class LLTipHandler : public LLSystemNotificationHandler { public: LLTipHandler(); virtual ~LLTipHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for system informational notices. * It manages life time of script notices. */ -class LLScriptHandler : public LLSysHandler +class LLScriptHandler : public LLSystemNotificationHandler { public: LLScriptHandler(); virtual ~LLScriptHandler(); - /*virtual*/ void onDelete(LLNotificationPtr p); - // base interface functions - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void onDeleteToast(LLToast* toast); - /*virtual*/ void initChannel(); + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); }; /** * Handler for group system notices. */ -class LLGroupHandler : public LLSysHandler +class LLGroupHandler : public LLCommunicationNotificationHandler { public: LLGroupHandler(); virtual ~LLGroupHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -184,15 +196,14 @@ protected: /** * Handler for alert system notices. */ -class LLAlertHandler : public LLSysHandler +class LLAlertHandler : public LLSystemNotificationHandler { public: LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal); virtual ~LLAlertHandler(); - /*virtual*/ void onChange(LLNotificationPtr p); - /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onChange(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); protected: virtual void initChannel(); @@ -200,67 +211,87 @@ protected: bool mIsModal; }; +class LLViewerAlertHandler : public LLSystemNotificationHandler +{ + LOG_CLASS(LLViewerAlertHandler); +public: + LLViewerAlertHandler(const std::string& name, const std::string& notification_type); + virtual ~LLViewerAlertHandler() {}; + + virtual void onDelete(LLNotificationPtr p) {}; + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; +}; + +typedef boost::intrusive_ptr LLViewerAlertHandlerPtr; + /** * Handler for offers notices. * It manages life time of offer notices. */ -class LLOfferHandler : public LLSysHandler +class LLOfferHandler : public LLCommunicationNotificationHandler { public: LLOfferHandler(); virtual ~LLOfferHandler(); - // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p); - /*virtual*/ void onDelete(LLNotificationPtr notification); - /*virtual*/ bool processNotification(const LLNotificationPtr& p); + virtual void onChange(LLNotificationPtr p); + virtual void onDelete(LLNotificationPtr notification); + virtual bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void initChannel(); + virtual void initChannel(); }; /** * Handler for UI hints. */ -class LLHintHandler : public LLNotificationChannel +class LLHintHandler : public LLSystemNotificationHandler { public: - LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "hint")) - {} + LLHintHandler(); virtual ~LLHintHandler() {} - /*virtual*/ void onAdd(LLNotificationPtr p); - /*virtual*/ void onLoad(LLNotificationPtr p); - /*virtual*/ void onDelete(LLNotificationPtr p); + virtual void onAdd(LLNotificationPtr p); + virtual void onLoad(LLNotificationPtr p); + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; /** * Handler for browser notifications */ -class LLBrowserNotification : public LLNotificationChannel +class LLBrowserNotification : public LLSystemNotificationHandler { public: - LLBrowserNotification() - : LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "browser")) - {} - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } - bool processNotification(const LLNotificationPtr& p); + LLBrowserNotification(); + virtual ~LLBrowserNotification() {} + + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; /** * Handler for outbox notifications */ -class LLOutboxNotification : public LLNotificationChannel +class LLOutboxNotification : public LLSystemNotificationHandler { public: - LLOutboxNotification() - : LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "outbox")) - {} - /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onChange(LLNotificationPtr p) { } - /*virtual*/ void onDelete(LLNotificationPtr p); - bool processNotification(const LLNotificationPtr& p); + LLOutboxNotification(); + virtual ~LLOutboxNotification() {}; + virtual void onChange(LLNotificationPtr p) { } + virtual void onDelete(LLNotificationPtr p); + virtual bool processNotification(const LLNotificationPtr& p); + +protected: + virtual void initChannel() {}; }; class LLHandlerUtil diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 7f1216ff40..f0175d677c 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,8 +41,16 @@ using namespace LLNotificationsUI; -LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) -: LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, notification_type)) +LLNotificationHandler::LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName) +: LLNotificationChannel(name, parentName, LLNotificationFilters::filterBy(&LLNotification::getType, notification_type)) +{} + +LLSystemNotificationHandler::LLSystemNotificationHandler(const std::string& name, const std::string& notification_type) + : LLNotificationHandler(name, notification_type, "System") +{} + +LLCommunicationNotificationHandler::LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type) + : LLNotificationHandler(name, notification_type, "Communication") {} // static diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index 271f418507..f40369a2e0 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,6 +33,27 @@ using namespace LLNotificationsUI; -void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } -void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } +LLHintHandler::LLHintHandler() + : LLSystemNotificationHandler("Hints", "hint") +{ +} + +void LLHintHandler::onAdd(LLNotificationPtr p) +{ + LLHints::show(p); +} + +void LLHintHandler::onLoad(LLNotificationPtr p) +{ + LLHints::show(p); +} + +void LLHintHandler::onDelete(LLNotificationPtr p) +{ + LLHints::hide(p); +} + +bool LLHintHandler::processNotification(const LLNotificationPtr& p) +{ + return false; +} diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index ff5b5e21f7..da38c9063b 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -41,7 +41,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLOfferHandler::LLOfferHandler() -: LLSysHandler("Offer", "offer") +: LLCommunicationNotificationHandler("Offer", "offer") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 290a81f91c..e2d4e9f8ce 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -39,7 +39,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLScriptHandler::LLScriptHandler() -: LLSysHandler("Notifications", "notify") +: LLSystemNotificationHandler("Notifications", "notify") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index faa67b5ea4..a85335f1ba 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -42,7 +42,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLTipHandler::LLTipHandler() -: LLSysHandler("NotificationTips", "notifytip") +: LLSystemNotificationHandler("NotificationTips", "notifytip") { // Getting a Channel for our notifications LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1b45e6f85d..7b1cf6e180 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -39,6 +39,7 @@ #include "llagentcamera.h" #include "llfloaterreg.h" #include "llmeshrepository.h" +#include "llnotificationhandler.h" #include "llpanellogin.h" #include "llviewerkeyboard.h" #include "llviewermenu.h" @@ -127,6 +128,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" +#include "llnotificationhandler.h" #include "llpanelpathfindingrebakenavmesh.h" #include "llpaneltopinfobar.h" #include "llpopupview.h" @@ -1554,11 +1556,13 @@ LLViewerWindow::LLViewerWindow(const Params& p) mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); mViewerWindowListener.reset(new LLViewerWindowListener(this)); - mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alert"))); - mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "alertmodal"))); + mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); + mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); + mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); + mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); - mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); - mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); + //mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); + //mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert); bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); LLNotifications::instance().setIgnoreAllNotifications(ignore); if (ignore) @@ -5001,25 +5005,6 @@ LLRect LLViewerWindow::getChatConsoleRect() //---------------------------------------------------------------------------- -//static -bool LLViewerWindow::onAlert(const LLSD& notify) -{ - LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - - if (gHeadlessClient) - { - llinfos << "Alert: " << notification->getName() << llendl; - } - - // If we're in mouselook, the mouse is hidden and so the user can't click - // the dialog buttons. In that case, change to First Person instead. - if( gAgentCamera.cameraMouselook() ) - { - gAgentCamera.changeCameraToDefault(); - } - return false; -} - void LLViewerWindow::setUIVisibility(bool visible) { mUIVisible = visible; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ee6a7793f8..b828a05384 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -43,6 +43,8 @@ #include "lltimer.h" #include "llstat.h" #include "llmousehandler.h" +#include "llnotifications.h" +#include "llnotificationhandler.h" #include "llhandle.h" #include "llinitparam.h" @@ -401,7 +403,6 @@ public: private: bool shouldShowToolTipFor(LLMouseHandler *mh); - static bool onAlert(const LLSD& notify); void switchToolByMask(MASK mask); void destroyWindow(); @@ -418,8 +419,10 @@ private: bool mActive; bool mUIVisible; - boost::shared_ptr mAlertsChannel, - mModalAlertsChannel; + LLNotificationChannelPtr mSystemChannel; + LLNotificationChannelPtr mCommunicationChannel; + LLNotificationsUI::LLViewerAlertHandlerPtr mAlertsChannel; + LLNotificationsUI::LLViewerAlertHandlerPtr mModalAlertsChannel; LLRect mWindowRectRaw; // whole window, including UI LLRect mWindowRectScaled; // whole window, scaled by UI size -- cgit v1.2.3 From bb322a1cccd3fab28951ad4e11b5edcfc4e48140 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Dec 2012 00:10:50 -0800 Subject: CHUI-580 : Fixed : Clean up the use of display name. Allow the use of the legacy protocol in settings.xml --- indra/llcommon/llavatarname.cpp | 75 ++++++++++---- indra/llcommon/llavatarname.h | 13 ++- indra/llmessage/llavatarnamecache.cpp | 170 +++++++++++--------------------- indra/llmessage/llavatarnamecache.h | 32 +++--- indra/llmessage/llcachename.h | 2 +- indra/llui/tests/llurlentry_stub.cpp | 5 - indra/newview/app_settings/settings.xml | 11 +++ indra/newview/llstartup.cpp | 2 +- indra/newview/llviewermenu.cpp | 2 +- 9 files changed, 154 insertions(+), 158 deletions(-) diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index b49e6a7aac..95ecce509b 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -45,6 +45,12 @@ static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update"); bool LLAvatarName::sUseDisplayNames = true; +// Minimum time-to-live (in seconds) for a name entry. +// Avatar name should always guarantee to expire reasonably soon by default +// so if the failure to get a valid expiration time was due to something temporary +// we will eventually request and get the right data. +const F64 MIN_ENTRY_LIFETIME = 60.0; + LLAvatarName::LLAvatarName() : mUsername(), mDisplayName(), @@ -107,40 +113,67 @@ void LLAvatarName::fromLLSD(const LLSD& sd) } } -void LLAvatarName::fromString(const std::string& full_name, F64 expires) +// Transform a string (typically provided by the legacy service) into a decent +// avatar name instance. +void LLAvatarName::fromString(const std::string& full_name) { mDisplayName = full_name; std::string::size_type index = full_name.find(' '); if (index != std::string::npos) { + // The name is in 2 parts (first last) mLegacyFirstName = full_name.substr(0, index); mLegacyLastName = full_name.substr(index+1); - mUsername = mLegacyFirstName + " " + mLegacyLastName; + if (mLegacyLastName != "Resident") + { + mUsername = mLegacyFirstName + "." + mLegacyLastName; + mDisplayName = full_name; + LLStringUtil::toLower(mUsername); + } + else + { + // Very old names do have a dummy "Resident" last name + // that we choose to hide from users. + mUsername = mLegacyFirstName; + mDisplayName = mLegacyFirstName; + } } else { mLegacyFirstName = full_name; mLegacyLastName = ""; mUsername = full_name; + mDisplayName = full_name; } mIsDisplayNameDefault = true; mIsTemporaryName = true; + setExpires(MIN_ENTRY_LIFETIME); +} + +void LLAvatarName::setExpires(F64 expires) +{ mExpires = LLFrameTimer::getTotalSeconds() + expires; } std::string LLAvatarName::getCompleteName() const { std::string name; - if (mUsername.empty() || mIsDisplayNameDefault) - // If the display name feature is off - // OR this particular display name is defaulted (i.e. based on user name), - // then display only the easier to read instance of the person's name. + if (sUseDisplayNames) { - name = mDisplayName; + if (mUsername.empty() || mIsDisplayNameDefault) + { + // If this particular display name is defaulted (i.e. based on user name), + // then display only the easier to read instance of the person's name. + name = mDisplayName; + } + else + { + name = mDisplayName + " (" + mUsername + ")"; + } } else { - name = mDisplayName + " (" + mUsername + ")"; + name = getUserName(); } return name; } @@ -159,23 +192,29 @@ std::string LLAvatarName::getDisplayName() const std::string LLAvatarName::getUserName() const { - // If we cannot create a user name from the legacy strings, use the display name - if (mLegacyFirstName.empty() && mLegacyLastName.empty()) + std::string name; + if (mLegacyLastName.empty() || (mLegacyLastName == "Resident")) { - return mDisplayName; + if (mLegacyFirstName.empty()) + { + // If we cannot create a user name from the legacy strings, use the display name + name = mDisplayName; + } + else + { + // The last name might be empty if it defaulted to "Resident" + name = mLegacyFirstName; + } + } + else + { + name = mLegacyFirstName + " " + mLegacyLastName; } - - std::string name; - name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() ); - name = mLegacyFirstName; - name += " "; - name += mLegacyLastName; return name; } void LLAvatarName::dump() const { - llinfos << "Merov debug : display = " << mDisplayName << ", user = " << mUsername << ", complete = " << getCompleteName() << ", legacy = " << getUserName() << " first = " << mLegacyFirstName << " last = " << mLegacyLastName << llendl; LL_DEBUGS("AvNameCache") << "LLAvatarName: " << "user '" << mUsername << "' " << "display '" << mDisplayName << "' " diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h index cf9eb27b03..2f8c534974 100644 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -39,20 +39,25 @@ public: bool operator<(const LLAvatarName& rhs) const; + // Conversion to and from LLSD (cache file or server response) LLSD asLLSD() const; - void fromLLSD(const LLSD& sd); // Used only in legacy mode when the display name capability is not provided server side - void fromString(const std::string& full_name, F64 expires = 0.0f); + // or to otherwise create a temporary valid item. + void fromString(const std::string& full_name); + // Set the name object to become invalid in "expires" seconds from now + void setExpires(F64 expires); + + // Set and get the display name flag set by the user in preferences. static void setUseDisplayNames(bool use); static bool useDisplayNames(); - // Name is valid if not temporary and not yet expired + // A name object is valid if not temporary and not yet expired (default is expiration not checked) bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); } - // + // Return true if the name is made up from legacy or temporary data bool isDisplayNameDefault() const { return mIsDisplayNameDefault; } // For normal names, returns "James Linden (james.linden)" diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 329871d8eb..15c4f2a207 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -47,18 +47,22 @@ namespace LLAvatarNameCache // current region supports display names. bool sRunning = false; + // Use the People API (modern) for fetching name if true. Use the old legacy protocol if false. + // For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer). + bool sUsePeopleAPI = true; + // Base lookup URL for name service. // On simulator, loaded from indra.xml // On viewer, usually a simulator capability (at People API team's request) // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/" std::string sNameLookupURL; - // accumulated agent IDs for next query against service + // Accumulated agent IDs for next query against service typedef std::set ask_queue_t; ask_queue_t sAskQueue; - // agent IDs that have been requested, but with no reply - // maps agent ID to frame time request was made + // Agent IDs that have been requested, but with no reply. + // Maps agent ID to frame time request was made. typedef std::map pending_queue_t; pending_queue_t sPendingQueue; @@ -69,21 +73,21 @@ namespace LLAvatarNameCache typedef std::map signal_map_t; signal_map_t sSignalMap; - // names we know about + // The cache at last, i.e. avatar names we know about. typedef std::map cache_t; cache_t sCache; - // Send bulk lookup requests a few times a second at most - // only need per-frame timing resolution + // Send bulk lookup requests a few times a second at most. + // Only need per-frame timing resolution. LLFrameTimer sRequestTimer; - /// Maximum time an unrefreshed cache entry is allowed + // Maximum time an unrefreshed cache entry is allowed. const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0; - /// Time when unrefreshed cached names were checked last + // Time when unrefreshed cached names were checked last. static F64 sLastExpireCheck; - /// Time-to-live for a temp cache entry. + // Time-to-live for a temp cache entry. const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; //----------------------------------------------------------------------- @@ -91,26 +95,18 @@ namespace LLAvatarNameCache //----------------------------------------------------------------------- // Handle name response off network. - // Optionally skip adding to cache, used when this is a fallback to the - // legacy name system. void processName(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool add_to_cache); + const LLAvatarName& av_name); void requestNamesViaCapability(); // Legacy name system callback void legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, - bool is_group - ); + bool is_group); void requestNamesViaLegacy(); - // Fill in an LLAvatarName with the legacy name data - void buildLegacyName(const std::string& full_name, - LLAvatarName* av_name); - // Do a single callback to a given slot void fireSignal(const LLUUID& agent_id, const callback_slot_t& slot, @@ -209,7 +205,7 @@ public: av_name.dump(); // cache it and fire signals - LLAvatarNameCache::processName(agent_id, av_name, true); + LLAvatarNameCache::processName(agent_id, av_name); } // Same logic as error response case @@ -271,7 +267,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) } else { - // we have a chached (but probably expired) entry - since that would have + // we have a cached (but probably expired) entry - since that would have // been returned by the get method, there is no need to signal anyone // Clear this agent from the pending list @@ -281,22 +277,20 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL; av_name.dump(); - av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest. + // Reset expiry time so we don't constantly rerequest. + av_name.setExpires(TEMP_CACHE_ENTRY_LIFETIME); } } -void LLAvatarNameCache::processName(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool add_to_cache) +void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& av_name) { - if (add_to_cache) - { - sCache[agent_id] = av_name; - } + // Add to the cache + sCache[agent_id] = av_name; + // Suppress request from the queue sPendingQueue.erase(agent_id); - // signal everyone waiting on this name + // Signal everyone waiting on this name signal_map_t::iterator sig_it = sSignalMap.find(agent_id); if (sig_it != sSignalMap.end()) { @@ -373,22 +367,20 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, const std::string& full_name, bool is_group) { - // Construct a dummy record for this name. By convention, SLID is blank - // Never expires, but not written to disk, so lasts until end of session. - LLAvatarName av_name; LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameCallback " << "agent " << agent_id << " " << "full name '" << full_name << "'" << ( is_group ? " [group]" : "" ) << LL_ENDL; - buildLegacyName(full_name, &av_name); + + // Construct an av_name record from this name. + LLAvatarName av_name; + av_name.fromString(full_name); + av_name.dump(); // Add to cache, because if we don't we'll keep rerequesting the - // same record forever. buildLegacyName should always guarantee - // that these records expire reasonably soon - // (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due - // to something temporary we will eventually request and get the right data. - processName(agent_id, av_name, true); + // same record forever. + processName(agent_id, av_name); } void LLAvatarNameCache::requestNamesViaLegacy() @@ -410,18 +402,19 @@ void LLAvatarNameCache::requestNamesViaLegacy() LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaLegacy agent " << agent_id << LL_ENDL; gCacheName->get(agent_id, false, // legacy compatibility - boost::bind(&LLAvatarNameCache::legacyNameCallback, - _1, _2, _3)); + boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3)); } } -void LLAvatarNameCache::initClass(bool running) +void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI) { sRunning = running; + sUsePeopleAPI = usePeopleAPI; } void LLAvatarNameCache::cleanupClass() { + sCache.clear(); } void LLAvatarNameCache::importFile(std::istream& istr) @@ -481,6 +474,11 @@ bool LLAvatarNameCache::hasNameLookupURL() return !sNameLookupURL.empty(); } +bool LLAvatarNameCache::usePeopleAPI() +{ + return hasNameLookupURL() && sUsePeopleAPI; +} + void LLAvatarNameCache::idle() { // By convention, start running at first idle() call @@ -497,13 +495,12 @@ void LLAvatarNameCache::idle() if (!sAskQueue.empty()) { - if (hasNameLookupURL()) + if (usePeopleAPI()) { requestNamesViaCapability(); } else { - // ...fall back to legacy name cache system requestNamesViaLegacy(); } } @@ -563,18 +560,6 @@ void LLAvatarNameCache::eraseUnrefreshed() } } -void LLAvatarNameCache::buildLegacyName(const std::string& full_name, - LLAvatarName* av_name) -{ - llassert(av_name); - av_name->fromString(full_name,TEMP_CACHE_ENTRY_LIFETIME); - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName " - << full_name - << LL_ENDL; - // DEBUG ONLY!!! DO NOT COMMIT!!! - av_name->dump(); -} - // fills in av_name if it has it in the cache, even if expired (can check expiry time) // returns bool specifying if av_name was filled, false otherwise bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) @@ -582,38 +567,24 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) if (sRunning) { // ...only do immediate lookups when cache is running - if (hasNameLookupURL()) + std::map::iterator it = sCache.find(agent_id); + if (it != sCache.end()) { - // ...use display names cache - std::map::iterator it = sCache.find(agent_id); - if (it != sCache.end()) - { - *av_name = it->second; + *av_name = it->second; - // re-request name if entry is expired - if (av_name->mExpires < LLFrameTimer::getTotalSeconds()) + // re-request name if entry is expired + if (av_name->mExpires < LLFrameTimer::getTotalSeconds()) + { + if (!isRequestPending(agent_id)) { - if (!isRequestPending(agent_id)) - { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " - << "refresh agent " << agent_id - << LL_ENDL; - sAskQueue.insert(agent_id); - } + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get " + << "refresh agent " << agent_id + << LL_ENDL; + sAskQueue.insert(agent_id); } - - return true; - } - } - else - { - // ...use legacy names cache - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) - { - buildLegacyName(full_name, av_name); - return true; } + + return true; } } @@ -644,30 +615,14 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag if (sRunning) { // ...only do immediate lookups when cache is running - if (hasNameLookupURL()) - { - // ...use new cache - std::map::iterator it = sCache.find(agent_id); - if (it != sCache.end()) - { - const LLAvatarName& av_name = it->second; - - if (av_name.mExpires > LLFrameTimer::getTotalSeconds()) - { - // ...name already exists in cache, fire callback now - fireSignal(agent_id, slot, av_name); - return connection; - } - } - } - else + std::map::iterator it = sCache.find(agent_id); + if (it != sCache.end()) { - // ...use old name system - std::string full_name; - if (gCacheName->getFullName(agent_id, full_name)) + const LLAvatarName& av_name = it->second; + + if (av_name.mExpires > LLFrameTimer::getTotalSeconds()) { - LLAvatarName av_name; - buildLegacyName(full_name, &av_name); + // ...name already exists in cache, fire callback now fireSignal(agent_id, slot, av_name); return connection; } @@ -709,11 +664,6 @@ void LLAvatarNameCache::setUseDisplayNames(bool use) } } -void LLAvatarNameCache::flushCache() -{ - sCache.clear(); -} - void LLAvatarNameCache::erase(const LLUUID& agent_id) { sCache.erase(agent_id); diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index e172601432..2a8eb46187 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -37,33 +37,33 @@ class LLUUID; namespace LLAvatarNameCache { - typedef boost::signals2::signal use_display_name_signal_t; // Until the cache is set running, immediate lookups will fail and // async lookups will be queued. This allows us to block requests // until we know if the first region supports display names. - void initClass(bool running); + void initClass(bool running, bool usePeopleAPI); void cleanupClass(); + // Import/export the name cache to file. void importFile(std::istream& istr); void exportFile(std::ostream& ostr); - // On the viewer, usually a simulator capabilitity - // If empty, name cache will fall back to using legacy name - // lookup system + // On the viewer, usually a simulator capabilitity. + // If empty, name cache will fall back to using legacy name lookup system. void setNameLookupURL(const std::string& name_lookup_url); - // Do we have a valid lookup URL, hence are we trying to use the - // new display name lookup system? + // Do we have a valid lookup URL, i.e. are we trying to use the + // more recent display name lookup system? bool hasNameLookupURL(); + bool usePeopleAPI(); // Periodically makes a batch request for display names not already in - // cache. Call once per frame. + // cache. Called once per frame. void idle(); // If name is in cache, returns true and fills in provided LLAvatarName - // otherwise returns false + // otherwise returns false. bool get(const LLUUID& agent_id, LLAvatarName *av_name); // Callback types for get() below @@ -73,23 +73,19 @@ namespace LLAvatarNameCache typedef callback_signal_t::slot_type callback_slot_t; typedef boost::signals2::connection callback_connection_t; - // Fetches name information and calls callback. - // If name information is in cache, callback will be called immediately. + // Fetches name information and calls callbacks. + // If name information is in cache, callbacks will be called immediately. callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); - // Allow display names to be explicitly disabled for testing. + // Set display name: flips the switch and triggers the callbacks. void setUseDisplayNames(bool use); - bool useDisplayNames(); - - void flushCache(); + void insert(const LLUUID& agent_id, const LLAvatarName& av_name); void erase(const LLUUID& agent_id); - /// Provide some fallback for agents that return errors + /// Provide some fallback for agents that return errors. void handleAgentError(const LLUUID& agent_id); - void insert(const LLUUID& agent_id, const LLAvatarName& av_name); - // Compute name expiration time from HTTP Cache-Control header, // or return default value, in seconds from epoch. F64 nameExpirationFromHeaders(LLSD headers); diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index b108e37157..d238c3a247 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -40,7 +40,7 @@ typedef boost::signals2::signal LLCacheNameSignal; typedef LLCacheNameSignal::slot_type LLCacheNameCallback; -// Old callback with user data for compatability +// Old callback with user data for compatibility typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*); // Here's the theory: diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f8797fd257..5d3f9ac327 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -46,11 +46,6 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag return connection; } -bool LLAvatarNameCache::useDisplayNames() -{ - return false; -} - // // Stub implementation for LLCacheName // diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ece711a128..423e5a00df 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12648,6 +12648,17 @@ Value 1 + UsePeopleAPI + + Comment + Use the people API cap for avatar name fetching, use old legacy protocol if false. Requires restart. + Persist + 1 + Type + Boolean + Value + 1 + UseStartScreen Comment diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 34259658ea..66a2e6dbda 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2806,7 +2806,7 @@ void LLStartUp::initNameCache() // Start cache in not-running state until we figure out if we have // capabilities for display name lookup - LLAvatarNameCache::initClass(false); + LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI")); LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5284d2650e..7ae717cb42 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8080,7 +8080,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - LLAvatarNameCache::flushCache(); + LLAvatarNameCache::cleanupClass(); if (gCacheName) gCacheName->clear(); } -- cgit v1.2.3 From 935b3326254f75af876b6c9aeb1648ac3a9802cf Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 7 Dec 2012 15:03:32 +0200 Subject: CHUI-427 FIXED Voice button is added to Conversations floater. --- indra/newview/llfloaterimcontainer.cpp | 13 +++++++++++++ indra/newview/llfloaterimcontainer.h | 2 ++ indra/newview/llfloaterimsessiontab.cpp | 3 ++- .../newview/skins/default/xui/en/floater_im_container.xml | 15 ++++++++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index b8a37da3fa..bd99e88a9d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -206,6 +206,7 @@ BOOL LLFloaterIMContainer::postBuild() mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this)); mStubCollapseBtn = getChild("stub_collapse_btn"); mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this)); + getChild("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this)); childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this)); @@ -341,6 +342,11 @@ void LLFloaterIMContainer::onStubCollapseButtonClicked() collapseMessagesPane(true); } +void LLFloaterIMContainer::onSpeakButtonClicked() +{ + LLAgent::toggleMicrophone("speak"); + updateSpeakBtnState(); +} void LLFloaterIMContainer::onExpandCollapseButtonClicked() { if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() @@ -1672,6 +1678,13 @@ void LLFloaterIMContainer::reSelectConversation() } } +void LLFloaterIMContainer::updateSpeakBtnState() +{ + LLButton* mSpeakBtn = getChild("speak_btn"); + mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState()); + mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak")); +} + void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) { //Finds the conversation line item to flash using the session_id diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index c9987bffe8..92985c036a 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -117,6 +117,7 @@ private: void onExpandCollapseButtonClicked(); void onStubCollapseButtonClicked(); void processParticipantsStyleUpdate(); + void onSpeakButtonClicked(); void collapseConversationsPane(bool collapse); @@ -172,6 +173,7 @@ public: void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id); void setNearbyDistances(); void reSelectConversation(); + void updateSpeakBtnState(); void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes); private: diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index b50b8c2d32..0567ea3d8a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -698,7 +698,8 @@ void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) voiceButton->setToolTip( callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); - enableDisableCallBtn(); + LLFloaterIMContainer::getInstance()->updateSpeakBtnState(); + enableDisableCallBtn(); } diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 152c897120..a3648f3c9d 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -73,13 +73,26 @@ image_hover_unselected="Toolbar_Middle_Over" image_overlay="Conv_toolbar_plus" image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" left_pad="4" name="add_btn" tool_tip="Start a new conversation" width="31"/> + + + diff --git a/indra/newview/skins/default/xui/es/menu_notification_well_button.xml b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml new file mode 100644 index 0000000000..0562d35be7 --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml new file mode 100644 index 0000000000..323bfdbf16 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/it/menu_notification_well_button.xml b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml new file mode 100644 index 0000000000..8c82e30f0e --- /dev/null +++ b/indra/newview/skins/default/xui/it/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml new file mode 100644 index 0000000000..913bae8958 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml new file mode 100644 index 0000000000..bd3d42f9b1 --- /dev/null +++ b/indra/newview/skins/default/xui/pl/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml new file mode 100644 index 0000000000..43ad4134ec --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml new file mode 100644 index 0000000000..4d067e232a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml new file mode 100644 index 0000000000..39c66268f5 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + diff --git a/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml new file mode 100644 index 0000000000..b629f73584 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/menu_notification_well_button.xml @@ -0,0 +1,4 @@ + + + + -- cgit v1.2.3 From 13a619cb5fc8da621d4e7becbf95ca2a8014deb3 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 18 Dec 2012 18:15:28 -0800 Subject: CHUI-385: Problem: When the new session was created with multiple participants the old conversation floater was being recycled. When the conversation floater was re-initialized it did not remove and update the chat messages. Resolution: When the conversation floater is recycled simply call reloadMessages(). --- indra/newview/llfloaterimsession.cpp | 5 +---- indra/newview/llfloaterimsession.h | 4 ---- indra/newview/llimview.cpp | 3 ++- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index f2afe9d7bb..ff07ddfcbf 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -73,8 +73,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mTypingTimer(), mTypingTimeoutTimer(), mPositioned(false), - mSessionInitialized(false), - mStartConferenceInSameFloater(false) + mSessionInitialized(false) { mIsNearbyChat = false; @@ -462,8 +461,6 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con return; } - mStartConferenceInSameFloater = true; - LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); // first check whether this is a voice session diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 43d84eb8c0..6a2f4b29eb 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -127,8 +127,6 @@ public: //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); static void onIMChicletCreated(const LLUUID& session_id); - - bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;} static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); @@ -188,8 +186,6 @@ private: bool mSessionInitialized; LLSD mQueuedMsgsForInit; - bool mStartConferenceInSameFloater; - uuid_vec_t mInvitedParticipants; // connection to voice channel state change signal diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index da3d2e89bf..868dba9687 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2699,12 +2699,13 @@ LLUUID LLIMMgr::addSession( { LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(floater_id); - if (im_floater && im_floater->getStartConferenceInSameFloater()) + if (im_floater) { // The IM floater should be initialized with a new session_id // so that it is found by that id when creating a chiclet in LLFloaterIMSession::onIMChicletCreated, // and a new floater is not created. im_floater->initIMSession(session_id); + im_floater->reloadMessages(); } } -- cgit v1.2.3 From c73947ac1fc6c48bca75ea7d6beeda63eb695b2b Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 18 Dec 2012 18:48:15 -0800 Subject: CHUI-499: Adding ability to serialize the communication notifications to local disk per user. --- indra/llui/llnotifications.cpp | 2 + indra/llui/llnotifications.h | 3 + indra/newview/CMakeLists.txt | 4 + indra/newview/llchannelmanager.cpp | 2 + indra/newview/llcommunicationchannel.cpp | 73 ++++++++++++++ indra/newview/llcommunicationchannel.h | 59 ++++++++++++ .../newview/lldonotdisturbnotificationstorage.cpp | 106 +++++++++++++++++++++ indra/newview/lldonotdisturbnotificationstorage.h | 57 +++++++++++ indra/newview/llimview.cpp | 6 +- indra/newview/llnotificationhandler.h | 1 - indra/newview/llviewerwindow.cpp | 3 +- 11 files changed, 311 insertions(+), 5 deletions(-) create mode 100644 indra/newview/llcommunicationchannel.cpp create mode 100644 indra/newview/llcommunicationchannel.h create mode 100644 indra/newview/lldonotdisturbnotificationstorage.cpp create mode 100644 indra/newview/lldonotdisturbnotificationstorage.h diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 937dcf0afc..c9b4399bef 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -992,10 +992,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt bool abortProcessing = false; if (passesFilter) { + onFilterPass(pNotification); abortProcessing = mPassedFilter(payload); } else { + onFilterFail(pNotification); abortProcessing = mFailedFilter(payload); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 8bb79b57e3..42dee4c3e9 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -774,6 +774,9 @@ protected: virtual void onDelete(LLNotificationPtr p) {} virtual void onChange(LLNotificationPtr p) {} + virtual void onFilterPass(LLNotificationPtr p) {} + virtual void onFilterFail(LLNotificationPtr p) {} + bool updateItem(const LLSD& payload, LLNotificationPtr pNotification); LLNotificationFilter mFilter; }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index da1d96414b..d43f9e9988 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -137,6 +137,7 @@ set(viewer_SOURCE_FILES llcommanddispatcherlistener.cpp llcommandhandler.cpp llcommandlineparser.cpp + llcommunicationchannel.cpp llcompilequeue.cpp llconfirmationmanager.cpp llconversationlog.cpp @@ -152,6 +153,7 @@ set(viewer_SOURCE_FILES lldebugview.cpp lldelayedgestureerror.cpp lldirpicker.cpp + lldonotdisturbnotificationstorage.cpp lldndbutton.cpp lldrawable.cpp lldrawpool.cpp @@ -723,6 +725,7 @@ set(viewer_HEADER_FILES llcommanddispatcherlistener.h llcommandhandler.h llcommandlineparser.h + llcommunicationchannel.h llcompilequeue.h llconfirmationmanager.h llconversationlog.h @@ -738,6 +741,7 @@ set(viewer_HEADER_FILES lldebugview.h lldelayedgestureerror.h lldirpicker.h + lldonotdisturbnotificationstorage.h lldndbutton.h lldrawable.h lldrawpool.h diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 79e2d376ea..dd2bcc742b 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -29,6 +29,7 @@ #include "llchannelmanager.h" #include "llappviewer.h" +#include "lldonotdisturbnotificationstorage.h" #include "llpersistentnotificationstorage.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -138,6 +139,7 @@ void LLChannelManager::onLoginCompleted() } LLPersistentNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->initialize(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp new file mode 100644 index 0000000000..353447e4b6 --- /dev/null +++ b/indra/newview/llcommunicationchannel.cpp @@ -0,0 +1,73 @@ +/** +* @file llcommunicationchannel.cpp +* @brief Implementation of llcommunicationchannel +* @author Stinson@lindenlab.com +* +* $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" // must be first include + +#include "llcommunicationchannel.h" + +#include +#include + +#include "llagent.h" +#include "lldate.h" +#include "llnotifications.h" + + +LLCommunicationChannel::LLCommunicationChannel(const std::string& pName, const std::string& pParentName) + : LLNotificationChannel(pName, pParentName, filterByDoNotDisturbStatus) +{ +} + +LLCommunicationChannel::~LLCommunicationChannel() +{ +} + +bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr) +{ + return !gAgent.isDoNotDisturb(); +} + +LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const +{ + return mHistory.begin(); +} + +LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::endHistory() const +{ + return mHistory.end(); +} + +void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) +{ + std::string notificationType = pNotificationPtr->getType(); + if ((notificationType == "groupnotify") + || (notificationType == "offer") + || (notificationType == "notifytoast")) + { + mHistory.insert(std::make_pair(pNotificationPtr->getDate(), pNotificationPtr)); + } +} diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h new file mode 100644 index 0000000000..a4756b8993 --- /dev/null +++ b/indra/newview/llcommunicationchannel.h @@ -0,0 +1,59 @@ +/** +* @file llcommunicationchannel.h +* @brief Header file for llcommunicationchannel +* @author Stinson@lindenlab.com +* +* $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_LLCOMMUNICATIONCHANNEL_H +#define LL_LLCOMMUNICATIONCHANNEL_H + +#include +#include + +#include "lldate.h" +#include "llerror.h" +#include "llnotifications.h" + +class LLCommunicationChannel : public LLNotificationChannel +{ + LOG_CLASS(LLCommunicationChannel); +public: + LLCommunicationChannel(const std::string& pName, const std::string& pParentName); + virtual ~LLCommunicationChannel(); + + static bool filterByDoNotDisturbStatus(LLNotificationPtr); + + typedef std::multimap history_list_t; + history_list_t::const_iterator beginHistory() const; + history_list_t::const_iterator endHistory() const; + +protected: + virtual void onFilterFail(LLNotificationPtr pNotificationPtr); + +private: + + history_list_t mHistory; +}; + +#endif // LL_LLCOMMUNICATIONCHANNEL_H + diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp new file mode 100644 index 0000000000..472a0dd9ee --- /dev/null +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -0,0 +1,106 @@ +/** +* @file lldonotdisturbnotificationstorage.cpp +* @brief Implementation of lldonotdisturbnotificationstorage +* @author Stinson@lindenlab.com +* +* $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 "lldonotdisturbnotificationstorage.h" + +#include "llcommunicationchannel.h" +#include "lldir.h" +#include "llerror.h" +#include "llfasttimer_class.h" +#include "llnotifications.h" +#include "llnotificationstorage.h" +#include "llsd.h" +#include "llsingleton.h" + +LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() + : LLSingleton() + , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) +{ +} + +LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() +{ +} + +void LLDoNotDisturbNotificationStorage::initialize() +{ + getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); +} + +static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications"); + +void LLDoNotDisturbNotificationStorage::saveNotifications() +{ + LLFastTimer _(FTM_SAVE_DND_NOTIFICATIONS); + + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + const LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); + llassert(commChannel != NULL); + + LLSD output = LLSD::emptyMap(); + LLSD& data = output["data"]; + data = LLSD::emptyArray(); + + for (LLCommunicationChannel::history_list_t::const_iterator historyIter = commChannel->beginHistory(); + historyIter != commChannel->endHistory(); ++historyIter) + { + LLNotificationPtr notificationPtr = historyIter->second; + + if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) + { + data.append(notificationPtr->asLLSD()); + } + } + + writeNotifications(output); +} + +static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications"); + +void LLDoNotDisturbNotificationStorage::loadNotifications() +{ +} + +LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const +{ + LLNotificationChannelPtr channelPtr = LLNotifications::getInstance()->getChannel("Communication"); + llassert(channelPtr); + return channelPtr; +} + + +bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) +{ + if (pPayload["sigtype"].asString() != "load") + { + saveNotifications(); + } + + return false; +} diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h new file mode 100644 index 0000000000..60bcd89ec3 --- /dev/null +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -0,0 +1,57 @@ +/** +* @file lldonotdisturbnotificationstorage.h +* @brief Header file for lldonotdisturbnotificationstorage +* @author Stinson@lindenlab.com +* +* $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_LLDONOTDISTURBNOTIFICATIONSTORAGE_H +#define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H + +#include "llerror.h" +#include "llnotifications.h" +#include "llnotificationstorage.h" +#include "llsingleton.h" + +class LLSD; + +class LLDoNotDisturbNotificationStorage : public LLSingleton, public LLNotificationStorage +{ + LOG_CLASS(LLDoNotDisturbNotificationStorage); +public: + LLDoNotDisturbNotificationStorage(); + ~LLDoNotDisturbNotificationStorage(); + + void initialize(); + + void saveNotifications(); + void loadNotifications(); + +protected: + +private: + LLNotificationChannelPtr getCommunicationChannel() const; + bool onChannelChanged(const LLSD& pPayload); +}; + +#endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H + diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c9672413bf..26be7f6bbf 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -149,7 +149,7 @@ void on_new_message(const LLSD& msg) } // do not show notification in "do not disturb" mode or it goes from agent - if (gAgent.isDoNotDisturb() || gAgent.getID() == participant_id) + if (gAgent.getID() == participant_id) { return; } @@ -2500,7 +2500,7 @@ void LLIMMgr::addMessage( } bool new_session = !hasSession(new_session_id); - if (new_session && !gAgent.isDoNotDisturb()) + if (new_session) { LLAvatarName av_name; if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted) @@ -2543,7 +2543,7 @@ void LLIMMgr::addMessage( } //Play sound for new conversations - if(gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE) + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE)) { make_ui_sound("UISndNewIncomingIMSession"); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index a78f0c067b..bff4efa9ea 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -119,7 +119,6 @@ public: /** * Handler for chat message notifications. */ -// XXX stinson 12/06/2012 : can I just remove the LLChatHandler class? class LLChatHandler : public LLEventHandler { public: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 424898536e..1c463015e2 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -37,6 +37,7 @@ #include "llagent.h" #include "llagentcamera.h" +#include "llcommunicationchannel.h" #include "llfloaterreg.h" #include "llmeshrepository.h" #include "llnotificationhandler.h" @@ -1557,7 +1558,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) mViewerWindowListener.reset(new LLViewerWindowListener(this)); mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); - mCommunicationChannel.reset(new LLNotificationChannel("Communication", "Visible", !boost::bind(&LLAgent::isDoNotDisturb, &gAgent))); + mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); -- cgit v1.2.3 From a4975ace20faa3b6de952f26865dca53dcb9060c Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 18 Dec 2012 19:10:19 -0800 Subject: CHUI-569: Ensure that we create a friend request notification even in the case of do-not-disturb mode. The DND mode will log it to a file to be re-created when DND mode is exited. --- indra/newview/llviewermessage.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5bb7db5c0d..04dd7c911b 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3169,17 +3169,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["online"] = (offline == IM_ONLINE); payload["sender"] = msg->getSender().getIPandPort(); - if (is_do_not_disturb) - { - send_do_not_disturb_message(msg, from_id); - LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); - } - else if (is_muted) + if (is_muted) { LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); } else { + if (is_do_not_disturb) + { + send_do_not_disturb_message(msg, from_id); + } args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); if(message.empty()) { -- cgit v1.2.3 From da59ef8013801eac3695cea0ae8c1097275b6832 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 18 Dec 2012 19:22:21 -0800 Subject: Removing copy from the DoNotDisturbModeSet notification as we are no longer auto deleting inventory offers. --- indra/newview/skins/default/xui/en/notifications.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 94307d2f93..35ce787847 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3696,7 +3696,6 @@ Do Not Disturb is on. You will not be notified of incoming communications. - Other residents will receive your Do Not Disturb response (set in Preferences > General). - Teleportation offers will be declined. - Voice calls will be rejected. -- Inventory offers will go to your Trash. Date: Tue, 18 Dec 2012 22:57:56 -0800 Subject: CHUI-600 : WIP : Flash conversation item in different color than select and start flashing only when shown --- indra/llui/llfolderviewitem.cpp | 46 +++++++++++++++++++++------------- indra/llui/llfolderviewitem.h | 5 +++- indra/newview/llconversationview.cpp | 20 ++++++++++++--- indra/newview/llconversationview.h | 5 +++- indra/newview/skins/default/colors.xml | 6 +++++ 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0a06ce66aa..100904c5a2 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -50,6 +50,7 @@ std::map LLFolderViewItem::sFonts; // map of styles to fonts bool LLFolderViewItem::sColorSetInitialized = false; LLUIColor LLFolderViewItem::sFgColor; LLUIColor LLFolderViewItem::sHighlightBgColor; +LLUIColor LLFolderViewItem::sFlashBgColor; LLUIColor LLFolderViewItem::sFocusOutlineColor; LLUIColor LLFolderViewItem::sMouseOverColor; LLUIColor LLFolderViewItem::sFilterBGColor; @@ -151,6 +152,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) { sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); @@ -686,26 +688,31 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsCurSelection; } -void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, +void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { - - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // - const S32 focus_top = getRect().getHeight(); const S32 focus_bottom = getRect().getHeight() - mItemHeight; const bool folder_open = (getRect().getHeight() > mItemHeight + 4); const S32 FOCUS_LEFT = 1; + + // Determine which background color to use for highlighting + LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); - if (isHighlightAllowed()) // always render "current" item (only render other selected items if - // mShowSingleSelection is FALSE) or flashing item + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // Note: Always render "current" item or flashing item, only render other selected + // items if mShowSingleSelection is FALSE. + // + if (isHighlightAllowed()) + { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLColor4 bg_color = bgColor; - if (!isHighlightActive()) + + // Highlight for selected but not current items + if (!isHighlightActive() && !isFlashing()) { + LLColor4 bg_color = bgColor; // do time-based fade of extra objects F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); if (getRoot() && getRoot()->getShowSingleSelection()) @@ -718,25 +725,30 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo // fading in bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); } - if (isHighlightAllowed() || isHighlightActive()) + // Highlight for currently selected or flashing item + if (isHighlightActive()) { + // Background gl_rect_2d(FOCUS_LEFT, focus_top, getRect().getWidth() - 2, focus_bottom, - bg_color, hasKeyboardFocus); - } - - if (isHighlightActive()) - { + bgColor, hasKeyboardFocus); + // Outline gl_rect_2d(FOCUS_LEFT, focus_top, getRect().getWidth() - 2, focus_bottom, focusOutlineColor, FALSE); } + if (folder_open) { gl_rect_2d(FOCUS_LEFT, @@ -810,7 +822,7 @@ void LLFolderViewItem::draw() drawOpenFolderArrow(default_params, sFgColor); - drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); //--------------------------------------------------------------------------------// // Draw open icon diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index d7f5e86aea..ca31931e19 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -128,6 +128,7 @@ protected: static LLUIColor sFgColor; static LLUIColor sFgDisabledColor; static LLUIColor sHighlightBgColor; + static LLUIColor sFlashBgColor; static LLUIColor sFocusOutlineColor; static LLUIColor sMouseOverColor; static LLUIColor sFilterBGColor; @@ -141,6 +142,8 @@ protected: virtual void addFolder(LLFolderViewFolder*) { } virtual bool isHighlightAllowed(); virtual bool isHighlightActive(); + virtual bool isFlashing() { return false; } + virtual void setFlashState(bool) { } static LLFontGL* getLabelFontForStyle(U8 style); @@ -269,7 +272,7 @@ public: // virtual void handleDropped(); virtual void draw(); void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color); - void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); + void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor); void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index c0a209f22d..d3a0e882f5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -101,7 +101,17 @@ LLConversationViewSession::~LLConversationViewSession() void LLConversationViewSession::setFlashState(bool flash_state) { mFlashStateOn = flash_state; - (flash_state ? mFlashTimer->startFlashing() : mFlashTimer->stopFlashing()); + mFlashStarted = false; + mFlashTimer->stopFlashing(); +} + +void LLConversationViewSession::startFlashing() +{ + if (mFlashStateOn && !mFlashStarted) + { + mFlashStarted = true; + mFlashTimer->startFlashing(); + } } bool LLConversationViewSession::isHighlightAllowed() @@ -198,8 +208,11 @@ void LLConversationViewSession::draw() drawOpenFolderArrow(default_params, sFgColor); } + // Indicate that flash can start (moot operation if already started, done or not flashing) + startFlashing(); + // draw highlight for selected items - drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, true, sHighlightBgColor, 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(this) || isOpen(); @@ -427,6 +440,7 @@ void LLConversationViewParticipant::draw() static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + static LLUIColor sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); @@ -450,7 +464,7 @@ void LLConversationViewParticipant::draw() color = mIsSelected ? sHighlightFgColor : sFgColor; } - drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); + drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); drawLabel(font, text_left, y, color, right_x); refresh(); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 1e20fb8b7e..74443e1d88 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -58,6 +58,7 @@ protected: /*virtual*/ bool isHighlightAllowed(); /*virtual*/ bool isHighlightActive(); + /*virtual*/ bool isFlashing() { return mFlashStateOn; } LLFloaterIMContainer* mContainer; @@ -83,11 +84,12 @@ public: virtual void refresh(); - void setFlashState(bool flash_state); + /*virtual*/ void setFlashState(bool flash_state); private: void onCurrentVoiceSessionChanged(const LLUUID& session_id); + void startFlashing(); LLPanel* mItemPanel; LLPanel* mCallIconLayoutPanel; @@ -95,6 +97,7 @@ private: LLOutputMonitorCtrl* mSpeakingIndicator; LLFlashTimer* mFlashTimer; bool mFlashStateOn; + bool mFlashStarted; bool mCollapsedMode; bool mHasArrow; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 05230b8bd5..becdbda067 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -11,6 +11,9 @@ + @@ -522,6 +525,9 @@ + -- cgit v1.2.3 From 6b9ead91459d702727b54ab7e51614c2d5959f5f Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Tue, 18 Dec 2012 23:07:27 -0800 Subject: CHUI-499: Refactoring the LLPersistentNotificationStorage implementation for shared usage with the new LLDoNotDisturbNotificationStorage class. --- indra/newview/llnotificationstorage.cpp | 69 +++++++++++++++++++++++ indra/newview/llnotificationstorage.h | 3 + indra/newview/llpersistentnotificationstorage.cpp | 67 +--------------------- 3 files changed, 73 insertions(+), 66 deletions(-) diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index d25a212059..4746e4bbd4 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -29,14 +29,39 @@ #include "llnotificationstorage.h" #include +#include #include "llerror.h" #include "llfile.h" +#include "llnotifications.h" #include "llpointer.h" #include "llsd.h" #include "llsdserialize.h" +#include "llsingleton.h" +#include "llviewermessage.h" +class LLResponderRegistry : public LLSingleton +{ +public: + LLResponderRegistry(); + ~LLResponderRegistry(); + + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams); + +protected: + +private: + template static LLNotificationResponderInterface* create(const LLSD& pParams); + + typedef boost::function responder_constructor_t; + + void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor); + + typedef std::map build_map_t; + build_map_t mBuildMap; +}; + LLNotificationStorage::LLNotificationStorage(std::string pFileName) : mFileName(pFileName) { @@ -90,3 +115,47 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const return didFileRead; } + +LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const +{ + return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); +} + +LLResponderRegistry::LLResponderRegistry() + : LLSingleton() + , mBuildMap() +{ + add("ObjectGiveItem", &create); + add("UserGiveItem", &create); +} + +LLResponderRegistry::~LLResponderRegistry() +{ +} + +LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + build_map_t::const_iterator it = mBuildMap.find(pNotificationName); + if(mBuildMap.end() == it) + { + return NULL; + } + responder_constructor_t ctr = it->second; + return ctr(pParams); +} + +template LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} + +void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor) +{ + if (mBuildMap.find(pNotificationName) != mBuildMap.end()) + { + LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL; + } + mBuildMap.insert(std::make_pair(pNotificationName, pConstructor)); +} diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index ab4da4e73f..7aabf7d09e 100644 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -31,6 +31,7 @@ #include "llerror.h" +class LLNotificationResponderInterface; class LLSD; class LLNotificationStorage @@ -44,6 +45,8 @@ protected: bool writeNotifications(const LLSD& pNotificationData) const; bool readNotifications(LLSD& pNotificationData) const; + LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const; + private: std::string mFileName; }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 7aaad64fd7..224aaa2146 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -36,34 +36,6 @@ #include "llscriptfloater.h" #include "llviewermessage.h" -class LLResponderRegistry -{ -public: - - static void registerResponders(); - - static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); - -protected: - -private: - template - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function responder_constructor_t; - - static void add(const std::string& notification_name, const responder_constructor_t& ctr); - - typedef std::map build_map_t; - - static build_map_t sBuildMap; -}; - LLPersistentNotificationStorage::LLPersistentNotificationStorage() : LLSingleton() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) @@ -114,7 +86,6 @@ static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); void LLPersistentNotificationStorage::loadNotifications() { LLFastTimer _(FTM_LOAD_NOTIFICATIONS); - LLResponderRegistry::registerResponders(); LLNotifications::instance().getChannel("Persistent")-> connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); @@ -144,8 +115,7 @@ void LLPersistentNotificationStorage::loadNotifications() LLSD notification_params = *notification_it; LLNotificationPtr notification(new LLNotification(notification_params)); - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); + LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); notification->setResponseFunctor(responder); instance.add(notification); @@ -172,39 +142,4 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay return false; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() -{ - sBuildMap.clear(); - - add("ObjectGiveItem", &create); - add("UserGiveItem", &create); -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) -{ - build_map_t::const_iterator it = sBuildMap.find(notification_name); - if(sBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(params); -} - -void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) -{ - if(sBuildMap.find(notification_name) != sBuildMap.end()) - { - llwarns << "Responder is already registered : " << notification_name << llendl; - llassert(!"Responder already registered"); - } - sBuildMap[notification_name] = ctr; -} - // EOF -- cgit v1.2.3 From bd6d34d312c3e3322ab62f3a60253fb88fcbc9e3 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Wed, 19 Dec 2012 01:48:37 -0800 Subject: CHUI-499: Loading the DND notifications upon exit from DND mode and after login. --- indra/newview/llagent.cpp | 14 ++-- indra/newview/llchannelmanager.cpp | 2 + indra/newview/llcommunicationchannel.cpp | 6 ++ indra/newview/llcommunicationchannel.h | 2 + .../newview/lldonotdisturbnotificationstorage.cpp | 76 ++++++++++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 49c570c30b..fc3be9ca21 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -41,6 +41,7 @@ #include "llchannelmanager.h" #include "llchicletbar.h" #include "llconsole.h" +#include "lldonotdisturbnotificationstorage.h" #include "llenvmanager.h" #include "llfirstuse.h" #include "llfloatercamera.h" @@ -1389,11 +1390,16 @@ BOOL LLAgent::getAFK() const //----------------------------------------------------------------------------- // setDoNotDisturb() //----------------------------------------------------------------------------- -void LLAgent::setDoNotDisturb(bool pIsDotNotDisturb) +void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) { - mIsDoNotDisturb = pIsDotNotDisturb; - sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP)); - LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDotNotDisturb); + bool isDoNotDisturbSwitchedOff = (mIsDoNotDisturb && !pIsDoNotDisturb); + mIsDoNotDisturb = pIsDoNotDisturb; + sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDoNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP)); + LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb); + if (isDoNotDisturbSwitchedOff) + { + LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); + } } //----------------------------------------------------------------------------- diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index dd2bcc742b..43757d0174 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -139,7 +139,9 @@ void LLChannelManager::onLoginCompleted() } LLPersistentNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->initialize(); + LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index 353447e4b6..4b0a70ffd8 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -39,6 +39,7 @@ LLCommunicationChannel::LLCommunicationChannel(const std::string& pName, const std::string& pParentName) : LLNotificationChannel(pName, pParentName, filterByDoNotDisturbStatus) + , mHistory() { } @@ -61,6 +62,11 @@ LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::e return mHistory.end(); } +void LLCommunicationChannel::clearHistory() +{ + mHistory.clear(); +} + void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) { std::string notificationType = pNotificationPtr->getType(); diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index a4756b8993..0e15e1cd15 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -46,6 +46,8 @@ public: typedef std::multimap history_list_t; history_list_t::const_iterator beginHistory() const; history_list_t::const_iterator endHistory() const; + + void clearHistory(); protected: virtual void onFilterFail(LLNotificationPtr pNotificationPtr); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 472a0dd9ee..43fd7705aa 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -29,14 +29,25 @@ #include "lldonotdisturbnotificationstorage.h" +#define XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT 0 + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llchannelmanager.h" +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llcommunicationchannel.h" #include "lldir.h" #include "llerror.h" #include "llfasttimer_class.h" #include "llnotifications.h" +#include "llnotificationhandler.h" #include "llnotificationstorage.h" +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llscreenchannel.h" +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT +#include "llscriptfloater.h" #include "llsd.h" #include "llsingleton.h" +#include "lluuid.h" LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton() @@ -85,6 +96,71 @@ static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notificati void LLDoNotDisturbNotificationStorage::loadNotifications() { + LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS); + + LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notifiations" << LL_ENDL; + + LLSD input; + if (!readNotifications(input) ||input.isUndefined()) + { + return; + } + + LLSD& data = input["data"]; + if (data.isUndefined()) + { + return; + } + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + LLNotificationsUI::LLScreenChannel* notification_channel = + dynamic_cast(LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + + LLNotifications& instance = LLNotifications::instance(); + + for (LLSD::array_const_iterator notification_it = data.beginArray(); + notification_it != data.endArray(); + ++notification_it) + { + LLSD notification_params = *notification_it; + LLNotificationPtr notification(new LLNotification(notification_params)); + + LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notification of type '" << notification->getType() << "'" << LL_ENDL; + + const LLUUID& notificationID = notification->id(); + if (instance.find(notificationID)) + { + instance.update(notification); + } + else + { + LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); + notification->setResponseFunctor(responder); + + instance.add(notification); + } + +#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + // hide script floaters so they don't confuse the user and don't overlap startup toast + LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); + + if(notification_channel) + { + // hide saved toasts so they don't confuse the user + notification_channel->hideToast(notification->getID()); + } +#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT + } + + // Clear the communication channel history and rewrite the save file to empty it as well + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); + llassert(commChannel != NULL); + commChannel->clearHistory(); + + saveNotifications(); } LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const -- cgit v1.2.3 From ca4c5d3bcb18afefc181bdc164d1c338abef7488 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Wed, 19 Dec 2012 11:28:38 -0800 Subject: Switching some notification types from "offer" to be "notify" as the notifications were not offers. --- indra/newview/skins/default/xui/en/notifications.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 35ce787847..05798da8e2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6583,7 +6583,7 @@ However, this region contains content accessible to adults only. log_to_im="true" log_to_chat="false" show_toast="false" - type="offer"> + type="notify"> Teleport offer sent to [TO_NAME] @@ -6636,7 +6636,7 @@ However, this region contains content accessible to adults only. name="FriendshipOffered" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> friendship You have offered friendship to [TO_NAME] @@ -6666,7 +6666,7 @@ However, this region contains content accessible to adults only. icon="notify.tga" name="FriendshipAccepted" log_to_im="true" - type="offer"> + type="notify"> friendship <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6686,7 +6686,7 @@ However, this region contains content accessible to adults only. name="FriendshipAcceptedByMe" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> friendship Friendship offer accepted. @@ -6696,7 +6696,7 @@ Friendship offer accepted. name="FriendshipDeclinedByMe" log_to_im="true" show_toast="false" - type="offer"> + type="notify"> friendship Friendship offer declined. -- cgit v1.2.3 From dcfcc191dd3caaa84d0f789a928a83adf55c13b1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 19 Dec 2012 12:45:59 -0800 Subject: Pull merge from richard/viewer-chui --- indra/newview/llconversationview.cpp | 1 + indra/newview/llimview.cpp | 14 +++++++------- indra/newview/skins/default/colors.xml | 3 --- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index d3a0e882f5..fdba5b7289 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -109,6 +109,7 @@ void LLConversationViewSession::startFlashing() { if (mFlashStateOn && !mFlashStarted) { + llinfos << "Merov debug : Start the flashing for " << getName() << llendl; mFlashStarted = true; mFlashTimer->startFlashing(); } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 5b4d5466a1..39f54dfd4d 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,6 +155,8 @@ void on_new_message(const LLSD& msg) } // execution of the action + llinfos << "Merov debug : on_new_message action = " << action << llendl; + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); @@ -174,13 +176,11 @@ void on_new_message(const LLSD& msg) if ("toast" == action) { // Skip toasting if we have open window of IM with this session id - if ( - session_floater + if (session_floater && session_floater->isInVisibleChain() && session_floater->hasFocus() && !session_floater->isMinimized() - && !(session_floater->getHost() - && session_floater->getHost()->isMinimized()) + && !(session_floater->getHost() && session_floater->getHost()->isMinimized()) ) { return; @@ -222,10 +222,10 @@ void on_new_message(const LLSD& msg) gToolBarView->flashCommand(LLCommandId("chat"), true); } //conversation floater is open but a different conversation is focused - else - { + //else + //{ im_box->flashConversationItemWidget(session_id, true); - } + //} } } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index c3df04d0a6..becdbda067 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -11,9 +11,6 @@ - -- cgit v1.2.3 From ef6121cba1c72549cca10763645254ae3aaf2887 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Wed, 19 Dec 2012 15:37:12 -0800 Subject: CHUI-499: Code clean-up and adding some more types badly defined. --- indra/newview/lldonotdisturbnotificationstorage.cpp | 17 +++++++++++------ indra/newview/llnotificationstorage.cpp | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 43fd7705aa..bf3dcae1f3 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -98,8 +98,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS); - LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notifiations" << LL_ENDL; - LLSD input; if (!readNotifications(input) ||input.isUndefined()) { @@ -127,8 +125,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() LLSD notification_params = *notification_it; LLNotificationPtr notification(new LLNotification(notification_params)); - LL_INFOS("stinsonDebug") << "STINSON DEBUG: loading notification of type '" << notification->getType() << "'" << LL_ENDL; - const LLUUID& notificationID = notification->id(); if (instance.find(notificationID)) { @@ -136,8 +132,17 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } else { - LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"])); - notification->setResponseFunctor(responder); + LLNotificationResponderInterface* responder = createResponder(notification_params["name"], notification_params["responder"]); + if (responder == NULL) + { + LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" + << notification->getType() << "'" << LL_ENDL; + } + else + { + LLNotificationResponderPtr responderPtr(responder); + notification->setResponseFunctor(responderPtr); + } instance.add(notification); } diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 4746e4bbd4..b797775369 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -126,7 +126,13 @@ LLResponderRegistry::LLResponderRegistry() , mBuildMap() { add("ObjectGiveItem", &create); + add("OwnObjectGiveItem", &create); add("UserGiveItem", &create); + + add("TeleportOffered", &create); + add("TeleportOffered_MaturityExceeded", &create); + + add("OfferFriendship", &create); } LLResponderRegistry::~LLResponderRegistry() -- cgit v1.2.3 From c81cf89086b0282121c6577b6fde75e050c1a0e8 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 19 Dec 2012 17:10:31 -0800 Subject: CHUI-600 : Fix the orange (provided by Leo), fix the conversation item flashing (when shown) --- indra/newview/llconversationview.cpp | 6 ++++-- indra/newview/llfloaterimcontainer.cpp | 25 ++++++++++++++----------- indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llimview.cpp | 3 --- indra/newview/skins/default/colors.xml | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index fdba5b7289..e51efd48f5 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -81,7 +81,9 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mSpeakingIndicator(NULL), mVoiceClientObserver(NULL), mCollapsedMode(false), - mHasArrow(true) + mHasArrow(true), + mFlashStateOn(false), + mFlashStarted(false) { mFlashTimer = new LLFlashTimer(); } @@ -109,7 +111,6 @@ void LLConversationViewSession::startFlashing() { if (mFlashStateOn && !mFlashStarted) { - llinfos << "Merov debug : Start the flashing for " << getName() << llendl; mFlashStarted = true; mFlashTimer->startFlashing(); } @@ -245,6 +246,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) if(result && getRoot()->getCurSelectedItem() == this) { LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); + im_container->clearAllFlashStates(); im_container->selectConversationPair(session_id, false); im_container->collapseMessagesPane(false); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 390eec84f6..58ba186b57 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1229,6 +1229,20 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) selectConversationPair(session_id, true); } +void LLFloaterIMContainer::clearAllFlashStates() +{ + llinfos << "Merov debug : clear all flash states" << llendl; + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (;widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast(widget_it->second); + if (widget) + { + widget->setFlashState(false); + } + } +} + void LLFloaterIMContainer::selectConversation(const LLUUID& session_id) { selectConversationPair(session_id, true); @@ -1240,17 +1254,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - // On selection, stop the flash state on all conversation widgets - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - for (;widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast(widget_it->second); - if (widget) - { - widget->setFlashState(false); - } - } - /* widget processing */ if (select_widget) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 5db1565cea..09a24c0105 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -69,6 +69,7 @@ public: void showConversation(const LLUUID& session_id); void selectConversation(const LLUUID& session_id); BOOL selectConversationPair(const LLUUID& session_id, bool select_widget); + void clearAllFlashStates(); /*virtual*/ void tabClose(); void showStub(bool visible); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 39f54dfd4d..65048e352e 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -155,9 +155,6 @@ void on_new_message(const LLSD& msg) } // execution of the action - llinfos << "Merov debug : on_new_message action = " << action << llendl; - - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index becdbda067..0de217fc0d 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -13,7 +13,7 @@ value="0.38 0.694 0.573 0.35" /> + value="0.749 0.298 0 1" /> -- cgit v1.2.3 From b15ba74485e24db9a996a2f6a9438ac48224ea7a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 19 Dec 2012 17:19:48 -0800 Subject: CHUI-607: Due to a problem in design we have two checkboxes that determine whether a conversation transcript should be saved. By defaut commiting a change that makes both checkboxes checked by default. This makes it so that a new user can see their transcript/chat history. --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24fa0a0cd4..ebc915ec5a 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4676,7 +4676,7 @@ Type Boolean Value - 0 + 1 LandBrushSize -- cgit v1.2.3 From ba297b167f75d8a09c959952a300d492f2aec88b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 19 Dec 2012 20:07:08 -0800 Subject: CHUI-600 : Fixed! Modified the button flash state so it sticks after the animation and is dismissed on toggle --- indra/llui/llbutton.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 99384439d2..7ca9b869a8 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -311,7 +311,7 @@ void LLButton::onCommit() { make_ui_sound("UISndClickRelease"); } - + if (mIsToggle) { toggleState(); @@ -613,10 +613,6 @@ void LLButton::draw() static LLCachedControl sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - if (mFlashingTimer) - { - mFlashing = mFlashingTimer->isFlashingInProgress(); - } bool flash = mFlashing && sEnableButtonFlashing; bool pressed_by_keyboard = FALSE; @@ -701,7 +697,8 @@ void LLButton::draw() imagep = mImageDisabled; } - if (mFlashing) + // Selected has a higher priority than flashing. If both are set, flashing is ignored. + if (mFlashing && !selected) { // if button should flash and we have icon for flashing, use it as image for button if(flash && mImageFlash) @@ -711,13 +708,13 @@ void LLButton::draw() imagep = mImageFlash; } // else use usual flashing via flash_color - else + else if (mFlashingTimer) { LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow - if (mFlashingTimer->isCurrentlyHighlighted()) + if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress()) { glow_color = flash_color; } @@ -773,8 +770,7 @@ void LLButton::draw() if (use_glow_effect) { mCurGlowStrength = lerp(mCurGlowStrength, - mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || mNeedsHighlight? 1.0 : 0.0) - : mHoverGlowStrength, + mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); } else @@ -961,23 +957,18 @@ void LLButton::setToggleState(BOOL b) { setControlValue(b); // will fire LLControlVariable callbacks (if any) setValue(b); // may or may not be redundant + setFlashing(false); // stop flash state whenever the selected/unselected state if reset // Unselected label assignments autoResize(); } } -void LLButton::setFlashing( bool b ) +void LLButton::setFlashing(bool b) { if (mFlashingTimer) { - if (b) - { - mFlashingTimer->startFlashing(); - } - else - { - mFlashingTimer->stopFlashing(); - } + mFlashing = b; + (b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing()); } else if (b != mFlashing) { -- cgit v1.2.3 From ed716d996987722c32a105fac79daf1af4e5fb23 Mon Sep 17 00:00:00 2001 From: MaximB ProductEngine Date: Thu, 20 Dec 2012 09:42:34 +0200 Subject: CHUI-588 (Clicking nearby chat toast doesn't highlight proper conversation line item) --- indra/newview/llfloaterimsessiontab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 7984034ded..53d2f31b79 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -308,7 +308,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance("im_container"); if (container) { - container->selectConversationPair(mSessionID, ! getHost()); + container->selectConversationPair(mSessionID, true); container->showStub(! getHost()); } } -- cgit v1.2.3 From eb68845767309900b6b5915f6358ae5027fb7136 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 20 Dec 2012 15:01:50 +0200 Subject: CHUI-606 Default settings in CHUI viewer do not keep IM logs for users: Preferences > Chat > Keep a convers. log was turned on --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24fa0a0cd4..ebc915ec5a 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4676,7 +4676,7 @@ Type Boolean Value - 0 + 1 LandBrushSize -- cgit v1.2.3 From c81a0b0a5701425aa52521d8600a280d05040517 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Thu, 20 Dec 2012 15:23:36 +0200 Subject: CHUI-602 FIXED Don't call getUUID() if there is no selected participants --- indra/newview/llfloaterimcontainer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 58ba186b57..92ea6dacde 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,7 +1101,14 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); - if("can_activate_group" == item) + + // If nothing is selected, everything needs to be disabled + if (uuids.size() <= 0) + { + return false; + } + + if("can_activate_group" == item) { LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); return gAgent.getGroupID() != selected_group_id; @@ -1116,12 +1123,6 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); } - - // If nothing is selected, everything needs to be disabled - if (uuids.size() <= 0) - { - return false; - } // Extract the single select info bool is_single_select = (uuids.size() == 1); -- cgit v1.2.3 From 2aefdb47ca1d02bfe8b74928dee479072ef151a3 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 20 Dec 2012 15:24:14 +0200 Subject: CHUI-618 User sees no indication of offline messages received with conversation log preference turned off: flashing of CHUI button if offline messages was received --- indra/newview/llimview.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 65048e352e..cdc51ad2fc 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2488,16 +2488,23 @@ void LLIMMgr::addMessage( } // Open conversation log if offline messages are present and user allows a Call Log - if (is_offline_msg && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - LLFloaterConversationLog* floater_log = - LLFloaterReg::getTypedInstance("conversation"); - if (floater_log && !(floater_log->isFrontmost())) + if (is_offline_msg) + { + if (gSavedSettings.getBOOL("KeepConversationLogTranscripts")) { - floater_log->openFloater(); - floater_log->setFrontmost(TRUE); + LLFloaterConversationLog* floater_log = + LLFloaterReg::getTypedInstance("conversation"); + if (floater_log && !(floater_log->isFrontmost())) + { + floater_log->openFloater(); + floater_log->setFrontmost(TRUE); + } } - } + else + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + } //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; -- cgit v1.2.3 From cbf24c55d511b2390fdc4c12698682531f26f41b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 20 Dec 2012 10:27:18 -0500 Subject: SH-3344 WIP - additional debugging output for avatar local textures --- indra/llrender/llgltexture.h | 19 +++++---- indra/newview/llviewertexture.cpp | 1 + indra/newview/llviewertexture.h | 2 + indra/newview/llvoavatar.cpp | 4 +- indra/newview/llvoavatarself.cpp | 85 +++++++++++++++++++++++++++++++++++++++ indra/newview/llvoavatarself.h | 1 + 6 files changed, 103 insertions(+), 9 deletions(-) diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index b1efe77519..e69b322d60 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -79,6 +79,15 @@ public: MAX_GL_IMAGE_CATEGORY }; + typedef enum + { + DELETED = 0, //removed from memory + DELETION_CANDIDATE, //ready to be removed from memory + INACTIVE, //not be used for the last certain period (i.e., 30 seconds). + ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). + NO_DELETE = 99 //stay in memory, can not be removed. + } LLGLTextureState; + static S32 getTotalNumOfCategories() ; static S32 getIndexFromCategory(S32 category) ; static S32 getCategoryFromIndex(S32 index) ; @@ -143,6 +152,8 @@ public: U32 getTexelsInGLTexture() const ; BOOL isGLTextureCreated() const ; S32 getDiscardLevelInAtlas() const ; + LLGLTextureState getTextureState() const { return mTextureState; } + //--------------------------------------------------------------------------------------------- //end of functions to access LLImageGL //--------------------------------------------------------------------------------------------- @@ -179,14 +190,6 @@ protected: S8 mDontDiscard; // Keep full res version of this image (for UI, etc) protected: - typedef enum - { - DELETED = 0, //removed from memory - DELETION_CANDIDATE, //ready to be removed from memory - INACTIVE, //not be used for the last certain period (i.e., 30 seconds). - ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). - NO_DELETE = 99 //stay in memory, can not be removed. - } LLGLTextureState; LLGLTextureState mTextureState ; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 846216211e..a673862882 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -616,6 +616,7 @@ LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : LLViewerTexture::~LLViewerTexture() { + // LL_DEBUGS("Avatar") << mID << llendl; cleanup(); sImageCount--; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 3df942d922..ba6beec883 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -134,6 +134,7 @@ public: void resetTextureStats(); void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;} + S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; } virtual F32 getMaxVirtualSize() ; @@ -306,6 +307,7 @@ public: // the priority list, and cause horrible things to happen. void setDecodePriority(F32 priority = -1.0f); F32 getDecodePriority() const { return mDecodePriority; }; + F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; }; void setAdditionalDecodePriority(F32 priority) ; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 117f28cc36..086e4306f8 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5811,6 +5811,7 @@ void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) // virtual void LLVOAvatar::updateMeshTextures() { + static S32 update_counter = 0; mBakedTextureDebugText.clear(); // if user has never specified a texture, assign the default @@ -5840,7 +5841,8 @@ void LLVOAvatar::updateMeshTextures() std::vector use_lkg_baked_layer; // lkg = "last known good" use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false); - mBakedTextureDebugText += "indx layerset linvld ltda ilb ulkg ltid\n"; + mBakedTextureDebugText += llformat("%06d\n",update_counter++); + mBakedTextureDebugText += "indx layerset linvld ltda ilb ulkg ltid\n"; for (U32 i=0; i < mBakedTextureDatas.size(); i++) { is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 77deb5e3bc..674988d94b 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -176,6 +176,17 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, lldebugs << "Marking avatar as self " << id << llendl; } +// Called periodically for diagnostics, return true when done. +bool output_texture_diagnostics() +{ + if (!isAgentAvatarValid()) + return true; // done checking + + gAgentAvatarp->outputRezDiagnostics(); + + return false; +} + void LLVOAvatarSelf::initInstance() { BOOL status = TRUE; @@ -209,6 +220,8 @@ void LLVOAvatarSelf::initInstance() llerrs << "Unable to load user's avatar" << llendl; return; } + + //doPeriodically(output_texture_diagnostics, 30.0); } // virtual @@ -2008,6 +2021,64 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); } +const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const +{ + std::ostringstream outbuf; + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + outbuf << "baked_index: " << baked_index << "\n"; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + outbuf << " tex_index " << (S32) tex_index << "\n"; + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << "\n"; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); + if (local_tex_obj) + { + LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); + if (tex_index >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !image->isMissingAsset()) + { + outbuf << " id: " << image->getID() + << " refs: " << image->getNumRefs() + << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) + << " discard: " << image->getDiscardLevel() + << " desired: " << image->getDesiredDiscardLevel() + << " decode: " << image->getDecodePriority() + << " addl: " << image->getAdditionalDecodePriority() + << " ts: " << image->getTextureState() + << " bl: " << image->getBoostLevel() + << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. + << " mvs: " << image->getMaxVirtualSize() + << " mvsc: " << image->getMaxVirtualSizeResetCounter() + << "\n"; + } + } + } + } + } + break; + } + } + return outbuf.str(); +} + const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; @@ -2282,6 +2353,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + // DRANO what priority should wearable-based textures have? if (isUsingLocalAppearance()) { imagep->setBoostLevel(getAvatarBoostLevel()); @@ -2466,6 +2538,19 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset_buffer) continue; LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } + std::string vd_text = "Local textures per baked index and wearable:\n"; + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); + } + LL_DEBUGS("Avatar") << vd_text << llendl; } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index eeac5ddaeb..02612b83da 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -390,6 +390,7 @@ public: BOOL isAllLocalTextureDataFinal() const; const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return (LLViewerTexLayerSet*)(mBakedTextureDatas[index].mTexLayerSet); } + const std::string verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD LLSD metricsData(); -- cgit v1.2.3 From 95380b0aaa635c18c03801048559ba811640bc02 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 20 Dec 2012 22:37:04 +0200 Subject: CHUI-513 FIXED Revise initial conversation floater size --- indra/newview/app_settings/settings_per_account.xml | 2 +- indra/newview/skins/default/xui/en/floater_im_container.xml | 7 ++----- indra/newview/skins/default/xui/en/floater_im_session.xml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index ca22041671..4ff494fbfb 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -53,7 +53,7 @@ Type S32 Value - 268 + 205 ConversationsMessagePaneCollapsed diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 3475c7da33..cbf1830093 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -3,9 +3,8 @@ can_close="true" can_minimize="true" can_resize="true" - height="230" + height="210" layout="topleft" - min_height="50" name="floater_im_box" help_topic="floater_im_box" save_rect="true" @@ -15,7 +14,7 @@ title="CONVERSATIONS" bottom="-50" right="-5" - width="500"> + width="450"> @@ -37,7 +36,6 @@ user_resize="true" name="conversations_layout_panel" min_dim="38" - width="225" expanded_min_dim="156"> + min_width="221"> Date: Thu, 20 Dec 2012 18:36:01 -0800 Subject: CHUI-429 : Fixed! Add a flag to filter multi/single selection situations in menu building. Implement in conversation contextual menu. --- indra/llui/llfolderview.cpp | 5 +- indra/llui/llfolderview.h | 1 + indra/newview/llconversationmodel.cpp | 67 ++++++++++++---------- indra/newview/llconversationmodel.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 1 - .../skins/default/xui/en/menu_conversation.xml | 7 +++ 6 files changed, 50 insertions(+), 33 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index a33ffc4240..7ae79d94fe 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1913,14 +1913,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) // Successively filter out invalid options - U32 flags = FIRST_SELECTED_ITEM; + U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); + U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor) { LLFolderViewItem* selected_item = (*item_itor); selected_item->buildContextMenu(*menu, flags); - flags = 0x0; + flags = multi_select_flag; } addNoOptions(menu); diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index d4a1434c73..2ee7417240 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -400,5 +400,6 @@ public: // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; +const U32 ITEM_IN_MULTI_SELECTION = 0x4; #endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index d03ad92fbc..005439301a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -102,35 +102,44 @@ void LLConversationItem::showProperties(void) { } -void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) -{ - items.push_back(std::string("view_profile")); - items.push_back(std::string("im")); - items.push_back(std::string("offer_teleport")); - items.push_back(std::string("voice_call")); - items.push_back(std::string("chat_history")); - items.push_back(std::string("separator_chat_history")); - items.push_back(std::string("add_friend")); - items.push_back(std::string("remove_friend")); - items.push_back(std::string("invite_to_group")); - items.push_back(std::string("separator_invite_to_group")); - items.push_back(std::string("map")); - items.push_back(std::string("share")); - items.push_back(std::string("pay")); - items.push_back(std::string("block_unblock")); - items.push_back(std::string("MuteText")); - - if(this->getType() != CONV_SESSION_1_ON_1 && mDisplayModeratorOptions) +void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags) +{ + if (flags & ITEM_IN_MULTI_SELECTION) { - items.push_back(std::string("Moderator Options Separator")); - items.push_back(std::string("Moderator Options")); - items.push_back(std::string("AllowTextChat")); - items.push_back(std::string("moderate_voice_separator")); - items.push_back(std::string("ModerateVoiceToggleMuteSelected")); - items.push_back(std::string("ModerateVoiceMute")); - items.push_back(std::string("ModerateVoiceUnmute")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("remove_friends")); + } + else + { + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); + items.push_back(std::string("MuteText")); + + if ((getType() != CONV_SESSION_1_ON_1) && mDisplayModeratorOptions) + { + items.push_back(std::string("Moderator Options Separator")); + items.push_back(std::string("Moderator Options")); + items.push_back(std::string("AllowTextChat")); + items.push_back(std::string("moderate_voice_separator")); + items.push_back(std::string("ModerateVoiceToggleMuteSelected")); + items.push_back(std::string("ModerateVoiceMute")); + items.push_back(std::string("ModerateVoiceUnmute")); + } } - } // @@ -306,7 +315,7 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("close_conversation")); items.push_back(std::string("separator_disconnect_from_voice")); - buildParticipantMenuOptions(items); + buildParticipantMenuOptions(items, flags); } else if(this->getType() == CONV_SESSION_GROUP) { @@ -440,7 +449,7 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - buildParticipantMenuOptions(items); + buildParticipantMenuOptions(items, flags); hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 743a6ba40b..02002d8f70 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -130,7 +130,7 @@ public: void postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant); - void buildParticipantMenuOptions(menuentry_vec_t& items); + void buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags); protected: std::string mName; // Name of the session or the participant diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 92ea6dacde..2019a35faa 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1232,7 +1232,6 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id) void LLFloaterIMContainer::clearAllFlashStates() { - llinfos << "Merov debug : clear all flash states" << llendl; conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); for (;widget_it != mConversationsWidgets.end(); ++widget_it) { diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index e0edf384d6..46c6e19fa5 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -75,6 +75,13 @@ + + + + Date: Thu, 20 Dec 2012 19:57:51 +0200 Subject: CHUI-605 : Fixed : Keep conversation log requires restart to change preference: connected LLConversationLog::enableLogging() as listener to "LogInstantMessages" control changes --- indra/newview/llconversationlog.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 1171b3db41..eb3a3731ee 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -187,16 +187,23 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() { - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - if (ctrl) + LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); + LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + bool is_log_message = false; + bool is_keep_log = false; + + if (log_instant_message) { - ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - if (ctrl->getValue().asBoolean() - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - enableLogging(true); - } + log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + is_log_message = log_instant_message->getValue().asBoolean(); } + if (keep_convers_log) + { + keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + is_keep_log = keep_convers_log->getValue().asBoolean(); + } + + enableLogging(is_log_message && is_keep_log); } void LLConversationLog::enableLogging(bool enable) -- cgit v1.2.3 From 2f7901ab929e90748e38734555cb861a2645f256 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 20 Dec 2012 21:33:30 +0000 Subject: Skipping rendering of unneeded morph masks --- indra/llappearance/lltexlayer.cpp | 34 ++++++++++++++++++++++++---------- indra/llappearance/lltexlayer.h | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 6e184beac8..15d531259f 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1136,7 +1136,8 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) } }//*/ - renderMorphMasks(x, y, width, height, net_color); + const bool force_render = true; + renderMorphMasks(x, y, width, height, net_color, force_render); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1385,8 +1386,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) } static LLFastTimer::DeclareTimer FTM_RENDER_MORPH_MASKS("renderMorphMasks"); -BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) { + if (!force_render && !hasMorph()) + { + lldebugs << "skipping renderMorphMasks for " << getUUID() << llendl; + return; + } LLFastTimer t(FTM_RENDER_MORPH_MASKS); BOOL success = TRUE; @@ -1423,6 +1429,11 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { LLTexLayerParamAlpha* param = *iter; success &= param->render( x, y, width, height ); + if (!success && !force_render) + { + lldebugs << "Failed to render param " << param->getID() << " ; skipping morph mask." << llendl; + return; + } } // Approximates a min() function @@ -1448,25 +1459,29 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } } - if( !getInfo()->mStaticImageFileName.empty() ) + if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask ) { LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { - if( (tex->getComponents() == 4) || - ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) + if( (tex->getComponents() == 4) || (tex->getComponents() == 1) ) { LLGLSNoAlphaTest gls_no_alpha_test; gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } + else + { + llwarns << "Skipping rendering of " << getInfo()->mStaticImageFileName + << "; expected 1 or 4 components." << llendl; + } } } // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if (layer_color.mV[VW] != 1.f) + if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) { LLGLDisable no_alpha(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1519,8 +1534,6 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC mMorphMasksValid = TRUE; getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); } - - return success; } static LLFastTimer::DeclareTimer FTM_ADD_ALPHA_MASK("addAlphaMask"); @@ -1535,7 +1548,8 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 findNetColor( &net_color ); // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); - renderMorphMasks(originX, originY, width, height, net_color); + const bool force_render = false; + renderMorphMasks(originX, originY, width, height, net_color, force_render); alphaData = getAlphaData(); } if (alphaData) @@ -1544,7 +1558,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 { U8 curAlpha = data[i]; U16 resultAlpha = curAlpha; - resultAlpha *= (alphaData[i] + 1); + resultAlpha *= ( ((U16)alphaData[i]) + 1); resultAlpha = resultAlpha >> 8; data[i] = (U8)resultAlpha; } diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 405d2c7df4..959d6e499a 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -160,7 +160,7 @@ public: BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render); void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); /*virtual*/ BOOL isInvisibleAlphaMask() const; -- cgit v1.2.3 From e1af26eaa2e3d065129821fe1e9458fa2698d72e Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 20 Dec 2012 21:39:33 +0000 Subject: Disabling build of headless appearance utility --- autobuild.xml | 4 ++-- indra/cmake/Variables.cmake | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 098140db85..3c503997cc 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@ archive hash - 8180c6f8d96a76c0c4b7746eb9e98964 + 17bcc2481fe362e297376d9c46888de8 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/268052/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121212.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/268501/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121220.tar.bz2 name linux diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 54c77da64e..6ec621632b 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -118,10 +118,10 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if (INSTALL_PROPRIETARY) # Only turn on headless if we can find osmesa libraries. include(FindPkgConfig) - pkg_check_modules(OSMESA osmesa) - if (OSMESA_FOUND) - set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") - endif (OSMESA_FOUND) + #pkg_check_modules(OSMESA osmesa) + #if (OSMESA_FOUND) + # set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") + #endif (OSMESA_FOUND) endif (INSTALL_PROPRIETARY) endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") -- cgit v1.2.3 From 2610af9798374ce9fff7623d7aa7e269b2a78174 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 21 Dec 2012 15:35:56 +0200 Subject: CHUI-619 FUI button and conversation line items blink at different rates: changed rate --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llimview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ebc915ec5a..507eb33f2d 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13173,7 +13173,7 @@ Type F32 Value - 0.25 + 0.5 WindLightUseAtmosShaders diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cdc51ad2fc..708400cbe1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -964,7 +964,7 @@ const std::string LLIMModel::getName(const LLUUID& session_id) const { LLIMSession* session = findIMSession(session_id); - if (!session) + if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; return LLTrans::getString("no_session_message"); -- cgit v1.2.3 From 7549a392cc32dc36f0bc673a6569f01731cc1bbd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 21 Dec 2012 16:28:33 +0200 Subject: CHUI-566 Flashing and color on Conversations FUI button and conversation line item: change behavior for the case "If conversations (container) floater open but not on top" --- indra/newview/llimview.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 708400cbe1..d736b81bb7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -160,6 +160,7 @@ void on_new_message(const LLSD& msg) //session floater not focused (visible or not) bool session_floater_not_focused = session_floater && !session_floater->hasFocus(); + //conv. floater is closed bool conversation_floater_is_closed = !( im_box @@ -210,20 +211,16 @@ void on_new_message(const LLSD& msg) else if ("flash" == action) { - if (session_floater_not_focused) + if (conversation_floater_not_focused) { - //User is not focused on conversation containing the message - - if(conversation_floater_not_focused) + if(session_floater_not_focused) { + //User is not focused on conversation containing the message gToolBarView->flashCommand(LLCommandId("chat"), true); } - //conversation floater is open but a different conversation is focused - //else - //{ - im_box->flashConversationItemWidget(session_id, true); - //} - } + + im_box->flashConversationItemWidget(session_id, true); + } } else if("openconversations" == action) -- cgit v1.2.3 From 765a5a73dd3e2e7a88141e26f4aa7b479229ad2e Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 21 Dec 2012 16:45:58 +0200 Subject: CHUI-621 FIXED Notification chiclet UI error --- indra/newview/llchiclet.cpp | 2 +- .../skins/default/textures/bottomtray/Notices_Unread.png | Bin 0 -> 3693 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 indra/newview/skins/default/textures/bottomtray/Notices_Unread.png diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 2fdcb17570..3dbb43c657 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -76,7 +76,7 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) LLSysWellChiclet::~LLSysWellChiclet() { - delete mFlashToLitTimer; + mFlashToLitTimer->unset(); } void LLSysWellChiclet::setCounter(S32 counter) diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png new file mode 100644 index 0000000000..0ac5b72b8f Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png differ -- cgit v1.2.3 From dd7509f56de5e8a47680b33176e90c11ed518066 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 21 Dec 2012 20:05:40 +0200 Subject: CHUI-411 Entries in chat history viewer do not show all dates of entries and some entries show on multiple pages Type of variable for the time saving was changed from S32 to long int ("capacity" of S32-timer is only ~18 hours!) --- indra/newview/llconversationlog.cpp | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index eb3a3731ee..e44749fd79 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -236,17 +236,20 @@ void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offli const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); LLConversation* conversation = findConversation(session); - if (session && conversation) + if (session) { - if(has_offline_msg) + if (conversation) { - updateOfflineIMs(session, has_offline_msg); + if(has_offline_msg) + { + updateOfflineIMs(session, has_offline_msg); + } + updateConversationTimestamp(conversation); + } + else + { + createConversation(session); } - updateConversationTimestamp(conversation); - } - else if (session && !conversation) - { - createConversation(session); } } @@ -307,19 +310,17 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation LLConversation* LLConversationLog::findConversation(const LLIMModel::LLIMSession* session) { - if (!session) + if (session) { - return NULL; - } + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; - - conversations_vec_t::iterator conv_it = mConversations.begin(); - for(; conv_it != mConversations.end(); ++conv_it) - { - if (conv_it->getSessionID() == session_id) + conversations_vec_t::iterator conv_it = mConversations.begin(); + for(; conv_it != mConversations.end(); ++conv_it) { - return &*conv_it; + if (conv_it->getSessionID() == session_id) + { + return &*conv_it; + } } } @@ -411,8 +412,8 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| - fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", - (S32)conv_it->getTime(), + fprintf(fp, "[%ld] %d %d %d %s| %s %s %s|\n", + conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, (S32)conv_it->hasOfflineMessages(), @@ -446,7 +447,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char history_file_name[MAX_STRING]; int has_offline_ims; int stype; - S32 time; + time_t time; // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; @@ -456,7 +457,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) part_id_buffer[0] = '\0'; conv_id_buffer[0] = '\0'; - sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", + sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, &prereserved_unused, -- cgit v1.2.3 From 6df0377d1dd810cc1656c6c2664af2c7c87705fc Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 21 Dec 2012 20:11:01 +0200 Subject: CHUI-622 FIXED Default size of conversation log floater seems large --- .../default/xui/en/floater_conversation_log.xml | 163 ++++++++++----------- 1 file changed, 80 insertions(+), 83 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index c9c52e5ce5..960db137b3 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -1,91 +1,88 @@ - + can_resize="true" + positioning="cascading" + height="200" + min_height="100" + min_width="200" + layout="topleft" + name="floater_conversation_log" + save_rect="true" + single_instance="true" + reuse_instance="true" + title="CONVERSATION LOG" + width="300"> Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. - - - - - - - + + + + + + - + allow_select="true" + bottom="-8" + opaque="true" + follows="all" + left="8" + keep_selection_visible_on_reshape="true" + item_pad="2" + multi_select="false" + name="conversation_log_list" + right="-8" + top="0" /> + -- cgit v1.2.3 From 923262f154748eea5ce1eda37df1b9df1eaf0f43 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Mon, 24 Dec 2012 14:20:25 +0200 Subject: CHUI-583 FIXED Link will be opened in external browser if this preference is set. --- indra/newview/llviewermenu.cpp | 15 +++++++++++++++ indra/newview/skins/default/xui/en/menu_viewer.xml | 14 +++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index fe9c00cc27..be9f7d645a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7586,6 +7586,20 @@ void handle_web_content_test(const LLSD& param) LLWeb::loadURLInternal(url); } +void handle_show_url(const LLSD& param) +{ + std::string url = param.asString(); + if(gSavedSettings.getBOOL("UseExternalBrowser")) + { + LLWeb::loadURLExternal(url); + } + else + { + LLWeb::loadURLInternal(url); + } + +} + void handle_buy_currency_test(void*) { std::string url = @@ -8415,6 +8429,7 @@ void initialize_menus() // Advanced > UI commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater + commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 00424e97f6..76de81559b 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1273,35 +1273,35 @@ label="User’s guide" name="User’s guide"> @@ -1309,14 +1309,14 @@ label="[SECOND_LIFE] News" name="Second Life News"> -- cgit v1.2.3 From 32944ef9e41a96950aa645a016c8f2c6bf71a351 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Mon, 24 Dec 2012 19:01:27 +0200 Subject: CHUI-627 FIXED Unnecessary attributes are deleted in xml --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index 960db137b3..cf61348a66 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -17,12 +17,10 @@ Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy. Date: Tue, 25 Dec 2012 21:16:30 +0200 Subject: CHUI-623 FIXED No vertical scrollbar in conversation list --- indra/newview/skins/default/xui/en/floater_im_container.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index cbf1830093..e7638fe669 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -113,11 +113,12 @@ @@ -127,7 +128,7 @@ name="messages_layout_panel" expanded_min_dim="222"> Date: Wed, 26 Dec 2012 11:23:59 +0200 Subject: CHUI-632 FIXED Disable Gear button if nothing is selected --- indra/newview/llpanelblockedlist.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index ecab7d2167..df1ccdd9fc 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -137,6 +137,7 @@ void LLPanelBlockedList::updateButtons() { bool hasSelected = NULL != mBlockedList->getSelectedItem(); getChildView("unblock_btn")->setEnabled(hasSelected); + getChildView("blocked_gear_btn")->setEnabled(hasSelected); } void LLPanelBlockedList::unblockItem() -- cgit v1.2.3 From d05df4087c334fe30a9d0fe5224a828c677d0244 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 26 Dec 2012 11:46:29 +0200 Subject: CHUI-617 FIXED Update Gear button state after initing session. mConversationsRoot creation is moved to postBuild(). --- indra/newview/llfloaterimsession.cpp | 4 +-- indra/newview/llfloaterimsessiontab.cpp | 44 ++++++++++++++------------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index ff07ddfcbf..d36b138c21 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -86,7 +86,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&LLFloaterIMSession::GearDoToSelected, this, _2)); mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&LLFloaterIMSession::checkGearMenuItem, this, _2)); - setDocked(true); + setDocked(true); } @@ -754,7 +754,7 @@ void LLFloaterIMSession::sessionInitReplyReceived(const LLUUID& im_session_id) } initIMFloater(); - + LLFloaterIMSessionTab::updateGearBtn(); //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messages collected while waiting for session initialization diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 53d2f31b79..f5b657fa60 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -240,7 +240,24 @@ BOOL LLFloaterIMSessionTab::postBuild() result = LLDockableFloater::postBuild(); } - // Now ready to build the conversation and participants list + // Create the root using an ad-hoc base item + LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + p.options_menu = "menu_conversation.xml"; + mConversationsRoot = LLUICtrlFactory::create(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Attach that root to the scroller + mScroller->addChild(mConversationsRoot); + mConversationsRoot->setScrollContainer(mScroller); + mConversationsRoot->setFollowsAll(); + mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); + buildConversationViewParticipant(); refreshConversation(); @@ -388,31 +405,6 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() return; } - // Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture - // We need to redo this when rebuilding as the session id (mSessionID) *may* have changed - if (mConversationsRoot) - { - // Remove the old root if any - mScroller->removeChild(mConversationsRoot); - } - // Create the root using an ad-hoc base item - LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - p.options_menu = "menu_conversation.xml"; - mConversationsRoot = LLUICtrlFactory::create(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); - // Attach that root to the scroller - mScroller->addChild(mConversationsRoot); - mConversationsRoot->setScrollContainer(mScroller); - mConversationsRoot->setFollowsAll(); - mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); - // Create the participants widgets now LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); -- cgit v1.2.3 From 099c9bcc6ffd9760cf935b6bcff8d796d0dff09d Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 26 Dec 2012 20:25:56 +0200 Subject: CHUI-629 FIXED Windows crash on exit when closing viewer with conversation log open with unread offline messages --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index e44749fd79..0479733706 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -412,7 +412,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| - fprintf(fp, "[%ld] %d %d %d %s| %s %s %s|\n", + fprintf(fp, "[%lld] %d %d %d %s| %s %s %s|\n", conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, -- cgit v1.2.3 From 1eae887434331357e057498905f7f5ff8f9f9c77 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 26 Dec 2012 23:55:23 +0200 Subject: CHUI-629 FIXED Resolve build problems; --- indra/newview/llconversationlog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 0479733706..8c86871134 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -413,7 +413,7 @@ bool LLConversationLog::saveToFile(const std::string& filename) // [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| fprintf(fp, "[%lld] %d %d %d %s| %s %s %s|\n", - conv_it->getTime(), + (S64)conv_it->getTime(), (S32)conv_it->getConversationType(), (S32)0, (S32)conv_it->hasOfflineMessages(), -- cgit v1.2.3 From 7e8d336749b42ce134a67dfe1f1990644f1b263a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 28 Dec 2012 15:28:19 +0200 Subject: CHUI-639 FIXED Min. width is increased to avoid overlapping --- indra/newview/skins/default/xui/en/floater_conversation_log.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml index cf61348a66..256e03c4d7 100644 --- a/indra/newview/skins/default/xui/en/floater_conversation_log.xml +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -5,7 +5,7 @@ positioning="cascading" height="200" min_height="100" - min_width="200" + min_width="230" layout="topleft" name="floater_conversation_log" save_rect="true" -- cgit v1.2.3 From d99fa985c8ff65913e85dfaa9fd91892a197c4cc Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 28 Dec 2012 18:55:24 +0200 Subject: CHUI-566 ADD. FIX Flashing and color on Conversations FUI button and conversation line item Cancel sticking of color, if the button is pressed, or when a flashing of the previously selected button is ended --- indra/llui/llbutton.cpp | 18 +++++++++++++----- indra/newview/llimview.cpp | 16 ++++++---------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 7ca9b869a8..a8149a9a1d 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -311,7 +311,7 @@ void LLButton::onCommit() { make_ui_sound("UISndClickRelease"); } - + if (mIsToggle) { toggleState(); @@ -613,8 +613,6 @@ void LLButton::draw() static LLCachedControl sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); - bool flash = mFlashing && sEnableButtonFlashing; - bool pressed_by_keyboard = FALSE; if (hasFocus()) { @@ -642,6 +640,17 @@ void LLButton::draw() LLColor4 glow_color; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; LLUIImage* imagep = NULL; + + // Cancel sticking of color, if the button is pressed, + // or when a flashing of the previously selected button is ended + if (mFlashingTimer + && ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed)) + { + mFlashing = false; + } + + bool flash = mFlashing && sEnableButtonFlashing; + if (pressed && mDisplayPressedState) { imagep = selected ? mImagePressedSelected : mImagePressed; @@ -697,8 +706,7 @@ void LLButton::draw() imagep = mImageDisabled; } - // Selected has a higher priority than flashing. If both are set, flashing is ignored. - if (mFlashing && !selected) + if (mFlashing) { // if button should flash and we have icon for flashing, use it as image for button if(flash && mImageFlash) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d736b81bb7..48cf7b3463 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -122,7 +122,7 @@ void on_new_message(const LLSD& msg) LLUUID session_id = msg["session_id"].asUUID(); LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - // determine action for this session + // determine action for this session if (session_id.isNull()) { @@ -148,13 +148,14 @@ void on_new_message(const LLSD& msg) action = gSavedSettings.getString("NotificationGroupChatOptions"); } - // do not show notification in "do not disturb" mode or it goes from agent + // do not show notification which goes from agent if (gAgent.getID() == participant_id) { return; } // execution of the action + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); @@ -173,7 +174,7 @@ void on_new_message(const LLSD& msg) if ("toast" == action) { - // Skip toasting if we have open window of IM with this session id + // Skip toasting and flashing if we have open window of IM with this session id if (session_floater && session_floater->isInVisibleChain() && session_floater->hasFocus() @@ -184,12 +185,6 @@ void on_new_message(const LLSD& msg) return; } - // Skip toasting for system messages and for nearby chat - if (participant_id.isNull()) - { - return; - } - //User is not focused on conversation containing the message if(session_floater_not_focused) { @@ -201,7 +196,8 @@ void on_new_message(const LLSD& msg) gToolBarView->flashCommand(LLCommandId("chat"), true); //Show IM toasts (upper right toasts) - if(session_id.notNull()) + // Skip toasting for system messages and for nearby chat + if(session_id.notNull() && participant_id.notNull()) { LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); } -- cgit v1.2.3 From a25e6eb733bb8f6a0e9f8de1094155f685c6216d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 28 Dec 2012 16:11:05 +0200 Subject: CHUI-453 FIXED Tooltip on chevron in torn-off conversation is incorrect: implemented suitable tool-tips; fixed a small separate bug ("tooltip_to_separate_window"/"tooltip_to_main_window" for Tear-Off Button: was shown reverse) --- indra/newview/llfloaterimsessiontab.cpp | 24 ++++++++++++++-------- .../skins/default/xui/en/floater_im_session.xml | 9 ++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4e79bd0ac8..a79b4b3f1d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -606,8 +606,8 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // prevent start conversation before its container LLFloaterIMContainer::getInstance(); - bool is_torn_off = checkIfTornOff(); - if (!is_torn_off) + bool is_not_torn_off = !checkIfTornOff(); + if (is_not_torn_off) { hideAllStandardButtons(); } @@ -616,7 +616,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // Participant list should be visible only in torn off floaters. bool is_participant_list_visible = - is_torn_off + !is_not_torn_off && gSavedSettings.getBOOL("IMShowControlPanel") && !mIsP2PChat; @@ -624,22 +624,28 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. - bool is_expanded = !is_torn_off || is_participant_list_visible; + bool is_expanded = is_not_torn_off || is_participant_list_visible; mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + mExpandCollapseBtn->setToolTip( + is_not_torn_off? + getString("expcol_button_not_tearoff_tooltip") : + (is_expanded? + getString("expcol_button_tearoff_and_expanded_tooltip") : + getString("expcol_button_tearoff_and_collapsed_tooltip"))); // toggle floater's drag handle and title visibility if (mDragHandle) { - mDragHandle->setTitleVisible(is_torn_off); + mDragHandle->setTitleVisible(!is_not_torn_off); } // The button (>>) should be disabled for torn off P2P conversations. - mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + mExpandCollapseBtn->setEnabled(is_not_torn_off || !mIsP2PChat); - mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); - mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); + mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon")); + mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window")); - mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat); enableDisableCallBtn(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 9e2132dc3b..8f0574177f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -49,6 +49,15 @@ + + + Date: Wed, 2 Jan 2013 13:10:42 -0800 Subject: CHUI-499: Removing debug code --- .../newview/lldonotdisturbnotificationstorage.cpp | 25 ---------------------- 1 file changed, 25 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index bf3dcae1f3..f4560d5668 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -29,11 +29,6 @@ #include "lldonotdisturbnotificationstorage.h" -#define XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT 0 - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT -#include "llchannelmanager.h" -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llcommunicationchannel.h" #include "lldir.h" #include "llerror.h" @@ -41,9 +36,6 @@ #include "llnotifications.h" #include "llnotificationhandler.h" #include "llnotificationstorage.h" -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT -#include "llscreenchannel.h" -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT #include "llscriptfloater.h" #include "llsd.h" #include "llsingleton.h" @@ -109,12 +101,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { return; } - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT - LLNotificationsUI::LLScreenChannel* notification_channel = - dynamic_cast(LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT LLNotifications& instance = LLNotifications::instance(); @@ -146,17 +132,6 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() instance.add(notification); } - -#if XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT - // hide script floaters so they don't confuse the user and don't overlap startup toast - LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); - - if(notification_channel) - { - // hide saved toasts so they don't confuse the user - notification_channel->hideToast(notification->getID()); - } -#endif // XXX_STINSON_HIDE_NOTIFICATIONS_ON_DND_EXIT } // Clear the communication channel history and rewrite the save file to empty it as well -- cgit v1.2.3 From f40ee4792d948ca99d19bdd6f645faea07e15f47 Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Thu, 3 Jan 2013 06:35:40 +0200 Subject: CHUI-616 (Left Click on participant name in torn off conference moves focus to conversation floater) --- indra/newview/llconversationview.cpp | 21 --------------------- indra/newview/llconversationview.h | 2 -- 2 files changed, 23 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index e51efd48f5..903dd2a407 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -547,27 +547,6 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask) LLFolderViewItem::onMouseLeave(x, y, mask); } -BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - LLConversationItem* item = NULL; - LLConversationViewSession* session_widget = - dynamic_cast(this->getParentFolder()); - if (session_widget) - { - item = dynamic_cast(session_widget->getViewModelItem()); - } - LLUUID session_id = item? item->getUUID() : LLUUID(); - BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask); - - if(result) - { - (LLFloaterReg::getTypedInstance("im_container"))-> - selectConversationPair(session_id, false); - } - - return result; -} - S32 LLConversationViewParticipant::getLabelXPos() { return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad; diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 74443e1d88..5f6acfb9ab 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -132,8 +132,6 @@ public: void addToFolder(LLFolderViewFolder* folder); void addToSession(const LLUUID& session_id); - /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); -- cgit v1.2.3 From 3d83fc3da5b0fa20bb631bfd2c94368946905675 Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Thu, 3 Jan 2013 06:43:25 +0200 Subject: CHUI-608 (Conversations floater can be resized too small once a conversation is torn off) --- indra/newview/llfloaterimcontainer.h | 3 ++- indra/newview/llfloaterimsessiontab.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 09a24c0105..8daed46c7d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -106,6 +106,8 @@ public: bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); + void assignResizeLimits(); + private: typedef std::map avatarID_panel_map_t; avatarID_panel_map_t mSessions; @@ -154,7 +156,6 @@ private: void toggleAllowTextChat(const LLUUID& participant_uuid); void toggleMute(const LLUUID& participant_id, U32 flags); void openNearbyChat(); - void assignResizeLimits(); LLButton* mExpandCollapseBtn; LLButton* mStubCollapseBtn; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index f5b657fa60..4e79bd0ac8 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -751,6 +751,11 @@ void LLFloaterIMSessionTab::onTearOffClicked() { forceReshape(); } + LLFloaterIMContainer* container = LLFloaterIMContainer::getInstance(); + if (container) + { + container->assignResizeLimits(); + } refreshConversation(); updateGearBtn(); } -- cgit v1.2.3 From c464adc8ae35d3656e8de6aa459eb4615bb34c6f Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Thu, 3 Jan 2013 14:03:33 +0200 Subject: CHUI-636 FIXED Enable group context menu options, if uuid is empty and selected model item is group chat. In addition enable Chat history item for ad-hoc and group conversations. --- indra/newview/llfloaterimcontainer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2019a35faa..61a67a1f9f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,12 +1101,20 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); + //Enable Chat history item for ad-hoc and group conversations + if ("can_chat_history" == item) + { + if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + { + return isConversationLoggingAllowed(); + } + } - // If nothing is selected, everything needs to be disabled + // If nothing is selected(and selected item is not group chat), everything needs to be disabled if (uuids.size() <= 0) - { - return false; - } + { + return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + } if("can_activate_group" == item) { @@ -1123,7 +1131,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v { return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); } - + // Extract the single select info bool is_single_select = (uuids.size() == 1); const LLUUID& single_id = uuids.front(); -- cgit v1.2.3 From f4902521f58956eda7701770eec51763a7663d3c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 3 Jan 2013 15:12:11 +0200 Subject: CHUI-631 FIXED 'Nearby chat' is not selected in Conversations floater after closing separate conversation if list of participants was expand in Conversations floater: force select 'Nearby chat' when session floater is destroyed --- indra/newview/llfloaterimsessiontab.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index a79b4b3f1d..76643b0235 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -82,6 +82,13 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; + + // Select Nearby Chat session + LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance("im_container"); + if (container) + { + container->selectConversationPair(LLUUID(NULL), true); + } } //static -- cgit v1.2.3 From 799c1f241f66db6d8701ee8c4339a5cce41c3c47 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 3 Jan 2013 18:59:20 +0200 Subject: CHUI-628 FIXED Open conversation log menu option not active in conversation floater when nearby chat is selected: Determination of the availability menu item was moved to the right place --- indra/newview/llfloaterimcontainer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 61a67a1f9f..50acd4ae24 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1101,6 +1101,11 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); + if ("conversation_log" == item) + { + return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + } + //Enable Chat history item for ad-hoc and group conversations if ("can_chat_history" == item) { @@ -1127,11 +1132,6 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_vec_t& uuids) { - if ("conversation_log" == item) - { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); - } - // Extract the single select info bool is_single_select = (uuids.size() == 1); const LLUUID& single_id = uuids.front(); -- cgit v1.2.3 From aa6fee292d1721eac6f0f1f270844e01e06979d4 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 3 Jan 2013 14:19:04 -0800 Subject: CHUI-499: Fixed a serialization problem where the a notification's objectInfo was not being serialized/deserialized. --- indra/llui/llnotifications.cpp | 5 +++++ indra/llui/llnotifications.h | 4 +++- indra/newview/lldonotdisturbnotificationstorage.cpp | 2 +- indra/newview/llnotificationstorage.cpp | 7 +------ indra/newview/llviewermessage.cpp | 3 +++ indra/newview/llviewermessage.h | 1 + 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index c9b4399bef..8aa0b6f110 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -517,6 +517,11 @@ LLSD LLNotification::asLLSD() p.expiry = mExpiresAt; p.priority = mPriority; + if(mResponder) + { + p.functor.responder_sd = mResponder->asLLSD(); + } + if(!mResponseFunctorName.empty()) { p.functor.name = mResponseFunctorName; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 42dee4c3e9..2a6391f49e 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -322,11 +322,13 @@ public: Alternative name; Alternative function; Alternative responder; + Alternative responder_sd; Functor() : name("responseFunctor"), function("functor"), - responder("responder") + responder("responder"), + responder_sd("responder_sd") {} }; Optional functor; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index f4560d5668..6407a3fa0c 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -118,7 +118,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } else { - LLNotificationResponderInterface* responder = createResponder(notification_params["name"], notification_params["responder"]); + LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) { LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index b797775369..4c5b7cc198 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -126,13 +126,8 @@ LLResponderRegistry::LLResponderRegistry() , mBuildMap() { add("ObjectGiveItem", &create); - add("OwnObjectGiveItem", &create); add("UserGiveItem", &create); - - add("TeleportOffered", &create); - add("TeleportOffered_MaturityExceeded", &create); - - add("OfferFriendship", &create); + add("offer_info", &create); } LLResponderRegistry::~LLResponderRegistry() diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 04dd7c911b..d264a18597 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1361,6 +1361,8 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id)); } +std::string LLOfferInfo::mResponderType = "offer_info"; + LLOfferInfo::LLOfferInfo() : LLNotificationResponderInterface() , mFromGroup(FALSE) @@ -1406,6 +1408,7 @@ LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) LLSD LLOfferInfo::asLLSD() { LLSD sd; + sd["responder_type"] = mResponderType; sd["im_type"] = mIM; sd["from_id"] = mFromID; sd["from_group"] = mFromGroup; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 447fdeb9c7..3237f3fbdd 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -229,6 +229,7 @@ public: void forceResponse(InventoryOfferResponse response); + static std::string mResponderType; EInstantMessage mIM; LLUUID mFromID; BOOL mFromGroup; -- cgit v1.2.3 From 0e6ff3e7021b2e72f02b22550bbb96bc3674cba4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 3 Jan 2013 14:37:24 -0800 Subject: CHUI-654 : Fixed! Select the Nearby Chat directly when one conversation only left, don't finesse with a root UUID that might not be NULL --- indra/newview/llfloaterimcontainer.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 50acd4ae24..9fe67e99da 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1430,11 +1430,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c { is_widget_selected = widget->isSelected(); new_selection = mConversationsRoot->getNextFromChild(widget); - if(new_selection == NULL) + if (!new_selection) { new_selection = mConversationsRoot->getPreviousFromChild(widget); } - widget->destroyView(); } @@ -1446,14 +1445,20 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c if (change_focus) { setFocus(TRUE); - if(new_selection != NULL) + if (new_selection) { if (mConversationsWidgets.size() == 1) - new_selection = new_selection->getParentFolder(); - LLConversationItem* vmi = dynamic_cast(new_selection->getViewModelItem()); - if(vmi != NULL) { - selectConversationPair(vmi->getUUID(), true); + // If only one widget is left, it has to be the Nearby Chat. Select it directly. + selectConversationPair(LLUUID(NULL), true); + } + else + { + LLConversationItem* vmi = dynamic_cast(new_selection->getViewModelItem()); + if (vmi) + { + selectConversationPair(vmi->getUUID(), true); + } } } } -- cgit v1.2.3 From 3d1feec7641051386733405186cfe81b68a929ca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 3 Jan 2013 15:11:53 -0800 Subject: CHUI-656 : Fixed. getTypedInstance() will create an instance if not found. Do not use that in destructors (bad...) or in places where creation is not required. Use findTypedInstance() instead. --- indra/newview/llfloaterimsessiontab.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 76643b0235..7b34a86f24 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -84,7 +84,7 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab() delete mRefreshTimer; // Select Nearby Chat session - LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance("im_container"); + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance("im_container"); if (container) { container->selectConversationPair(LLUUID(NULL), true); @@ -329,7 +329,7 @@ void LLFloaterIMSessionTab::onFocusReceived() LLTransientDockableFloater::onFocusReceived(); - LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance("im_container"); + LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance("im_container"); if (container) { container->selectConversationPair(mSessionID, true); -- cgit v1.2.3 From 9d687cc0042a6972a603778359055394c1cf0850 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 4 Jan 2013 15:14:24 +0200 Subject: CHUI-637 FIXED Call requestArrange() to update widget state. --- indra/newview/llfloaterimcontainer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 9fe67e99da..22db4dd0eb 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -678,6 +678,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) { widget->setOpen(false); } + widget->requestArrange(); } } } -- cgit v1.2.3 From 4d971c43518f02fe202cf437f059250061cd9756 Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Fri, 4 Jan 2013 16:48:34 +0200 Subject: CHUI-608 (Conversations floater can be resized too small once a conversation is torn off) --- indra/newview/llfloaterimcontainer.cpp | 6 ++++++ indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 5 ----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 2019a35faa..151d901708 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -605,6 +605,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLMultiFloater::setVisible(visible); } +void LLFloaterIMContainer::updateResizeLimits() +{ + LLMultiFloater::updateResizeLimits(); + assignResizeLimits(); +} + void LLFloaterIMContainer::collapseMessagesPane(bool collapse) { if (mMessagesPane->isCollapsed() == collapse) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 8daed46c7d..0cd1b6759b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -60,6 +60,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void updateResizeLimits(); void onCloseFloater(LLUUID& id); /*virtual*/ void addFloater(LLFloater* floaterp, diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4e79bd0ac8..f5b657fa60 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -751,11 +751,6 @@ void LLFloaterIMSessionTab::onTearOffClicked() { forceReshape(); } - LLFloaterIMContainer* container = LLFloaterIMContainer::getInstance(); - if (container) - { - container->assignResizeLimits(); - } refreshConversation(); updateGearBtn(); } -- cgit v1.2.3 From b1ba208e7fcb8dbaa2c47b70fe580094982e36dd Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Sat, 5 Jan 2013 00:09:36 +0200 Subject: CHUI-643 W.I.P. Collapsed conversations floater has huge right padding: corrected of a imcontainer's resize calculating --- indra/newview/llfloaterimcontainer.cpp | 59 ++++++++++++---------- .../skins/default/xui/en/floater_im_container.xml | 3 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ae243d6495..69d6f1ca38 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -618,34 +618,34 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse) return; } + // Save current width of panels before collapsing/expanding right pane. + S32 conv_pane_width = mConversationsPane->getRect().getWidth(); + S32 msg_pane_width = mMessagesPane->getRect().getWidth(); + if (collapse) { // Save the messages pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", msg_pane_width); // Save the order in which the panels are closed to reverse user's last action. gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } - // Save left pane rectangle before collapsing/expanding right pane. - LLRect prevRect = mConversationsPane->getRect(); - // Show/hide the messages pane. mConversationsStack->collapsePanel(mMessagesPane, collapse); - if (!collapse) - { - // Make sure layout is updated before resizing conversation pane. - mConversationsStack->updateLayout(); - } + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + if (!collapse) { // Restore conversation's pane previous width after expanding messages pane. - mConversationsPane->setTargetDim(prevRect.getWidth()); + mConversationsPane->setTargetDim(conv_pane_width); } } + void LLFloaterIMContainer::collapseConversationsPane(bool collapse) { if (mConversationsPane->isCollapsed() == collapse) @@ -657,10 +657,13 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) button_panel->setVisible(!collapse); mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + // Save current width of panels before collapsing/expanding right pane. + S32 conv_pane_width = mConversationsPane->getRect().getWidth(); + if (collapse) { // Save the conversations pane width before collapsing it. - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width); // Save the order in which the panels are closed to reverse user's last action. gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); @@ -668,8 +671,9 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) mConversationsStack->collapsePanel(mConversationsPane, collapse); - S32 collapsed_width = mConversationsPane->getMinDim(); - updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); + S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim(); + + updateState(collapse, delta_width); for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); widget_it != mConversationsWidgets.end(); ++widget_it) @@ -685,7 +689,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) widget->setOpen(false); } widget->requestArrange(); -} + } } } @@ -693,6 +697,8 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); +S32 debug_var = floater_rect.getWidth(); +debug_var = debug_var + 1; // Set by_user = true so that reshaped rect is saved in user_settings. setShape(floater_rect, true); @@ -705,29 +711,28 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) setCanResize(is_left_pane_expanded || is_right_pane_expanded); setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); + assignResizeLimits(); + // force set correct size for the title after show/hide minimize button LLRect cur_rect = getRect(); LLRect force_rect = cur_rect; force_rect.mRight = cur_rect.mRight + 1; setRect(force_rect); setRect(cur_rect); - - // restore floater's resize limits (prevent collapse when left panel is expanded) - if (is_left_pane_expanded && !is_right_pane_expanded) - { - S32 expanded_min_size = mConversationsPane->getExpandedMinDim(); - setResizeLimits(expanded_min_size, expanded_min_size); - } - - assignResizeLimits(); } void LLFloaterIMContainer::assignResizeLimits() { - const LLRect& conv_rect = mConversationsPane->isCollapsed() ? LLRect() : mConversationsPane->getRect(); - S32 msg_limits = mMessagesPane->isCollapsed() ? 0 : mMessagesPane->getExpandedMinDim(); - S32 x_limits = conv_rect.getWidth() + msg_limits; - setResizeLimits(x_limits + LLPANEL_BORDER_WIDTH * 3, getMinHeight()); + bool is_conv_pane_expanded = !mConversationsPane->isCollapsed(); + bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); + + S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); + S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; + S32 conv_pane_current_width = is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim(); + S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; + S32 new_min_width = conv_pane_current_width + msg_pane_min_width + summary_width_of_visible_borders; + + setResizeLimits(new_min_width, getMinHeight()); } void LLFloaterIMContainer::onAddButtonClicked() diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e7638fe669..951665552f 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -14,7 +14,8 @@ title="CONVERSATIONS" bottom="-50" right="-5" - width="450"> + width="450" + min_width="38"> -- cgit v1.2.3 From 118201943da157b6932d8c79ab3eb3d8c3c0a9a4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Fri, 4 Jan 2013 23:54:38 +0200 Subject: CHUI-643 FIXED Collapsed conversations floater has huge right padding: prevent of a rewriting mOriginMinWidth and mOriginMinHeight to default values --- indra/llui/llmultifloater.cpp | 10 ++++------ indra/newview/llfloaterimcontainer.cpp | 15 ++++++++++++--- indra/newview/llfloaterimcontainer.h | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 179b251cdb..59faabd482 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -37,12 +37,10 @@ // LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) - : LLFloater(key), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(TRUE), - mOrigMinWidth(params.min_width), - mOrigMinHeight(params.min_height) + : LLFloater(key) + , mTabContainer(NULL) + , mTabPos(LLTabContainer::TOP) + , mAutoResize(TRUE) { } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 69d6f1ca38..5624788e45 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -56,8 +56,8 @@ // // LLFloaterIMContainer // -LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed) -: LLMultiFloater(seed), +LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& params /*= getDefaultParams()*/) +: LLMultiFloater(seed, params), mExpandCollapseBtn(NULL), mConversationsRoot(NULL), mConversationsEventStream("ConversationsEvents"), @@ -153,6 +153,9 @@ void LLFloaterIMContainer::onCurrentChannelChanged(const LLUUID& session_id) BOOL LLFloaterIMContainer::postBuild() { + mOrigMinWidth = getMinWidth(); + mOrigMinHeight = getMinHeight(); + mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLFloaterIMContainer::onNewMessageReceived, this, _1)); // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button // mTabContainer will be initialized in LLMultiFloater::addChild() @@ -657,7 +660,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse) button_panel->setVisible(!collapse); mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); - // Save current width of panels before collapsing/expanding right pane. + // Save current width of Conversation panel before collapsing/expanding right pane. S32 conv_pane_width = mConversationsPane->getRect().getWidth(); if (collapse) @@ -1408,6 +1411,12 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& current_participant_model++; } } + + if (uuid.notNull() && im_sessionp->isP2PSessionType()) + { + item->fetchAvatarName(LLIMModel::getInstance()->getOtherParticipantID(uuid)); + } + // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 0cd1b6759b..85d950c58b 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -53,7 +53,7 @@ class LLFloaterIMContainer , public LLIMSessionObserver { public: - LLFloaterIMContainer(const LLSD& seed); + LLFloaterIMContainer(const LLSD& seed, const Params& params = getDefaultParams()); virtual ~LLFloaterIMContainer(); /*virtual*/ BOOL postBuild(); -- cgit v1.2.3 From e59458590535d7fe571f9504fe97caa4e15701e6 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Sat, 5 Jan 2013 00:19:54 +0200 Subject: CHUI-643 FIXED Collapsed conversations floater has huge right padding: clean up; remove debug code --- indra/newview/llfloaterimcontainer.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 5624788e45..09d83e2a8f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -700,8 +700,6 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width) { LLRect floater_rect = getRect(); floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); -S32 debug_var = floater_rect.getWidth(); -debug_var = debug_var + 1; // Set by_user = true so that reshaped rect is saved in user_settings. setShape(floater_rect, true); @@ -729,6 +727,8 @@ void LLFloaterIMContainer::assignResizeLimits() bool is_conv_pane_expanded = !mConversationsPane->isCollapsed(); bool is_msg_pane_expanded = !mMessagesPane->isCollapsed(); + // With two panels visible number of borders is three, because the borders + // between the panels are merged into one S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3); S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH; S32 conv_pane_current_width = is_conv_pane_expanded? mConversationsPane->getRect().getWidth() : mConversationsPane->getMinDim(); @@ -1412,11 +1412,6 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& } } - if (uuid.notNull() && im_sessionp->isP2PSessionType()) - { - item->fetchAvatarName(LLIMModel::getInstance()->getOtherParticipantID(uuid)); - } - // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) -- cgit v1.2.3 From 02ca16c1334d1409d8b14136f76305686796c359 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Fri, 4 Jan 2013 17:58:30 -0800 Subject: CHUI-499: Now when existing DND mode, stored IM's will not show a toast but instead flash the conversation line item and Chat FUI button. --- indra/llui/llnotifications.cpp | 3 +- indra/llui/llnotifications.h | 18 ++++- .../newview/lldonotdisturbnotificationstorage.cpp | 10 ++- indra/newview/llimhandler.cpp | 86 ++++++++++++---------- indra/newview/llimview.cpp | 37 ++++++++++ 5 files changed, 110 insertions(+), 44 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 8aa0b6f110..9ba598995f 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -475,7 +475,8 @@ LLNotification::LLNotification(const LLSDParamAdapter& p) : mIgnored(false), mResponderObj(NULL), mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()), - mOfferFromAgent(p.offer_from_agent) + mOfferFromAgent(p.offer_from_agent), + mIsDND(p.is_dnd) { if (p.functor.name.isChosen()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 2a6391f49e..092a9acd7c 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -316,6 +316,7 @@ public: Optional context; Optional responder; Optional offer_from_agent; + Optional is_dnd; struct Functor : public LLInitParam::ChoiceBlock { @@ -342,7 +343,8 @@ public: form_elements("form"), substitutions("substitutions"), expiry("expiry"), - offer_from_agent("offer_from_agent", false) + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { time_stamp = LLDate::now(); responder = NULL; @@ -356,7 +358,8 @@ public: form_elements("form"), substitutions("substitutions"), expiry("expiry"), - offer_from_agent("offer_from_agent", false) + offer_from_agent("offer_from_agent", false), + is_dnd("is_dnd", false) { functor.name = _name; name = _name; @@ -383,6 +386,7 @@ private: void* mResponderObj; // TODO - refactor/remove this field LLNotificationResponderPtr mResponder; bool mOfferFromAgent; + bool mIsDND; // a reference to the template LLNotificationTemplatePtr mTemplatep; @@ -523,6 +527,16 @@ public: return mOfferFromAgent; } + bool isDND() const + { + return mIsDND; + } + + void setDND(const bool flag) + { + mIsDND = flag; + } + std::string getType() const; std::string getMessage() const; std::string getFooter() const; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 6407a3fa0c..9bb2f27a46 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -109,15 +109,19 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() ++notification_it) { LLSD notification_params = *notification_it; - LLNotificationPtr notification(new LLNotification(notification_params)); + const LLUUID& notificationID = notification_params["id"]; + LLNotificationPtr notification = instance.find(notificationID); - const LLUUID& notificationID = notification->id(); - if (instance.find(notificationID)) + //Notification already exists in notification pipeline (same instance of app running) + if (notification) { + notification->setDND(true); instance.update(notification); } + //Notification doesn't exist (different instance since restarted app while in DND mode) else { + notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) { diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 72967eb6c7..c2b29f36e8 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -36,6 +36,8 @@ using namespace LLNotificationsUI; +extern void process_dnd_im(const LLSD& notification); + //-------------------------------------------------------------------------- LLIMHandler::LLIMHandler() : LLCommunicationNotificationHandler("IM Notifications", "notifytoast") @@ -60,44 +62,52 @@ void LLIMHandler::initChannel() //-------------------------------------------------------------------------- bool LLIMHandler::processNotification(const LLNotificationPtr& notification) { - if(mChannel.isDead()) - { - return false; - } - - // arrange a channel on a screen - if(!mChannel.get()->getVisible()) - { - initChannel(); - } - - LLSD substitutions = notification->getSubstitutions(); - - // According to comments in LLIMMgr::addMessage(), if we get message - // from ourselves, the sender id is set to null. This fixes EXT-875. - LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); - if (avatar_id.isNull()) - avatar_id = gAgentID; - - LLToastIMPanel::Params im_p; - im_p.notification = notification; - im_p.avatar_id = avatar_id; - im_p.from = substitutions["FROM"].asString(); - im_p.time = substitutions["TIME"].asString(); - im_p.message = substitutions["MESSAGE"].asString(); - im_p.session_id = substitutions["SESSION_ID"].asUUID(); - - LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.session_id = im_p.session_id; - p.notification = notification; - p.panel = im_box; - p.can_be_stored = false; - LLScreenChannel* channel = dynamic_cast(mChannel.get()); - if(channel) - channel->addToast(p); + if(notification->isDND()) + { + LLSD data = notification->asLLSD(); //don't need this if retrieve needed data from notification getters + process_dnd_im(data); + } + else + { + if(mChannel.isDead()) + { + return false; + } + + // arrange a channel on a screen + if(!mChannel.get()->getVisible()) + { + initChannel(); + } + + LLSD substitutions = notification->getSubstitutions(); + + // According to comments in LLIMMgr::addMessage(), if we get message + // from ourselves, the sender id is set to null. This fixes EXT-875. + LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); + if (avatar_id.isNull()) + avatar_id = gAgentID; + + LLToastIMPanel::Params im_p; + im_p.notification = notification; + im_p.avatar_id = avatar_id; + im_p.from = substitutions["FROM"].asString(); + im_p.time = substitutions["TIME"].asString(); + im_p.message = substitutions["MESSAGE"].asString(); + im_p.session_id = substitutions["SESSION_ID"].asUUID(); + + LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; + p.notification = notification; + p.panel = im_box; + p.can_be_stored = false; + LLScreenChannel* channel = dynamic_cast(mChannel.get()); + if(channel) + channel->addToast(p); + } return false; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d736b81bb7..716e6fe7ba 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -101,6 +101,43 @@ BOOL LLSessionTimeoutTimer::tick() return TRUE; } + + +void process_dnd_im(const LLSD& notification) +{ + LLSD data = notification["substitutions"]; + LLUUID sessionID = data["SESSION_ID"].asUUID(); + + //re-create the IM session if needed + //(when coming out of DND mode upon app restart) + if(!gIMMgr->hasSession(sessionID)) + { + //reconstruct session using data from the notification + std::string name = data["FROM"]; + LLAvatarName av_name; + if (LLAvatarNameCache::get(data["FROM_ID"], &av_name)) + { + name = av_name.getDisplayName(); + } + + + LLIMModel::getInstance()->newSession(sessionID, + name, + IM_NOTHING_SPECIAL, + data["FROM_ID"], + false, + false); //will need slight refactor to retrieve whether offline message or not (assume online for now) + } + + //For now always flash conversation line item + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); + im_box->flashConversationItemWidget(sessionID, true); + + //And flash toolbar button + gToolBarView->flashCommand(LLCommandId("chat"), true); +} + + static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD msg) -- cgit v1.2.3 From 12554bffb34895533ed11013a780bfa088756a67 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 4 Jan 2013 20:23:14 -0800 Subject: CHUI-580 : Fixed : Avoid fetching names while reacting to display name checkbox change (overkill), make display name pref disabled when usePeopleAPI is off --- indra/newview/llconversationmodel.cpp | 33 +++++++++++++++++++++++++-------- indra/newview/llconversationmodel.h | 6 ++++-- indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llfloaterpreference.cpp | 13 ++++++++++++- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index b1f45d6d64..bc5b72e029 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -434,24 +434,31 @@ void LLConversationItemParticipant::fetchAvatarName() } } -void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +void LLConversationItemParticipant::updateAvatarName() { - menuentry_vec_t items; - menuentry_vec_t disabled_items; - - buildParticipantMenuOptions(items); - - hide_context_entries(menu, items, disabled_items); + llassert(getUUID().notNull()); + if (getUUID().notNull()) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(getUUID(),&av_name)) + { + updateAvatarName(av_name); + } + } } void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); + updateAvatarName(av_name); +} +void LLConversationItemParticipant::updateAvatarName(const LLAvatarName& av_name) +{ mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); mNeedsRefresh = true; - if(mParent != NULL) + if (mParent != NULL) { LLConversationItemSession* parent_session = dynamic_cast(mParent); if (parent_session != NULL) @@ -463,6 +470,16 @@ void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_nam } } +void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + buildParticipantMenuOptions(items); + + hide_context_entries(menu, items, disabled_items); +} + LLConversationItemSession* LLConversationItemParticipant::getParentSession() { LLConversationItemSession* parent_session = NULL; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 743a6ba40b..6ae891203d 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -195,14 +195,16 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } - void fetchAvatarName(); + void fetchAvatarName(); // fetch and update the avatar name + void updateAvatarName(); // get from the cache (do *not* fetch) and update the avatar name LLConversationItemSession* getParentSession(); void dumpDebugData(); void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; } private: - void onAvatarNameCache(const LLAvatarName& av_name); + void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName + void updateAvatarName(const LLAvatarName& av_name); bool mIsMuted; // default is false bool mIsModerator; // default is false diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 3c85f21188..e1288a763c 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -393,7 +393,7 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate() { LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); // Get the avatar name for this participant id from the cache and update the model - participant_model->fetchAvatarName(); + participant_model->updateAvatarName(); // Next participant current_participant_model++; } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 13d8a79f8d..3d4a1c44d8 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1682,6 +1682,17 @@ LLPanelPreference::LLPanelPreference() //virtual BOOL LLPanelPreference::postBuild() { + ////////////////////// PanelGeneral /////////////////// + if (hasChild("display_names_check")) + { + BOOL use_people_api = gSavedSettings.getBOOL("UsePeopleAPI"); + LLCheckBoxCtrl* ctrl_display_name = getChild("display_names_check"); + ctrl_display_name->setEnabled(use_people_api); + if (!use_people_api) + { + ctrl_display_name->setValue(FALSE); + } + } ////////////////////// PanelVoice /////////////////// if (hasChild("voice_unavailable")) @@ -1732,7 +1743,7 @@ BOOL LLPanelPreference::postBuild() getChild("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); } - // Panel Advanced + //////////////////////PanelAdvanced /////////////////// if (hasChild("modifier_combo")) { //localizing if push2talk button is set to middle mouse -- cgit v1.2.3 From 4e1eda1c3bc898ae8481b8dfcff4b29196ac835e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 7 Jan 2013 18:31:28 -0500 Subject: SH-3344 WIP - keep avatar local textures flagged no-delete while in use --- indra/newview/llviewertexture.cpp | 5 ++- indra/newview/llvoavatar.cpp | 73 ++++++++++++++++++++++++++++++++++ indra/newview/llvoavatar.h | 3 ++ indra/newview/llvoavatarself.cpp | 82 ++++++++++++++++++++++----------------- indra/newview/llvoavatarself.h | 1 + 5 files changed, 127 insertions(+), 37 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a673862882..8eada5c2a1 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -616,7 +616,7 @@ LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : LLViewerTexture::~LLViewerTexture() { - // LL_DEBUGS("Avatar") << mID << llendl; + LL_DEBUGS("Avatar") << mID << llendl; cleanup(); sImageCount--; } @@ -1160,7 +1160,8 @@ void LLViewerFetchedTexture::destroyTexture() { return ; } - + + LL_DEBUGS("Avatar") << mID << llendl; destroyGLTexture() ; mFullyLoaded = FALSE ; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 086e4306f8..df0b8171a6 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4004,8 +4004,81 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) //------------------------------------------------------------------------ // LLVOAvatar::updateTextures() //------------------------------------------------------------------------ +void LLVOAvatar::collectTextureUUIDs(std::set& ids, S32& local_mem, S32& baked_mem) +{ + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + + LLViewerFetchedTexture *imagep = NULL; + for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); + if (imagep) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + if (texture_dict->mIsLocalTexture) + { + local_mem += imagep->getTextureMemory(); + ids.insert(imagep->getID()); + } + } + } + if (isIndexBakedTexture((ETextureIndex) texture_index)) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + if (imagep) + { + baked_mem += imagep->getTextureMemory(); + ids.insert(imagep->getID()); + } + } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); +} + +void LLVOAvatar::releaseOldTextures() +{ + S32 current_texture_mem = 0; + + // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" + std::set new_texture_ids; + S32 local_mem = 0, baked_mem = 0; + collectTextureUUIDs(new_texture_ids, local_mem, baked_mem); + LL_DEBUGS("Avatar") << getFullname() << " local_mem: " << local_mem << " baked_mem: " << baked_mem << llendl; + for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) + { + if (new_texture_ids.find(*it) == new_texture_ids.end()) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep) + { + current_texture_mem += imagep->getTextureMemory(); + if (imagep->getTextureState() == LLGLTexture::NO_DELETE) + { + // This will allow the texture to be deleted if not in use. + imagep->forceActive(); + + // This resets the clock to being flagged as + // unused, preventing the texture from being + // deleted immediately. If other avatars or + // objects are using it, it can still be flagged + // no-delete by them. + imagep->forceUpdateBindStats(); + } + } + } + } + mTextureIDs = new_texture_ids; +} + void LLVOAvatar::updateTextures() { + releaseOldTextures(); + BOOL render_avatar = TRUE; if (mIsDummy) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 4802476e59..5b1395e566 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -134,6 +134,8 @@ public: BOOL updateJointLODs(); void updateLODRiggedAttachments( void ); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + void collectTextureUUIDs(std::set& ids, S32& local_mem, S32& baked_mem); + void releaseOldTextures(); /*virtual*/ void updateTextures(); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. /*virtual*/ void onShift(const LLVector4a& shift_vector); @@ -528,6 +530,7 @@ protected: LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; BOOL mLoadedCallbacksPaused; + std::set mTextureIDs; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 674988d94b..41dfe51116 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -177,7 +177,7 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, } // Called periodically for diagnostics, return true when done. -bool output_texture_diagnostics() +bool output_self_av_texture_diagnostics() { if (!isAgentAvatarValid()) return true; // done checking @@ -221,7 +221,7 @@ void LLVOAvatarSelf::initInstance() return; } - //doPeriodically(output_texture_diagnostics, 30.0); + doPeriodically(output_self_av_texture_diagnostics, 30.0); } // virtual @@ -2039,14 +2039,15 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV ++local_tex_iter) { const ETextureIndex tex_index = *local_tex_iter; - outbuf << " tex_index " << (S32) tex_index << "\n"; + const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(tex_index)->mName; + outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); if (wearable_count > 0) { for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << "\n"; + outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":"; const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); if (local_tex_obj) { @@ -2055,7 +2056,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV && local_tex_obj->getID() != IMG_DEFAULT_AVATAR && !image->isMissingAsset()) { - outbuf << " id: " << image->getID() + outbuf << " id: " << image->getID() << " refs: " << image->getNumRefs() << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) << " discard: " << image->getDiscardLevel() @@ -2067,9 +2068,10 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. << " mvs: " << image->getMaxVirtualSize() << " mvsc: " << image->getMaxVirtualSizeResetCounter() - << "\n"; + << " mem: " << image->getTextureMemory(); } } + outbuf << "\n"; } } } @@ -2079,6 +2081,23 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV return outbuf.str(); } +void LLVOAvatarSelf::dumpAllTextures() const +{ + std::string vd_text = "Local textures per baked index and wearable:\n"; + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); + } + LL_DEBUGS("Avatar") << vd_text << llendl; +} + const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; @@ -2348,24 +2367,28 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { if (!isIndexLocalTexture(type)) return; - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) + if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR) { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - // DRANO what priority should wearable-based textures have? - if (isUsingLocalAppearance()) - { - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - } - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) + imagep->setNoDelete(); + if (imagep->getDiscardLevel() != 0) { - mHasGrey = TRUE; // for statistics gathering + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + + // DRANO what priority should wearable-based textures have? + if (isUsingLocalAppearance()) + { + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + } + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } } } else @@ -2538,19 +2561,8 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset_buffer) continue; LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } - std::string vd_text = "Local textures per baked index and wearable:\n"; - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); - ++baked_iter) - { - const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); - if (!layerset) continue; - const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); - if (!layerset_buffer) continue; - vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); - } - LL_DEBUGS("Avatar") << vd_text << llendl; + + dumpAllTextures(); } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 02612b83da..74888e470d 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -391,6 +391,7 @@ public: const LLViewerTexLayerSet* debugGetLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex index) const { return (LLViewerTexLayerSet*)(mBakedTextureDatas[index].mTexLayerSet); } const std::string verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer + void dumpAllTextures() const; const std::string debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD LLSD metricsData(); -- cgit v1.2.3 From 3d0ec3da5baea6bb2b9b72707a884ac7b516c4fd Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 7 Jan 2013 15:32:47 -0800 Subject: CHUI-659 : WIP : Verified (tested) and cleaned up some CHUI-101 refactoring code. --- indra/llui/llfolderviewmodel.h | 4 ++-- indra/newview/llinventoryfilter.cpp | 9 +++------ indra/newview/llpanelobjectinventory.cpp | 10 +++++----- indra/newview/lltexturectrl.cpp | 15 --------------- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 7019857c0f..5837052565 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -401,8 +401,8 @@ public: virtual const FilterType& getFilter() const { return mFilter; } virtual void setFilter(const FilterType& filter) { mFilter = filter; } - // TODO RN: remove this and put all filtering logic in view model - // add getStatusText and isFiltering() + // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, + // this method needs to be overloaded and return the relevant fetch status. virtual bool contentsReady() { return true; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c913269aad..92f2d33073 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -42,8 +42,6 @@ #include "llclipboard.h" #include "lltrans.h" -//TODO RN: fix use of static cast as much as possible - LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); LLInventoryFilter::FilterOps::FilterOps(const Params& p) @@ -83,7 +81,7 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { - const LLFolderViewModelItemInventory* listener = static_cast(item); + const LLFolderViewModelItemInventory* listener = dynamic_cast(item); // Clipboard cut items are *always* filtered so we need this value upfront const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); @@ -122,7 +120,7 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const { - const LLFolderViewModelItemInventory* listener = static_cast(item); + const LLFolderViewModelItemInventory* listener = dynamic_cast(item); if (!listener) { llerrs << "Folder view event listener not found." << llendl; @@ -384,8 +382,7 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const { - const LLFolderViewModelItemInventory* listener = static_cast(item); - return mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; + return mFilterSubString.size() ? item->getSearchableName().find(mFilterSubString) : std::string::npos; } bool LLInventoryFilter::isDefault() const diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index a2aabb50b5..527aefe821 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1555,6 +1555,10 @@ void LLPanelObjectInventory::reset() mCommitCallbackRegistrar.pushScope(); // push local callbacks + // Reset the inventory model to show all folders by default + mInventoryViewModel.getFilter().setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + + // Create a new folder view root LLRect dummy_rect(0, 1, 1, 0); LLFolderView::Params p; p.name = "task inventory"; @@ -1566,11 +1570,7 @@ void LLPanelObjectInventory::reset() p.view_model = &mInventoryViewModel; p.root = NULL; mFolders = LLUICtrlFactory::create(p); - // this ensures that we never say "searching..." or "no items found" - //TODO RN: make this happen by manipulating filter object directly - LLInventoryFilter& inventoryFilter = dynamic_cast(mFolders->getFolderViewModel()->getFilter()); - inventoryFilter.setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); - + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 65f0290060..007eb8e33f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -652,26 +652,11 @@ void LLFloaterTexturePicker::draw() { folder_view->setPinningSelectedItem(mSelectedItemPinned); folder_view->getViewModelItem()->dirtyFilter(); - //TODO RN: test..still works without this? - //folder_view->arrangeFromRoot(); - mSelectedItemPinned = TRUE; } } } -// static -/* -void LLFloaterTexturePicker::onSaveAnotherCopyDialog( S32 option, void* userdata ) -{ - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - if( 0 == option ) - { - self->copyToInventoryFinal(); - } -} -*/ - const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only) { LLViewerInventoryCategory::cat_array_t cats; -- cgit v1.2.3 From d68f4ff646378070c1a92b3dc53f791454395356 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 7 Jan 2013 17:42:11 -0800 Subject: CHUI-659 : WIP : Reimplemented favorite landmark sorting to follow favorites bar index sorting. --- indra/newview/llfolderviewmodelinventory.cpp | 53 ++++++++++++---------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 8a4b4bae84..429315e33f 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -29,6 +29,7 @@ #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" #include "lltooldraganddrop.h" +#include "llfavoritesbar.h" // // class LLFolderViewModelInventory @@ -236,39 +237,31 @@ const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const { - // ignore sort order for landmarks in the Favorites folder. - // they should be always sorted as in Favorites bar. See EXT-719 - //TODO RN: fix sorting in favorites folder - //if (a->getSortGroup() == SG_ITEM - // && b->getSortGroup() == SG_ITEM - // && a->getInventoryType() == LLInventoryType::IT_LANDMARK - // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) - //{ - - // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - // LLUUID a_uuid = a->getParentFolder()->getUUID(); - // LLUUID b_uuid = b->getParentFolder()->getUUID(); - - // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - // { - // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // // or to LLInvFVBridge - // LLViewerInventoryItem* aitem = (static_cast(a))->getItem(); - // LLViewerInventoryItem* bitem = (static_cast(b))->getItem(); - // if (!aitem || !bitem) - // return false; - // S32 a_sort = aitem->getSortField(); - // S32 b_sort = bitem->getSortField(); - // return a_sort < b_sort; - // } - //} + // Ignore sort order for landmarks in the Favorites folder. + // In that folder, landmarks should be always sorted as in the Favorites bar. See EXT-719 + if (a->getSortGroup() == SG_ITEM + && b->getSortGroup() == SG_ITEM + && a->getInventoryType() == LLInventoryType::IT_LANDMARK + && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + // If both landmarks are in the favorite folder... + if (gInventory.isObjectDescendentOf(a->getUUID(), favorites_folder_id) && gInventory.isObjectDescendentOf(b->getUUID(), favorites_folder_id)) + { + // Get their index in that folder + S32 a_sort = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); + S32 b_sort = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); + // Note: since there are both in the favorite, we shouldn't get negative index value... + if (!((a_sort < 0) && (b_sort < 0))) + { + return a_sort < b_sort; + } + } + } // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. - bool by_name = (!mByDate - || (mFoldersByName - && (a->getSortGroup() != SG_ITEM))); + bool by_name = (!mByDate || (mFoldersByName && (a->getSortGroup() != SG_ITEM))); if (a->getSortGroup() != b->getSortGroup()) { -- cgit v1.2.3 From 51d6589eedc408aa7f8a81009b1be356ddc99252 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 7 Jan 2013 18:02:28 -0800 Subject: CHUI-659 : WIP : Clean up typos in my own comments --- indra/newview/llfolderviewmodelinventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 429315e33f..d47c28678d 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -245,13 +245,13 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, && b->getInventoryType() == LLInventoryType::IT_LANDMARK) { static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - // If both landmarks are in the favorite folder... + // If both landmarks are in the Favorites folder... if (gInventory.isObjectDescendentOf(a->getUUID(), favorites_folder_id) && gInventory.isObjectDescendentOf(b->getUUID(), favorites_folder_id)) { // Get their index in that folder S32 a_sort = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); S32 b_sort = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); - // Note: since there are both in the favorite, we shouldn't get negative index value... + // Note: this test is a bit overkill: since they are both in the Favorites folder, we shouldn't get negative index values... if (!((a_sort < 0) && (b_sort < 0))) { return a_sort < b_sort; -- cgit v1.2.3 From d71c0ab32c744a6672e4364e3d090d317ec0647c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 7 Jan 2013 18:30:59 -0800 Subject: CHUI-659 : WIP : Clamp down on the number of rearrange we really need. --- indra/llui/llfolderviewitem.cpp | 14 +++++++------- indra/newview/llfolderviewmodelinventory.cpp | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 1281d6bd66..6f8bdb1919 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1664,16 +1664,16 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) void LLFolderViewFolder::requestArrange() { - //if ( mLastArrangeGeneration != -1) + if ( mLastArrangeGeneration != -1) { - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); } } +} void LLFolderViewFolder::toggleOpen() { diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index d47c28678d..586965e5a0 100644 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -135,7 +135,6 @@ void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_gen if (passed_filter_before != mPrevPassedAllFilters) { - //TODO RN: ensure this still happens, but without dependency on folderview LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); if (parent_folder) { -- cgit v1.2.3 From 0e7e877379b4ab0d8d8b7ae3ce8c9dfb91cc9de7 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 7 Jan 2013 19:12:32 -0800 Subject: CHUI-659 : WIP : Cleanup llfolderviewitem of filter code as it all moved into llfolderviewmodel. --- indra/llui/llfolderviewitem.cpp | 53 +++-------------------------------------- 1 file changed, 3 insertions(+), 50 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 6f8bdb1919..b7165f68b7 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -267,28 +267,11 @@ void LLFolderViewItem::refresh() mIconOpen = vmi.getIconOpen(); mIconOverlay = vmi.getIconOverlay(); - if (mRoot->useLabelSuffix()) - { + if (mRoot->useLabelSuffix()) + { mLabelStyle = vmi.getLabelStyle(); mLabelSuffix = vmi.getLabelSuffix(); -} - - //TODO RN: make sure this logic still fires - //std::string searchable_label(mLabel); - //searchable_label.append(mLabelSuffix); - //LLStringUtil::toUpper(searchable_label); - - //if (mSearchableLabel.compare(searchable_label)) - //{ - // mSearchableLabel.assign(searchable_label); - // vmi.dirtyFilter(); - // // some part of label has changed, so overall width has potentially changed, and sort order too - // if (mParentFolder) - // { - // mParentFolder->requestSort(); - // mParentFolder->requestArrange(); - // } - //} + } mLabelWidthDirty = true; vmi.dirtyFilter(); @@ -1125,22 +1108,6 @@ BOOL LLFolderViewFolder::needsArrange() return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); } -//TODO RN: get height resetting working -//void LLFolderViewFolder::setPassedFilter(BOOL passed, BOOL passed_folder, S32 filter_generation) -//{ -// // if this folder is now filtered, but wasn't before -// // (it just passed) -// if (passed && !passedFilter(filter_generation)) -// { -// // reset current height, because last time we drew it -// // it might have had more visible items than now -// mCurHeight = 0.f; -// } -// -// LLFolderViewItem::setPassedFilter(passed, passed_folder, filter_generation); -//} - - // Passes selection information on to children and record selection // information if necessary. BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -1620,20 +1587,6 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) { getViewModelItem()->addChild(item->getViewModelItem()); } - - //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria - //// Traverse parent folders and update creation date and resort, if necessary - //LLFolderViewFolder* parentp = this; - //while (parentp) - //{ - // if (parentp->mSortFunction.isByDate()) - // { - // // parent folder doesn't have a time stamp yet, so get it from us - // parentp->requestSort(); - // } - - // parentp = parentp->getParentFolder(); - //} } // this is an internal method used for adding items to folders. -- cgit v1.2.3 From dbe1d2f0933db59493d11e9b3ab2d84ca884e28a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Tue, 8 Jan 2013 14:38:30 +0200 Subject: CHUI-602 FIXED Return false if Selected view model item is null. --- indra/newview/llfloaterimcontainer.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 09d83e2a8f..82563b8736 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1124,16 +1124,23 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) //Enable Chat history item for ad-hoc and group conversations if ("can_chat_history" == item) { - if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + if(getCurSelectedViewModelItem()) { - return isConversationLoggingAllowed(); + if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT) + { + return isConversationLoggingAllowed(); + } } } // If nothing is selected(and selected item is not group chat), everything needs to be disabled if (uuids.size() <= 0) { - return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + if(getCurSelectedViewModelItem()) + { + return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP; + } + return false; } if("can_activate_group" == item) -- cgit v1.2.3 From df5378cf38b0e8325ae41be8af772e30cb815dd4 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Tue, 8 Jan 2013 19:59:27 +0200 Subject: CHUI-611 Fixed! Text in torn off message panel not wrapping correctly with size of conversation panel --- indra/newview/llfloaterimcontainer.cpp | 2 +- .../skins/default/xui/en/floater_im_container.xml | 30 ++++++---------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82563b8736..38528f18f0 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -162,7 +162,7 @@ BOOL LLFloaterIMContainer::postBuild() setTabContainer(getChild("im_box_tab_container")); mStubPanel = getChild("stub_panel"); - mStubTextBox = getChild("stub_textbox_2"); + mStubTextBox = getChild("stub_textbox"); mStubTextBox->setURLClickedCallback(boost::bind(&LLFloaterIMContainer::returnFloaterToHost, this)); mConversationsStack = getChild("conversations_stack"); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 951665552f..12c1676127 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -161,32 +161,18 @@ - This conversation is in a separate window. - - - [secondlife:/// Bring it back.] - + This conversation is in a separate window. [secondlife:/// Bring it back.] + -- cgit v1.2.3 From 974720373d608a8cbcd3cd26c125b6487b5926a2 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 8 Jan 2013 12:21:47 -0800 Subject: CHUI-660: Problem: Upon auto-existing DND mode upon startup, the notification form elements (buttonts) were added to the form. But then deserialized form elements were also being added to the form causing duplicate buttons. As a solution, only add on the deserialized form elements that exceed the amount in the template. --- indra/llui/llnotifications.cpp | 18 ++- indra/llui/llnotifications.h | 1 + indra/newview/lltoastnotifypanel.cpp | 300 +++++++++++++++++------------------ 3 files changed, 168 insertions(+), 151 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 386345177d..ebdb4d5024 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -320,6 +320,11 @@ void LLNotificationForm::addElement(const std::string& type, const std::string& mFormData.append(element); } +void LLNotificationForm::addElement(const LLSD& element) +{ + mFormData.append(element); +} + void LLNotificationForm::append(const LLSD& sub_form) { if (sub_form.isArray()) @@ -818,7 +823,18 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); - mForm->append(form_elements); + + //Prevents appending elements(buttons) that the template already had + if(form_elements.isArray() + && mForm->getNumElements() < form_elements.size()) + { + LLSD::array_const_iterator it = form_elements.beginArray() + mForm->getNumElements();; + + for(; it != form_elements.endArray(); ++it) + { + mForm->addElement(*it); + } + } // apply substitution to form labels mForm->formatElements(mSubstitutions); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 092a9acd7c..96e0a86b7f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -246,6 +246,7 @@ public: bool getElementEnabled(const std::string& element_name) const; void setElementEnabled(const std::string& element_name, bool enabled); void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); + void addElement(const LLSD &element); void formatElements(const LLSD& substitutions); // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 844d7314d9..d494d12903 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -343,156 +343,156 @@ void LLToastNotifyPanel::onClickButton(void* data) void LLToastNotifyPanel::init( LLRect rect, bool show_images ) { - deleteAllChildren(); - - mTextBox = NULL; - mInfoPanel = NULL; - mControlPanel = NULL; - mNumOptions = 0; - mNumButtons = 0; - mAddedDefaultBtn = false; - - buildFromFile( "panel_notification.xml"); - if(rect != LLRect::null) - { - this->setShape(rect); - } - mInfoPanel = getChild("info_panel"); - mInfoPanel->setFollowsAll(); - - mControlPanel = getChild("control_panel"); - BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); - // customize panel's attributes - // is it intended for displaying a tip? - mIsTip = mNotification->getType() == "notifytip"; - // is it a script dialog? - mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); - // is it a caution? - // - // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the - // notify xml template specifies that it is a caution - // tip-style notification handle 'caution' differently -they display the tip in a different color - mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - - // setup parameters - // get a notification message - mMessage = mNotification->getMessage(); - // init font variables - if (!sFont) -{ - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); -} - // initialize - setFocusRoot(!mIsTip); - // get a form for the notification - LLNotificationFormPtr form(mNotification->getForm()); - // get number of elements - mNumOptions = form->getNumElements(); - - // customize panel's outfit - // preliminary adjust panel's layout - //move to the end - //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - - // adjust text options according to the notification type - // add a caution textbox at the top of a caution notification - if (mIsCaution && !mIsTip) - { - mTextBox = getChild("caution_text_box"); - } - else - { - mTextBox = getChild("text_editor_box"); - } - - mTextBox->setMaxTextLength(MAX_LENGTH); - mTextBox->setVisible(TRUE); - mTextBox->setPlainText(!show_images); - mTextBox->setValue(mNotification->getMessage()); - - // add buttons for a script notification - if (mIsTip) - { - adjustPanelForTipNotice(); - } - else -{ - std::vector buttons; - buttons.reserve(mNumOptions); - S32 buttons_width = 0; - // create all buttons and accumulate they total width to reshape mControlPanel - for (S32 i = 0; i < mNumOptions; i++) - { - LLSD form_element = form->getElement(i); - if (form_element["type"].asString() != "button") - { - // not a button. - continue; - } - if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) - { - // a textbox pretending to be a button. - continue; - } - LLButton* new_button = createButton(form_element, TRUE); - buttons_width += new_button->getRect().getWidth(); - S32 index = form_element["index"].asInteger(); - buttons.push_back(index_button_pair_t(index,new_button)); -} - if (buttons.empty()) -{ - addDefaultButton(); - } - else - { - const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel - S32 button_panel_height = mControlPanel->getRect().getHeight(); - //try get an average h_pad to spread out buttons - S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); - if(h_pad < 2*HPAD) - { - /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ - S32 button_per_row = button_panel_width / BUTTON_WIDTH; - h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row - if(h_pad < 2*HPAD) // still not enough space between buttons ? - { - h_pad = 2*HPAD; - } -} - if (mIsScriptDialog) -{ - // we are using default width for script buttons so we can determinate button_rows - //to get a number of rows we divide the required width of the buttons to button_panel_width - S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); - //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; - //reserve one row for the ignore_btn - button_rows++; - //calculate required panel height for scripdialog notification. - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; - } - else - { - // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width - //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); - S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); - //calculate required panel height - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; -} - - // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed - adjustPanelForScriptNotice(button_panel_width, button_panel_height); - updateButtonsLayout(buttons, h_pad); - // save buttons for later use in disableButtons() - //mButtons.assign(buttons.begin(), buttons.end()); - } - } - // adjust panel's height to the text size - snapToMessageHeight(mTextBox, MAX_LENGTH); + deleteAllChildren(); + + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + buildFromFile( "panel_notification.xml"); + if(rect != LLRect::null) + { + this->setShape(rect); + } + mInfoPanel = getChild("info_panel"); + mInfoPanel->setFollowsAll(); + + mControlPanel = getChild("control_panel"); + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes + // is it intended for displaying a tip? + mIsTip = mNotification->getType() == "notifytip"; + // is it a script dialog? + mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); + // is it a caution? + // + // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the + // notify xml template specifies that it is a caution + // tip-style notification handle 'caution' differently -they display the tip in a different color + mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + + // setup parameters + // get a notification message + mMessage = mNotification->getMessage(); + // init font variables + if (!sFont) + { + sFont = LLFontGL::getFontSansSerif(); + sFontSmall = LLFontGL::getFontSansSerifSmall(); + } + // initialize + setFocusRoot(!mIsTip); + // get a form for the notification + LLNotificationFormPtr form(mNotification->getForm()); + // get number of elements + mNumOptions = form->getNumElements(); + + // customize panel's outfit + // preliminary adjust panel's layout + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + + // adjust text options according to the notification type + // add a caution textbox at the top of a caution notification + if (mIsCaution && !mIsTip) + { + mTextBox = getChild("caution_text_box"); + } + else + { + mTextBox = getChild("text_editor_box"); + } + + mTextBox->setMaxTextLength(MAX_LENGTH); + mTextBox->setVisible(TRUE); + mTextBox->setPlainText(!show_images); + mTextBox->setValue(mNotification->getMessage()); + + // add buttons for a script notification + if (mIsTip) + { + adjustPanelForTipNotice(); + } + else + { + std::vector buttons; + buttons.reserve(mNumOptions); + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) + { + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + // not a button. + continue; + } + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + // a textbox pretending to be a button. + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel + S32 button_panel_height = mControlPanel->getRect().getHeight(); + //try get an average h_pad to spread out buttons + S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); + if(h_pad < 2*HPAD) + { + /* + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ + S32 button_per_row = button_panel_width / BUTTON_WIDTH; + h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + if(h_pad < 2*HPAD) // still not enough space between buttons ? + { + h_pad = 2*HPAD; + } + } + if (mIsScriptDialog) + { + // we are using default width for script buttons so we can determinate button_rows + //to get a number of rows we divide the required width of the buttons to button_panel_width + S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); + //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + //reserve one row for the ignore_btn + button_rows++; + //calculate required panel height for scripdialog notification. + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; + } + else + { + // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width + //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); + S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); + //calculate required panel height + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; + } + + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + adjustPanelForScriptNotice(button_panel_width, button_panel_height); + updateButtonsLayout(buttons, h_pad); + // save buttons for later use in disableButtons() + //mButtons.assign(buttons.begin(), buttons.end()); + } + } + // adjust panel's height to the text size + snapToMessageHeight(mTextBox, MAX_LENGTH); } -- cgit v1.2.3 From 856969285e027def5acba6c252dc65a242349d4f Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Thu, 10 Jan 2013 14:56:33 +0200 Subject: CHUI-658 FIXED Don't highlight whole content of the folder after right clicking if it is flashing. --- indra/llui/llfolderviewitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 42e5a6debf..ad18adddd5 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -736,7 +736,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo getRect().getWidth() - 2, 0, focusOutlineColor, FALSE); - if (showContent) + if (showContent && !isFlashing()) { gl_rect_2d(FOCUS_LEFT, focus_bottom + 1, -- cgit v1.2.3 From def252341a8c1675405404a6588749d06fa40791 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Tue, 8 Jan 2013 23:37:29 +0200 Subject: CHUI-612 FIXED Blank conversation names showing in conversation list --- indra/newview/llconversationmodel.cpp | 129 +++++++++++++++++++++------------ indra/newview/llconversationmodel.h | 20 +++-- indra/newview/llfloaterimcontainer.cpp | 9 ++- 3 files changed, 102 insertions(+), 56 deletions(-) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 0243fb1c97..a8da4908ce 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -47,7 +47,8 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } @@ -58,7 +59,8 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } @@ -69,10 +71,21 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod mNeedsRefresh(true), mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), - mDisplayModeratorOptions(false) + mDisplayModeratorOptions(false), + mAvatarNameCacheConnection() { } +LLConversationItem::~LLConversationItem() +{ + // Disconnect any previous avatar name cache connection to ensure + // that the callback method is not called after destruction + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) { LLUUID session_id = (session ? session->getUUID() : LLUUID()); @@ -142,6 +155,37 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 } } +// method does subscription to changes in avatar name cache for current session/participant conversation item. +void LLConversationItem::fetchAvatarName(bool isParticipant /*= true*/) +{ + LLUUID item_id = getUUID(); + + // item should not be null for participants + if (isParticipant) + { + llassert(item_id.notNull()); + } + + // disconnect any previous avatar name cache connection + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + // exclude nearby chat item + if (item_id.notNull()) + { + // for P2P session item, override it as item of called agent + if (CONV_SESSION_1_ON_1 == getType()) + { + item_id = LLIMModel::getInstance()->getOtherParticipantID(item_id); + } + + // subscribe on avatar name cache changes for participant and session items + mAvatarNameCacheConnection = LLAvatarNameCache::get(item_id, boost::bind(&LLConversationItem::onAvatarNameCache, this, _2)); + } +} + // // LLConversationItemSession // @@ -169,11 +213,11 @@ void LLConversationItemSession::addParticipant(LLConversationItemParticipant* pa addChild(participant); mIsLoaded = true; mNeedsRefresh = true; - updateParticipantName(participant); + updateName(participant); postEvent("add_participant", this, participant); } -void LLConversationItemSession::updateParticipantName(LLConversationItemParticipant* participant) +void LLConversationItemSession::updateName(LLConversationItemParticipant* participant) { EConversationType conversation_type = getType(); // We modify the session name only in the case of an ad-hoc session or P2P session, exit otherwise (nothing to do) @@ -181,11 +225,13 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip { return; } + // Avoid changing the default name if no participant present yet if (mChildren.size() == 0) { return; } + uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string if (conversation_type == CONV_SESSION_AD_HOC) { @@ -210,12 +256,14 @@ void LLConversationItemSession::updateParticipantName(LLConversationItemParticip } else if (conversation_type == CONV_SESSION_1_ON_1) { - // In the case of a P2P conversersation, we need to grab the name of the other participant in the session instance itself + // In the case of a P2P conversation, we need to grab the name of the other participant in the session instance itself // as we do not create participants for such a session. - LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(mUUID); - LLUUID participantID = conversationFloater->getOtherParticipantUUID(); - temp_uuids.push_back(participantID); + if (gAgentID != participant->getUUID()) + { + temp_uuids.push_back(participant->getUUID()); + } } + if (temp_uuids.size() != 0) { std::string new_session_name; @@ -229,7 +277,7 @@ void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* { removeChild(participant); mNeedsRefresh = true; - updateParticipantName(participant); + updateName(participant); postEvent("remove_participant", this, participant); } @@ -393,6 +441,18 @@ void LLConversationItemSession::dumpDebugData(bool dump_children) } } +// should be invoked only for P2P sessions +void LLConversationItemSession::onAvatarNameCache(const LLAvatarName& av_name) +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + renameItem(av_name.getDisplayName()); + postEvent("update_session", this, NULL); +} + // // LLConversationItemParticipant // @@ -401,8 +461,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display LLConversationItem(display_name,uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0), - mAvatarNameCacheConnection() + mDistToAgent(-1.0) { mDisplayName = display_name; mConvType = CONV_PARTICIPANT; @@ -412,38 +471,12 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLConversationItem(uuid,root_view_model), mIsMuted(false), mIsModerator(false), - mDistToAgent(-1.0), - mAvatarNameCacheConnection() + mDistToAgent(-1.0) { mConvType = CONV_PARTICIPANT; } -LLConversationItemParticipant::~LLConversationItemParticipant() -{ - // Disconnect any previous avatar name cache connection to ensure - // that the callback method is not called after destruction - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } -} - -void LLConversationItemParticipant::fetchAvatarName() -{ - // Request the avatar name from the cache - llassert(getUUID().notNull()); - if (getUUID().notNull()) - { - // Disconnect any previous avatar name cache connection - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } - mAvatarNameCacheConnection = LLAvatarNameCache::get(getUUID(), boost::bind(&LLConversationItemParticipant::onAvatarNameCache, this, _2)); - } -} - -void LLConversationItemParticipant::updateAvatarName() +void LLConversationItemParticipant::updateName() { llassert(getUUID().notNull()); if (getUUID().notNull()) @@ -451,29 +484,33 @@ void LLConversationItemParticipant::updateAvatarName() LLAvatarName av_name; if (LLAvatarNameCache::get(getUUID(),&av_name)) { - updateAvatarName(av_name); + updateName(av_name); } } } void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mAvatarNameCacheConnection.disconnect(); - updateAvatarName(av_name); + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } + + updateName(av_name); } -void LLConversationItemParticipant::updateAvatarName(const LLAvatarName& av_name) +void LLConversationItemParticipant::updateName(const LLAvatarName& av_name) { mName = av_name.getUserName(); mDisplayName = av_name.getDisplayName(); - mNeedsRefresh = true; + renameItem(mDisplayName); if (mParent != NULL) { LLConversationItemSession* parent_session = dynamic_cast(mParent); if (parent_session != NULL) { parent_session->requestSort(); - parent_session->updateParticipantName(this); + parent_session->updateName(this); postEvent("update_participant", parent_session, this); } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 01b3850f5e..6aaea041e4 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -64,7 +64,7 @@ public: LLConversationItem(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItem(LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItem() {} + virtual ~LLConversationItem(); // Stub those things we won't really be using in this conversation context virtual const std::string& getName() const { return mName; } @@ -132,27 +132,31 @@ public: void buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags); + void fetchAvatarName(bool isParticipant = true); // fetch and update the avatar name + protected: + virtual void onAvatarNameCache(const LLAvatarName& av_name) {} + std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant EConversationType mConvType; // Type of conversation item bool mNeedsRefresh; // Flag signaling to the view that something changed for this item F64 mLastActiveTime; bool mDisplayModeratorOptions; -}; + boost::signals2::connection mAvatarNameCacheConnection; +}; class LLConversationItemSession : public LLConversationItem { public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItemSession() {} /*virtual*/ bool hasChildren() const; LLPointer getIcon() const { return NULL; } void setSessionID(const LLUUID& session_id) { mUUID = session_id; mNeedsRefresh = true; } void addParticipant(LLConversationItemParticipant* participant); - void updateParticipantName(LLConversationItemParticipant* participant); + void updateName(LLConversationItemParticipant* participant); void removeParticipant(LLConversationItemParticipant* participant); void removeParticipant(const LLUUID& participant_id); void clearParticipants(); @@ -172,6 +176,8 @@ public: void dumpDebugData(bool dump_children = false); private: + /*virtual*/ void onAvatarNameCache(const LLAvatarName& av_name); + bool mIsLoaded; // true if at least one participant has been added to the session, false otherwise }; @@ -180,7 +186,6 @@ class LLConversationItemParticipant : public LLConversationItem public: LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); - virtual ~LLConversationItemParticipant(); virtual const std::string& getDisplayName() const { return mDisplayName; } @@ -195,8 +200,7 @@ public: virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } - void fetchAvatarName(); // fetch and update the avatar name - void updateAvatarName(); // get from the cache (do *not* fetch) and update the avatar name + void updateName(); // get from the cache (do *not* fetch) and update the avatar name LLConversationItemSession* getParentSession(); void dumpDebugData(); @@ -204,7 +208,7 @@ public: private: void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName - void updateAvatarName(const LLAvatarName& av_name); + void updateName(const LLAvatarName& av_name); bool mIsMuted; // default is false bool mIsModerator; // default is false diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 38528f18f0..a599fb51e1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -380,7 +380,7 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate() { LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); // Get the avatar name for this participant id from the cache and update the model - participant_model->updateAvatarName(); + participant_model->updateName(); // Next participant current_participant_model++; } @@ -1390,7 +1390,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& return NULL; } item->renameItem(display_name); - item->updateParticipantName(NULL); + item->updateName(NULL); mConversationsItems[uuid] = item; @@ -1419,6 +1419,11 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID& } } + if (uuid.notNull() && im_sessionp->isP2PSessionType()) + { + item->fetchAvatarName(false); + } + // Do that too for the conversation dialog LLFloaterIMSessionTab *conversation_floater = (uuid.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(uuid))); if (conversation_floater) -- cgit v1.2.3 From b5172de28fd6bb8a833cf93180d2d43dd9d4a073 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 8 Jan 2013 17:06:49 -0800 Subject: CHUI-660: Post code review changes --- indra/llui/llnotifications.cpp | 51 +++++++++++++--------- indra/llui/llnotifications.h | 4 +- .../newview/lldonotdisturbnotificationstorage.cpp | 2 +- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index ebdb4d5024..a5492b46f7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -279,6 +279,18 @@ bool LLNotificationForm::hasElement(const std::string& element_name) const return false; } +void LLNotificationForm::getElements(LLSD& elements, S32 offset) +{ + //Finds elements that the template did not add + LLSD::array_const_iterator it = mFormData.beginArray() + offset; + + //Keeps track of only the dynamic elements + for(; it != mFormData.endArray(); ++it) + { + elements.append(*it); + } +} + bool LLNotificationForm::getElementEnabled(const std::string& element_name) const { for (LLSD::array_const_iterator it = mFormData.beginArray(); @@ -320,11 +332,6 @@ void LLNotificationForm::addElement(const std::string& type, const std::string& mFormData.append(element); } -void LLNotificationForm::addElement(const LLSD& element) -{ - mFormData.append(element); -} - void LLNotificationForm::append(const LLSD& sub_form) { if (sub_form.isArray()) @@ -508,21 +515,36 @@ LLNotification::LLNotification(const LLSDParamAdapter& p) : } -LLSD LLNotification::asLLSD() +LLSD LLNotification::asLLSD(bool excludeTemplateElements) { LLParamSDParser parser; Params p; p.id = mId; p.name = mTemplatep->mName; - p.form_elements = getForm()->asLLSD(); - p.substitutions = mSubstitutions; p.payload = mPayload; p.time_stamp = mTimestamp; p.expiry = mExpiresAt; p.priority = mPriority; + LLNotificationFormPtr templateForm = mTemplatep->mForm; + LLSD formElements = mForm->asLLSD(); + + //All form elements (dynamic or not) + if(!excludeTemplateElements) + { + p.form_elements = formElements; + } + //Only dynamic form elements (exclude template elements) + else if(templateForm->getNumElements() < formElements.size()) + { + LLSD dynamicElements; + //Offset to dynamic elements and store them + mForm->getElements(dynamicElements, templateForm->getNumElements()); + p.form_elements = dynamicElements; + } + if(mResponder) { p.functor.responder_sd = mResponder->asLLSD(); @@ -823,18 +845,7 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); - - //Prevents appending elements(buttons) that the template already had - if(form_elements.isArray() - && mForm->getNumElements() < form_elements.size()) - { - LLSD::array_const_iterator it = form_elements.beginArray() + mForm->getNumElements();; - - for(; it != form_elements.endArray(); ++it) - { - mForm->addElement(*it); - } - } + mForm->append(form_elements); // apply substitution to form labels mForm->formatElements(mSubstitutions); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 96e0a86b7f..236c2a42d1 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -242,11 +242,11 @@ public: S32 getNumElements() { return mFormData.size(); } LLSD getElement(S32 index) { return mFormData.get(index); } LLSD getElement(const std::string& element_name); + void getElements(LLSD& elements, S32 offset = 0); bool hasElement(const std::string& element_name) const; bool getElementEnabled(const std::string& element_name) const; void setElementEnabled(const std::string& element_name, bool enabled); void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true); - void addElement(const LLSD &element); void formatElements(const LLSD& substitutions); // appends form elements from another form serialized as LLSD void append(const LLSD& sub_form); @@ -457,7 +457,7 @@ public: // ["time"] = time at which notification was generated; // ["expiry"] = time at which notification expires; // ["responseFunctor"] = name of registered functor that handles responses to notification; - LLSD asLLSD(); + LLSD asLLSD(bool excludeTemplateElements = false); const LLNotificationFormPtr getForm(); void updateForm(const LLNotificationFormPtr& form); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 9bb2f27a46..ac41a3804f 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -77,7 +77,7 @@ void LLDoNotDisturbNotificationStorage::saveNotifications() if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired()) { - data.append(notificationPtr->asLLSD()); + data.append(notificationPtr->asLLSD(true)); } } -- cgit v1.2.3 From 4ef1181cdcb03a08fbce8d774cd85ef914bef8f3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 8 Jan 2013 21:46:00 -0800 Subject: CHUI-659 : Fixed : Reimplemented open selection on hitting return the right way --- indra/llui/llfolderview.cpp | 86 -------------------------------------- indra/llui/llfolderview.h | 4 -- indra/llui/llfolderviewmodel.h | 2 +- indra/newview/llinventorypanel.cpp | 20 ++++++++- indra/newview/llinventorypanel.h | 1 + 5 files changed, 20 insertions(+), 93 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7ae79d94fe..324142f6c3 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -275,17 +275,6 @@ BOOL LLFolderView::canFocusChildren() const void LLFolderView::addFolder( LLFolderViewFolder* folder) { LLFolderViewFolder::addFolder(folder); - - // TODO RN: enforce sort order of My Inventory followed by Library - //mFolders.remove(folder); - //if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) - //{ - // mFolders.push_back(folder); - //} - //else - //{ - // mFolders.insert(mFolders.begin(), folder); - //} } void LLFolderView::closeAllFolders() @@ -793,76 +782,6 @@ void LLFolderView::removeSelectedItems() } } -// TODO RN: abstract -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // mSelectedItems.front()->openItem(); - // } - // else - // { - // LLMultiPreview* multi_previewp = new LLMultiPreview(); - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // // IT_{OBJECT,ATTACHMENT} creates LLProperties - // // floaters; others create LLPreviews. Put - // // each one in the right type of container. - // LLFolderViewModelItemInventory* listener = static_cast((*item_it)->getViewModelItem()); - // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - // if (is_prop) - // LLFloater::setFloaterHost(multi_propertiesp); - // else - // LLFloater::setFloaterHost(multi_previewp); - // listener->openItem(); - // } - - // LLFloater::setFloaterHost(NULL); - // // *NOTE: LLMulti* will safely auto-delete when open'd - // // without any children. - // multi_previewp->openFloater(LLSD()); - // multi_propertiesp->openFloater(LLSD()); - // } - //} - } - -void LLFolderView::propertiesSelectedItems( void ) -{ - //TODO RN: get working again - //if(getVisible() && getEnabled()) - //{ - // if (mSelectedItems.size() == 1) - // { - // LLFolderViewItem* folder_item = mSelectedItems.front(); - // if(!folder_item) return; - // folder_item->getViewModelItem()->showProperties(); - // } - // else - // { - // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - // LLFloater::setFloaterHost(multi_propertiesp); - - // selected_items_t::iterator item_it; - // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - // { - // (*item_it)->getViewModelItem()->showProperties(); - // } - - // LLFloater::setFloaterHost(NULL); - // multi_propertiesp->openFloater(LLSD()); - // } - //} - } - - void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) { if ((mAutoOpenItems.check() == item) || @@ -1151,11 +1070,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) mSearchString.clear(); handled = TRUE; } - else - { - LLFolderView::openSelectedItems(); - handled = TRUE; - } } break; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 2ee7417240..a6e0a3b4c0 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -163,10 +163,6 @@ public: // Deletion functionality void removeSelectedItems(); - // Open the selected item - void openSelectedItems( void ); - void propertiesSelectedItems( void ); - void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 5837052565..1b61212c0e 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -127,7 +127,7 @@ public: virtual bool startDrag(std::vector& items) = 0; }; -// This is am abstract base class that users of the folderview classes +// This is an abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data class LLFolderViewModelItem : public LLRefCount { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 81e7f166e1..25dc365467 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -684,8 +684,9 @@ void LLInventoryPanel::initializeViews() } else { - buildNewViews(gInventory.getRootFolderID()); - buildNewViews(gInventory.getLibraryRootFolderID()); + // Default case: always add "My Inventory" first, "Library" second + buildNewViews(gInventory.getRootFolderID()); // My Inventory + buildNewViews(gInventory.getLibraryRootFolderID()); // Library } gIdleCallbacks.addFunction(idle, this); @@ -1354,6 +1355,21 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata) return; } +BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + // Open selected items if enter key hit on the inventory panel + if (mask == MASK_NONE) + { + LLInventoryAction::doToSelected(mInventory, mFolderRoot, "open"); + handled = TRUE; + } + } + return handled; +} /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 9639086c11..6eb85fbad2 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -143,6 +143,7 @@ public: // LLView methods void draw(); + /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, -- cgit v1.2.3 From 3cf2d8e9eac215024bc216958b0920e61aa25de1 Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Wed, 9 Jan 2013 10:41:09 +0200 Subject: CHUI-665 (Change "Open conversation log" to "Conversation log..." in communication floater view/sort menu) --- indra/newview/skins/default/xui/en/menu_participant_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 33d7bd7c01..2f2bafb95d 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -76,7 +76,7 @@ parameter="privacy_preferences" /> Date: Wed, 9 Jan 2013 15:08:58 +0200 Subject: CHUI-638 FIXED Don't force button and widget to flash if the object is muted. --- indra/newview/llimview.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0011f54175..0326235d37 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -225,12 +225,17 @@ void on_new_message(const LLSD& msg) //User is not focused on conversation containing the message if(session_floater_not_focused) { - im_box->flashConversationItemWidget(session_id, true); - + if(!LLMuteList::getInstance()->isMuted(participant_id)) + { + im_box->flashConversationItemWidget(session_id, true); + } //The conversation floater isn't focused/open if(conversation_floater_not_focused) { - gToolBarView->flashCommand(LLCommandId("chat"), true); + if(!LLMuteList::getInstance()->isMuted(participant_id)) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } //Show IM toasts (upper right toasts) // Skip toasting for system messages and for nearby chat -- cgit v1.2.3 From 8e8765535f94d3084305ef7b9e4644ec92d10723 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 9 Jan 2013 12:41:51 -0500 Subject: SH-3620: Fix for editing a nocopy wearable being removed from the outfit --- indra/newview/llpaneleditwearable.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 786b215fdf..606e78bd58 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -882,9 +882,12 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c //static void LLPanelEditWearable::onBackButtonClicked(void* userdata) -{ - LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; - panel->saveChanges(true); +{ + LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; + if ( panel->isDirty() ) + { + LLAppearanceMgr::instance().setOutfitDirty( true ); + } } //static -- cgit v1.2.3 From 547f48eabe6b363de9b8551074b004041814ea12 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 9 Jan 2013 15:43:09 -0500 Subject: SH-3600. Undo change is disabled upon reentry into the appearance panel --- indra/newview/llsidepanelappearance.cpp | 1089 ++++++++++++++++--------------- 1 file changed, 545 insertions(+), 544 deletions(-) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 98dc2c0e09..f0844dd9a4 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -1,544 +1,545 @@ -/** - * @file llsidepanelappearance.cpp - * @brief Side Bar "Appearance" panel - * - * $LicenseInfo:firstyear=2009&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 "llsidepanelappearance.h" - -#include "llaccordionctrltab.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llappearancemgr.h" -#include "llfloatersidepanelcontainer.h" -#include "llfolderview.h" -#include "llinventorypanel.h" -#include "llfiltereditor.h" -#include "llfloaterreg.h" -#include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" -#include "lloutfitobserver.h" -#include "llpaneleditwearable.h" -#include "llpaneloutfitsinventory.h" -#include "lltextbox.h" -#include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerregion.h" -#include "llvoavatarself.h" -#include "llviewerwearable.h" - -static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); - -class LLCurrentlyWornFetchObserver : public LLInventoryFetchItemsObserver -{ -public: - LLCurrentlyWornFetchObserver(const uuid_vec_t &ids, - LLSidepanelAppearance *panel) : - LLInventoryFetchItemsObserver(ids), - mPanel(panel) - {} - ~LLCurrentlyWornFetchObserver() {} - virtual void done() - { - mPanel->inventoryFetched(); - gInventory.removeObserver(this); - delete this; - } -private: - LLSidepanelAppearance *mPanel; -}; - -LLSidepanelAppearance::LLSidepanelAppearance() : - LLPanel(), - mFilterSubString(LLStringUtil::null), - mFilterEditor(NULL), - mOutfitEdit(NULL), - mCurrOutfitPanel(NULL), - mOpened(false) -{ - LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); - outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); - outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); - outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); - - gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true)); - gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false)); -} - -LLSidepanelAppearance::~LLSidepanelAppearance() -{ -} - -// virtual -BOOL LLSidepanelAppearance::postBuild() -{ - mOpenOutfitBtn = getChild("openoutfit_btn"); - mOpenOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onOpenOutfitButtonClicked, this)); - - mEditAppearanceBtn = getChild("editappearance_btn"); - mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); - - childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); - - mNewOutfitBtn = getChild("newlook_btn"); - mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); - mNewOutfitBtn->setEnabled(false); - - mFilterEditor = getChild("Filter"); - if (mFilterEditor) - { - mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); - } - - mPanelOutfitsInventory = dynamic_cast(getChild("panel_outfits_inventory")); - - mOutfitEdit = dynamic_cast(getChild("panel_outfit_edit")); - if (mOutfitEdit) - { - LLButton* back_btn = mOutfitEdit->getChild("back_btn"); - if (back_btn) - { - back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this)); - } - - } - - mEditWearable = dynamic_cast(getChild("panel_edit_wearable")); - if (mEditWearable) - { - LLButton* edit_wearable_back_btn = mEditWearable->getChild("back_btn"); - if (edit_wearable_back_btn) - { - edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); - } - } - - mCurrentLookName = getChild("currentlook_name"); - - mOutfitStatus = getChild("currentlook_status"); - - mCurrOutfitPanel = getChild("panel_currentlook"); - - - setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); - - return TRUE; -} - -// virtual -void LLSidepanelAppearance::onOpen(const LLSD& key) -{ - if (!key.has("type")) - { - // No specific panel requested. - // If we're opened for the first time then show My Outfits. - // Else do nothing. - if (!mOpened) - { - showOutfitsInventoryPanel(); - } - } - else - { - // Switch to the requested panel. - std::string type = key["type"].asString(); - if (type == "my_outfits") - { - showOutfitsInventoryPanel(); - } - else if (type == "edit_outfit") - { - showOutfitEditPanel(); - } - else if (type == "edit_shape") - { - showWearableEditPanel(); - } - } - - mOpened = true; -} - -void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) -{ - LLSD visibility; - visibility["visible"] = new_visibility.asBoolean(); - visibility["reset_accordion"] = false; - updateToVisibility(visibility); -} - -void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) -{ - if (new_visibility["visible"].asBoolean()) - { - const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible(); - const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible(); - - if (is_outfit_edit_visible || is_wearable_edit_visible) - { - const LLViewerWearable *wearable_ptr = mEditWearable->getWearable(); - if (!wearable_ptr) - { - llwarns << "Visibility change to invalid wearable" << llendl; - return; - } - // Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar - // when editing its physics. - if (!gAgentCamera.cameraCustomizeAvatar()) - { - LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); - } - if (is_wearable_edit_visible) - { - if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE) - { - // we're no longer wearing the wearable we were last editing, switch back to outfit editor - showOutfitEditPanel(); - } - } - - if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean()) - { - mOutfitEdit->resetAccordionState(); - } - } - } - else - { - if (gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement")) - { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); - } - } -} - -void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) -{ - if (mFilterSubString != search_string) - { - mFilterSubString = search_string; - - // Searches are case-insensitive - // but we don't convert the typed string to upper-case so that it can be fed to the web search as-is. - - mPanelOutfitsInventory->onSearchEdit(mFilterSubString); - } -} - -void LLSidepanelAppearance::onOpenOutfitButtonClicked() -{ - const LLViewerInventoryItem *outfit_link = LLAppearanceMgr::getInstance()->getBaseOutfitLink(); - if (!outfit_link) - return; - if (!outfit_link->getIsLinkType()) - return; - - LLAccordionCtrlTab* tab_outfits = mPanelOutfitsInventory->findChild("tab_outfits"); - if (tab_outfits) - { - tab_outfits->changeOpenClose(FALSE); - LLInventoryPanel *inventory_panel = tab_outfits->findChild("outfitslist_tab"); - if (inventory_panel) - { - LLFolderView* root = inventory_panel->getRootFolder(); - LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); - if (outfit_folder) - { - outfit_folder->setOpen(!outfit_folder->isOpen()); - root->setSelectionFromRoot(outfit_folder,TRUE); - root->scrollToShowSelection(); - } - } - } -} - -// *TODO: obsolete? -void LLSidepanelAppearance::onEditAppearanceButtonClicked() -{ - if (gAgentWearables.areWearablesLoaded()) - { - LLVOAvatarSelf::onCustomizeStart(); - } -} - -void LLSidepanelAppearance::onNewOutfitButtonClicked() -{ - if (!mOutfitEdit->getVisible()) - { - mPanelOutfitsInventory->onSave(); - } -} - -void LLSidepanelAppearance::showOutfitsInventoryPanel() -{ - toggleWearableEditPanel(FALSE); - toggleOutfitEditPanel(FALSE); - toggleMyOutfitsPanel(TRUE); -} - -void LLSidepanelAppearance::showOutfitEditPanel() -{ - if (mOutfitEdit && mOutfitEdit->getVisible()) return; - - // Accordion's state must be reset in all cases except the one when user - // is returning back to the mOutfitEdit panel from the mEditWearable panel. - // The simplest way to control this is to check the visibility state of the mEditWearable - // BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE). - if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL) - { - mOutfitEdit->resetAccordionState(); - } - - // If we're exiting the edit wearable view, and the camera was not focused on the avatar - // (e.g. such as if we were editing a physics param), then skip the outfits edit mode since - // otherwise this would trigger the camera focus mode. - if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar()) - { - showOutfitsInventoryPanel(); - return; - } - - toggleMyOutfitsPanel(FALSE); - toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode - toggleOutfitEditPanel(TRUE); -} - -void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) -{ - toggleMyOutfitsPanel(FALSE); - toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode - toggleWearableEditPanel(TRUE, wearable, disable_camera_switch); -} - -void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible) -{ - if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible) - { - // visibility isn't changing, hence nothing to do - return; - } - - mPanelOutfitsInventory->setVisible(visible); - - // *TODO: Move these controls to panel_outfits_inventory.xml - // so that we don't need to toggle them explicitly. - mFilterEditor->setVisible(visible); - mNewOutfitBtn->setVisible(visible); - mCurrOutfitPanel->setVisible(visible); - - if (visible) - { - mPanelOutfitsInventory->onOpen(LLSD()); - } -} - -void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch) -{ - if (!mOutfitEdit || mOutfitEdit->getVisible() == visible) - { - // visibility isn't changing, hence nothing to do - return; - } - - mOutfitEdit->setVisible(visible); - - if (visible) - { - mOutfitEdit->onOpen(LLSD()); - LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); - } - else - { - if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. - { - LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); - } - } -} - -void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) -{ - if (!mEditWearable || mEditWearable->getVisible() == visible) - { - // visibility isn't changing, hence nothing to do - return; - } - - if (!wearable) - { - wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); - } - if (!wearable) - { - return; - } - - // Toggle panel visibility. - mEditWearable->setVisible(visible); - - if (visible) - { - LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); - mEditWearable->setWearable(wearable, disable_camera_switch); - mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency - } - else - { - // Save changes if closing. - mEditWearable->saveChanges(); - if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. - { - LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); - } - } -} - -void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) -{ - // Set current outfit status (wearing/unsaved). - bool dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); - std::string cof_status_str = getString(dirty ? "Unsaved Changes" : "Now Wearing"); - mOutfitStatus->setText(cof_status_str); - - if (name == "") - { - std::string outfit_name; - if (LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name)) - { - mCurrentLookName->setText(outfit_name); - return; - } - - std::string string_name = gAgentWearables.isCOFChangeInProgress() ? "Changing outfits" : "No Outfit"; - mCurrentLookName->setText(getString(string_name)); - mOpenOutfitBtn->setEnabled(FALSE); - } - else - { - mCurrentLookName->setText(name); - // Can't just call update verbs since the folder link may not have been created yet. - mOpenOutfitBtn->setEnabled(TRUE); - } -} - -//static -void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch) -{ - LLFloaterSidePanelContainer::showPanel("appearance", LLSD()); - - LLSidepanelAppearance *panel = dynamic_cast(data); - if (panel) - { - panel->showWearableEditPanel(wearable, disable_camera_switch); - } -} - -// Fetch currently worn items and only enable the New Look button after everything's been -// fetched. Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks. -void LLSidepanelAppearance::fetchInventory() -{ - - mNewOutfitBtn->setEnabled(false); - uuid_vec_t ids; - LLUUID item_id; - for(S32 type = (S32)LLWearableType::WT_SHAPE; type < (S32)LLWearableType::WT_COUNT; ++type) - { - for (U32 index = 0; index < gAgentWearables.getWearableCount((LLWearableType::EType)type); ++index) - { - item_id = gAgentWearables.getWearableItemID((LLWearableType::EType)type, index); - if(item_id.notNull()) - { - ids.push_back(item_id); - } - } - } - - if (isAgentAvatarValid()) - { - for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (!attachment) continue; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject* attached_object = (*attachment_iter); - if (!attached_object) continue; - const LLUUID& item_id = attached_object->getAttachmentItemID(); - if (item_id.isNull()) continue; - ids.push_back(item_id); - } - } - } - - LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(ids, this); - fetch_worn->startFetch(); - // If no items to be fetched, done will never be triggered. - // TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition. - if (fetch_worn->isFinished()) - { - fetch_worn->done(); - } - else - { - gInventory.addObserver(fetch_worn); - } -} - -void LLSidepanelAppearance::inventoryFetched() -{ - mNewOutfitBtn->setEnabled(true); -} - -void LLSidepanelAppearance::setWearablesLoading(bool val) -{ - getChildView("wearables_loading_indicator")->setVisible( val); - getChildView("edit_outfit_btn")->setVisible( !val); - - if (!val) - { - // refresh outfit name when COF is already changed. - refreshCurrentOutfitName(); - } -} - -void LLSidepanelAppearance::showDefaultSubpart() -{ - if (mEditWearable->getVisible()) - { - mEditWearable->showDefaultSubpart(); - } -} - -void LLSidepanelAppearance::updateScrollingPanelList() -{ - if (mEditWearable->getVisible()) - { - mEditWearable->updateScrollingPanelList(); - } -} +/** + * @file llsidepanelappearance.cpp + * @brief Side Bar "Appearance" panel + * + * $LicenseInfo:firstyear=2009&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 "llsidepanelappearance.h" + +#include "llaccordionctrltab.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llfloatersidepanelcontainer.h" +#include "llfolderview.h" +#include "llinventorypanel.h" +#include "llfiltereditor.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llfoldervieweventlistener.h" +#include "lloutfitobserver.h" +#include "llpaneleditwearable.h" +#include "llpaneloutfitsinventory.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "llviewerwearable.h" + +static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); + +class LLCurrentlyWornFetchObserver : public LLInventoryFetchItemsObserver +{ +public: + LLCurrentlyWornFetchObserver(const uuid_vec_t &ids, + LLSidepanelAppearance *panel) : + LLInventoryFetchItemsObserver(ids), + mPanel(panel) + {} + ~LLCurrentlyWornFetchObserver() {} + virtual void done() + { + mPanel->inventoryFetched(); + gInventory.removeObserver(this); + delete this; + } +private: + LLSidepanelAppearance *mPanel; +}; + +LLSidepanelAppearance::LLSidepanelAppearance() : + LLPanel(), + mFilterSubString(LLStringUtil::null), + mFilterEditor(NULL), + mOutfitEdit(NULL), + mCurrOutfitPanel(NULL), + mOpened(false) +{ + LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); + outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); + outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); + + gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true)); + gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false)); +} + +LLSidepanelAppearance::~LLSidepanelAppearance() +{ +} + +// virtual +BOOL LLSidepanelAppearance::postBuild() +{ + mOpenOutfitBtn = getChild("openoutfit_btn"); + mOpenOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onOpenOutfitButtonClicked, this)); + + mEditAppearanceBtn = getChild("editappearance_btn"); + mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); + + childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); + + mNewOutfitBtn = getChild("newlook_btn"); + mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); + mNewOutfitBtn->setEnabled(false); + + mFilterEditor = getChild("Filter"); + if (mFilterEditor) + { + mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); + } + + mPanelOutfitsInventory = dynamic_cast(getChild("panel_outfits_inventory")); + + mOutfitEdit = dynamic_cast(getChild("panel_outfit_edit")); + if (mOutfitEdit) + { + LLButton* back_btn = mOutfitEdit->getChild("back_btn"); + if (back_btn) + { + back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this)); + } + + } + + mEditWearable = dynamic_cast(getChild("panel_edit_wearable")); + if (mEditWearable) + { + LLButton* edit_wearable_back_btn = mEditWearable->getChild("back_btn"); + if (edit_wearable_back_btn) + { + edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); + } + } + + mCurrentLookName = getChild("currentlook_name"); + + mOutfitStatus = getChild("currentlook_status"); + + mCurrOutfitPanel = getChild("panel_currentlook"); + + + setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); + + return TRUE; +} + +// virtual +void LLSidepanelAppearance::onOpen(const LLSD& key) +{ + if (!key.has("type")) + { + // No specific panel requested. + // If we're opened for the first time then show My Outfits. + // Else do nothing. + if (!mOpened) + { + showOutfitsInventoryPanel(); + } + } + else + { + // Switch to the requested panel. + std::string type = key["type"].asString(); + if (type == "my_outfits") + { + showOutfitsInventoryPanel(); + } + else if (type == "edit_outfit") + { + showOutfitEditPanel(); + } + else if (type == "edit_shape") + { + showWearableEditPanel(); + } + } + + mOpened = true; +} + +void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) +{ + LLSD visibility; + visibility["visible"] = new_visibility.asBoolean(); + visibility["reset_accordion"] = false; + updateToVisibility(visibility); +} + +void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) +{ + if (new_visibility["visible"].asBoolean()) + { + const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible(); + const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible(); + + if (is_outfit_edit_visible || is_wearable_edit_visible) + { + const LLViewerWearable *wearable_ptr = mEditWearable->getWearable(); + if (!wearable_ptr) + { + llwarns << "Visibility change to invalid wearable" << llendl; + return; + } + // Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar + // when editing its physics. + if (!gAgentCamera.cameraCustomizeAvatar()) + { + LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); + } + if (is_wearable_edit_visible) + { + if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE) + { + // we're no longer wearing the wearable we were last editing, switch back to outfit editor + showOutfitEditPanel(); + } + } + + if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean()) + { + mOutfitEdit->resetAccordionState(); + } + } + } + else + { + if (gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement")) + { + gAgentCamera.changeCameraToDefault(); + gAgentCamera.resetView(); + } + } +} + +void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) +{ + if (mFilterSubString != search_string) + { + mFilterSubString = search_string; + + // Searches are case-insensitive + // but we don't convert the typed string to upper-case so that it can be fed to the web search as-is. + + mPanelOutfitsInventory->onSearchEdit(mFilterSubString); + } +} + +void LLSidepanelAppearance::onOpenOutfitButtonClicked() +{ + const LLViewerInventoryItem *outfit_link = LLAppearanceMgr::getInstance()->getBaseOutfitLink(); + if (!outfit_link) + return; + if (!outfit_link->getIsLinkType()) + return; + + LLAccordionCtrlTab* tab_outfits = mPanelOutfitsInventory->findChild("tab_outfits"); + if (tab_outfits) + { + tab_outfits->changeOpenClose(FALSE); + LLInventoryPanel *inventory_panel = tab_outfits->findChild("outfitslist_tab"); + if (inventory_panel) + { + LLFolderView* root = inventory_panel->getRootFolder(); + LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); + if (outfit_folder) + { + outfit_folder->setOpen(!outfit_folder->isOpen()); + root->setSelectionFromRoot(outfit_folder,TRUE); + root->scrollToShowSelection(); + } + } + } +} + +// *TODO: obsolete? +void LLSidepanelAppearance::onEditAppearanceButtonClicked() +{ + if (gAgentWearables.areWearablesLoaded()) + { + LLVOAvatarSelf::onCustomizeStart(); + } +} + +void LLSidepanelAppearance::onNewOutfitButtonClicked() +{ + if (!mOutfitEdit->getVisible()) + { + mPanelOutfitsInventory->onSave(); + } +} + +void LLSidepanelAppearance::showOutfitsInventoryPanel() +{ + toggleWearableEditPanel(FALSE); + toggleOutfitEditPanel(FALSE); + toggleMyOutfitsPanel(TRUE); +} + +void LLSidepanelAppearance::showOutfitEditPanel() +{ + if (mOutfitEdit && mOutfitEdit->getVisible()) return; + + // Accordion's state must be reset in all cases except the one when user + // is returning back to the mOutfitEdit panel from the mEditWearable panel. + // The simplest way to control this is to check the visibility state of the mEditWearable + // BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE). + if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL) + { + mOutfitEdit->resetAccordionState(); + } + + // If we're exiting the edit wearable view, and the camera was not focused on the avatar + // (e.g. such as if we were editing a physics param), then skip the outfits edit mode since + // otherwise this would trigger the camera focus mode. + if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar()) + { + showOutfitsInventoryPanel(); + return; + } + + toggleMyOutfitsPanel(FALSE); + toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode + toggleOutfitEditPanel(TRUE); +} + +void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) +{ + toggleMyOutfitsPanel(FALSE); + toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode + toggleWearableEditPanel(TRUE, wearable, disable_camera_switch); +} + +void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible) +{ + if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible) + { + // visibility isn't changing, hence nothing to do + return; + } + + mPanelOutfitsInventory->setVisible(visible); + + // *TODO: Move these controls to panel_outfits_inventory.xml + // so that we don't need to toggle them explicitly. + mFilterEditor->setVisible(visible); + mNewOutfitBtn->setVisible(visible); + mCurrOutfitPanel->setVisible(visible); + + if (visible) + { + mPanelOutfitsInventory->onOpen(LLSD()); + } +} + +void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch) +{ + if (!mOutfitEdit || mOutfitEdit->getVisible() == visible) + { + // visibility isn't changing, hence nothing to do + return; + } + + mOutfitEdit->setVisible(visible); + + if (visible) + { + mOutfitEdit->onOpen(LLSD()); + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); + } + else + { + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. + { + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); + LLAppearanceMgr::getInstance()->setOutfitDirty( FALSE ); + } + } +} + +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) +{ + if (!mEditWearable || mEditWearable->getVisible() == visible) + { + // visibility isn't changing, hence nothing to do + return; + } + + if (!wearable) + { + wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); + } + if (!wearable) + { + return; + } + + // Toggle panel visibility. + mEditWearable->setVisible(visible); + + if (visible) + { + LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); + mEditWearable->setWearable(wearable, disable_camera_switch); + mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency + } + else + { + // Save changes if closing. + mEditWearable->saveChanges(); + if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. + { + LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); + } + } +} + +void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) +{ + // Set current outfit status (wearing/unsaved). + bool dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); + std::string cof_status_str = getString(dirty ? "Unsaved Changes" : "Now Wearing"); + mOutfitStatus->setText(cof_status_str); + + if (name == "") + { + std::string outfit_name; + if (LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name)) + { + mCurrentLookName->setText(outfit_name); + return; + } + + std::string string_name = gAgentWearables.isCOFChangeInProgress() ? "Changing outfits" : "No Outfit"; + mCurrentLookName->setText(getString(string_name)); + mOpenOutfitBtn->setEnabled(FALSE); + } + else + { + mCurrentLookName->setText(name); + // Can't just call update verbs since the folder link may not have been created yet. + mOpenOutfitBtn->setEnabled(TRUE); + } +} + +//static +void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch) +{ + LLFloaterSidePanelContainer::showPanel("appearance", LLSD()); + + LLSidepanelAppearance *panel = dynamic_cast(data); + if (panel) + { + panel->showWearableEditPanel(wearable, disable_camera_switch); + } +} + +// Fetch currently worn items and only enable the New Look button after everything's been +// fetched. Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks. +void LLSidepanelAppearance::fetchInventory() +{ + + mNewOutfitBtn->setEnabled(false); + uuid_vec_t ids; + LLUUID item_id; + for(S32 type = (S32)LLWearableType::WT_SHAPE; type < (S32)LLWearableType::WT_COUNT; ++type) + { + for (U32 index = 0; index < gAgentWearables.getWearableCount((LLWearableType::EType)type); ++index) + { + item_id = gAgentWearables.getWearableItemID((LLWearableType::EType)type, index); + if(item_id.notNull()) + { + ids.push_back(item_id); + } + } + } + + if (isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment) continue; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + if (!attached_object) continue; + const LLUUID& item_id = attached_object->getAttachmentItemID(); + if (item_id.isNull()) continue; + ids.push_back(item_id); + } + } + } + + LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(ids, this); + fetch_worn->startFetch(); + // If no items to be fetched, done will never be triggered. + // TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition. + if (fetch_worn->isFinished()) + { + fetch_worn->done(); + } + else + { + gInventory.addObserver(fetch_worn); + } +} + +void LLSidepanelAppearance::inventoryFetched() +{ + mNewOutfitBtn->setEnabled(true); +} + +void LLSidepanelAppearance::setWearablesLoading(bool val) +{ + getChildView("wearables_loading_indicator")->setVisible( val); + getChildView("edit_outfit_btn")->setVisible( !val); + + if (!val) + { + // refresh outfit name when COF is already changed. + refreshCurrentOutfitName(); + } +} + +void LLSidepanelAppearance::showDefaultSubpart() +{ + if (mEditWearable->getVisible()) + { + mEditWearable->showDefaultSubpart(); + } +} + +void LLSidepanelAppearance::updateScrollingPanelList() +{ + if (mEditWearable->getVisible()) + { + mEditWearable->updateScrollingPanelList(); + } +} -- cgit v1.2.3 From 9d70bc259a02a0f6dcc6cff1c95a34353e0f1e59 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 9 Jan 2013 12:45:34 -0800 Subject: CHUI-652 : Fixed : Skip the bogus fetching test when adding objects to object content. --- indra/newview/llviewerobject.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 2fe6cd578b..52f73d6c43 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2869,23 +2869,6 @@ void LLViewerObject::updateInventory( U8 key, bool is_new) { - LLMemType mt(LLMemType::MTYPE_OBJECT); - - std::list::iterator begin = mPendingInventoryItemsIDs.begin(); - std::list::iterator end = mPendingInventoryItemsIDs.end(); - - bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; - bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; - - if (is_fetched || is_fetching) - { - return; - } - else - { - mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); - } - // This slices the object into what we're concerned about on the // viewer. The simulator will take the permissions and transfer // ownership. -- cgit v1.2.3 From 6a30c4c3c54f3d70d1a10fb76e7c81cd5e36a524 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 9 Jan 2013 13:30:14 -0800 Subject: CHUI-669: Upon DND mode exit, no longer flash IM messages that were stored during DND mode. --- indra/newview/llimview.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 0326235d37..a3c338831c 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -129,11 +129,7 @@ void process_dnd_im(const LLSD& notification) false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - //For now always flash conversation line item - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); - im_box->flashConversationItemWidget(sessionID, true); - - //And flash toolbar button + //Flash toolbar button for now, eventually the user's preference will be taken into account gToolBarView->flashCommand(LLCommandId("chat"), true); } -- cgit v1.2.3 From 41d5f820ea1859493b7f14d9d81b145a6a3b38b6 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 9 Jan 2013 14:30:10 -0800 Subject: CHUI-670: Prevent flashing of 'Chat' FUI button while in DND mode and receive IM. --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a3c338831c..067f0d1993 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -228,7 +228,8 @@ void on_new_message(const LLSD& msg) //The conversation floater isn't focused/open if(conversation_floater_not_focused) { - if(!LLMuteList::getInstance()->isMuted(participant_id)) + if(!LLMuteList::getInstance()->isMuted(participant_id) + && !gAgent.isDoNotDisturb()) { gToolBarView->flashCommand(LLCommandId("chat"), true); } -- cgit v1.2.3 From 60eaa8875df45f023c3bf0fb82863b05cb5a090f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 9 Jan 2013 19:10:41 -0800 Subject: CHUI-652 : Fixed : Maintain multi selection consistent when click and drag an already selected item (drag multi select was broken) --- indra/llui/llfolderviewitem.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index b7165f68b7..42e5a6debf 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -506,13 +506,10 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } make_ui_sound("UISndClick"); } - //Just re-select the item since it is clicked without ctrl or shift - else if(!(mask & (MASK_CONTROL | MASK_SHIFT))) - { - getRoot()->setSelection(this, FALSE); - } else { + // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. + // This is necessary so we maintain selection consistent when starting a drag. mSelectPending = TRUE; } -- cgit v1.2.3 From be3cfd872be89f30012d66a4b64071e4fe2568cf Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 9 Jan 2013 20:20:32 -0800 Subject: CHUI-649 : WIP : Cleanup code to make it readable --- indra/llui/llfolderviewitem.cpp | 8 ++++---- indra/newview/llinventorybridge.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 42e5a6debf..6d3b883b09 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -409,7 +409,7 @@ void LLFolderViewItem::selectItem(void) BOOL LLFolderViewItem::isMovable() { return getViewModelItem()->isItemMovable(); - } +} BOOL LLFolderViewItem::isRemovable() { @@ -438,19 +438,19 @@ BOOL LLFolderViewItem::remove() return FALSE; } return getViewModelItem()->removeItem(); - } +} // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { getViewModelItem()->buildContextMenu(menu, flags); - } +} void LLFolderViewItem::openItem( void ) { if (mAllowOpen) { - getViewModelItem()->openItem(); + getViewModelItem()->openItem(); } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cb6290368c..837870ae27 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -511,8 +511,10 @@ BOOL LLInvFVBridge::isClipboardPasteable() const // Each item must be copyable to be pastable LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id); if (!item_br.isItemCopyable()) - return FALSE; - } + { + return FALSE; + } + } return TRUE; } -- cgit v1.2.3 From bad4eda43677d26b88c86f4381c6a0f7436f0daf Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Thu, 10 Jan 2013 13:41:47 +0200 Subject: CHUI-663 (Right click menus on participants inactive in conversation floater for torn off conversation) --- indra/newview/llfloaterimcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82563b8736..a21cbf2bb2 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -906,7 +906,7 @@ const LLConversationItem * LLFloaterIMContainer::getCurSelectedViewModelItem() mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { LLFloaterIMSessionTab *selected_session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); - if (selected_session_floater && !selected_session_floater->getHost()) + if (selected_session_floater && !selected_session_floater->getHost() && selected_session_floater->getCurSelectedViewModelItem()) { conversation_item = selected_session_floater->getCurSelectedViewModelItem(); } -- cgit v1.2.3 From 008e078bf5c7bd3b72eacecb200733715841afe4 Mon Sep 17 00:00:00 2001 From: prep Date: Thu, 10 Jan 2013 11:26:05 -0500 Subject: SH-3142: Added a debug option that circumvents the precache delay when teleporting. --- indra/newview/app_settings/settings.xml | 12 ++++++++++++ indra/newview/llviewerdisplay.cpp | 11 +++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c817579e9e..4b93cef57f 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14170,5 +14170,17 @@ Value 0 + + DisablePrecacheDelayAfterTeleporting + + Comment + Disables the artificial delay in the viewer that precaches some incoming assets + Persist + 0 + Type + Boolean + Value + 0 + diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index bd8377e281..25abf768cb 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -417,14 +417,21 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gTextureList.mForceResetTextureStats = TRUE; - gAgentCamera.resetView(TRUE, TRUE); - + gAgentCamera.resetView(TRUE, TRUE); + if ( gSavedSettings.getBOOL("DisablePrecacheDelayAfterTeleporting") ) + { + gViewerWindow->setShowProgress(FALSE); + gTeleportDisplay = FALSE; + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } + break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); + if( arrival_fraction > 1.f ) { arrival_fraction = 1.f; -- cgit v1.2.3 From 5e7f36541b503bb2bd03e121c7ef13025f69065a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 10 Jan 2013 13:22:48 -0500 Subject: SH-3639 WIP - increased retry interval to allow for intermittent extremely slow responses --- indra/newview/llappearancemgr.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8b4adc8785..bf35382b7a 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -155,6 +155,11 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string } } +// We want this to be much lower (e.g. 15.0 is usually fine), bumping +// up for now until we can diagnose some cases of very slow response +// to requests. +const F32 DEFAULT_RETRY_AFTER_INTERVAL = 300.0; + class LLCallAfterInventoryBatchMgr: public LLEventTimer { public: @@ -162,7 +167,7 @@ public: const std::string& phase_name, nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, - F32 retry_after = 15.0, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, S32 max_retries = 2 ): mDstCatID(dst_cat_id), @@ -365,7 +370,7 @@ public: const std::string& phase_name, nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, - F32 retry_after = 15.0, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, S32 max_retries = 2 ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) @@ -403,7 +408,7 @@ public: const std::string& phase_name, nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, - F32 retry_after = 15.0, + F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, S32 max_retries = 2 ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) -- cgit v1.2.3 From b5b44ddf175e46379aa20b79b0abedab6bc05e2e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 10 Jan 2013 11:10:41 -0800 Subject: CHUI-649 : Fixed : Added the contextual menu to in build content tab --- indra/newview/llinventorypanel.cpp | 4 ++-- indra/newview/llpanelobjectinventory.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 25dc365467..c4918f0a31 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -181,7 +181,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) LLAssetType::AT_CATEGORY, LLInventoryType::IT_CATEGORY, this, - &mInventoryViewModel, + &mInventoryViewModel, NULL, root_id); p.view_model = &mInventoryViewModel; @@ -218,7 +218,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) mFolderRoot = createFolderRoot(root_id); addItemID(root_id, mFolderRoot); -} + } mCommitCallbackRegistrar.popScope(); mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 527aefe821..7555ac7b2c 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1569,6 +1569,8 @@ void LLPanelObjectInventory::reset() p.folder_indentation = -14; // subtract space normally reserved for folder expanders p.view_model = &mInventoryViewModel; p.root = NULL; + p.options_menu = "menu_inventory.xml"; + mFolders = LLUICtrlFactory::create(p); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); -- cgit v1.2.3 From a8bc4787b9aa1d1aba1ce69063e93619e3b39d0d Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 11 Jan 2013 02:06:01 +0000 Subject: test commit --- indra/llaudio/lllistener.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp index df2366c8c2..de5adace5d 100644 --- a/indra/llaudio/lllistener.cpp +++ b/indra/llaudio/lllistener.cpp @@ -42,6 +42,7 @@ LLListener::LLListener() //----------------------------------------------------------------------- LLListener::~LLListener() { + // temporarily adding unnecessary comment to test committing to the repository and builds on TeamCity } //----------------------------------------------------------------------- -- cgit v1.2.3 From 2e3113863022a21d2145cc23992d6afab9c6fbcd Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 10 Jan 2013 20:19:26 -0800 Subject: CHUI-672 : Fixed : LLMultiFloater members need to be initialized in constructor. --- indra/llui/llmultifloater.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 59faabd482..179b251cdb 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -37,10 +37,12 @@ // LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) - : LLFloater(key) - , mTabContainer(NULL) - , mTabPos(LLTabContainer::TOP) - , mAutoResize(TRUE) + : LLFloater(key), + mTabContainer(NULL), + mTabPos(LLTabContainer::TOP), + mAutoResize(TRUE), + mOrigMinWidth(params.min_width), + mOrigMinHeight(params.min_height) { } -- cgit v1.2.3 From 16082462a4d355509338ed28e396c8c81a20712a Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 11 Jan 2013 15:32:05 +0200 Subject: CHUI-650 FIXED Set focus to floater when bringToFront() is called(even if it's already in front). --- indra/llui/llfloater.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8f9be5285d..e0e830f742 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2394,6 +2394,7 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { + child->setFocus(true); return; } -- cgit v1.2.3 From 0f753a530b914370c7c89c198ee335833ac3e6a1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 11 Jan 2013 11:36:11 -0500 Subject: SH-3639 WIP - cleaned up some diagnostics and added fault injection ability. Disabled inventory retries for now. --- indra/newview/app_settings/logcontrol.xml | 2 +- indra/newview/app_settings/settings.xml | 11 ++++++++ indra/newview/llappearancemgr.cpp | 43 ++++++++++++++++++++++++++----- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llvoavatarself.cpp | 2 +- indra/newview/llvovolume.cpp | 3 ++- 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 64122bbb6c..1259039010 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4b93cef57f..32b2920279 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4326,6 +4326,17 @@ Value 0.0 + InventoryDebugSimulateLateOpRate + + Comment + Rate at which we simulate late-completing copy/link requests in some operations + Persist + 1 + Type + F32 + Value + 0.0 + InventoryDisplayInbox Comment diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index bf35382b7a..7edba842b8 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -49,6 +49,7 @@ #include "llvoavatarself.h" #include "llviewerregion.h" #include "llwearablelist.h" +#include "llsdutil.h" std::string self_av_string() { @@ -160,6 +161,11 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string // to requests. const F32 DEFAULT_RETRY_AFTER_INTERVAL = 300.0; +// Given the current back-end problems, retrying is causing too many +// duplicate items. Bump this back to 2 once they are resolved (or can +// leave at 0 if the operations become actually reliable). +const S32 DEFAULT_MAX_RETRIES = 0; + class LLCallAfterInventoryBatchMgr: public LLEventTimer { public: @@ -168,7 +174,7 @@ public: nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, - S32 max_retries = 2 + S32 max_retries = DEFAULT_MAX_RETRIES ): mDstCatID(dst_cat_id), mTrackingPhase(phase_name), @@ -228,6 +234,13 @@ public: void onOp(const LLUUID& src_id, const LLUUID& dst_id, LLTimer timestamp) { + if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateLateOpRate")) + { + llwarns << "Simulating late operation by punting handling to later" << llendl; + doAfterInterval(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,src_id,dst_id,timestamp), + mRetryAfter); + return; + } mPendingRequests--; F32 elapsed = timestamp.getElapsedTimeF32(); LL_DEBUGS("Avatar") << "op done, src_id " << src_id << " dst_id " << dst_id << " after " << elapsed << " seconds" << llendl; @@ -371,7 +384,7 @@ public: nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, - S32 max_retries = 2 + S32 max_retries = DEFAULT_MAX_RETRIES ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) { @@ -409,7 +422,7 @@ public: nullary_func_t on_completion_func, nullary_func_t on_failure_func = no_op, F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, - S32 max_retries = 2 + S32 max_retries = DEFAULT_MAX_RETRIES ): LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) { @@ -1653,6 +1666,7 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin continue; if (item->getIsLinkType()) { +#if 0 if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL) { llinfos << "preserved item" << llendl; @@ -1661,7 +1675,10 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin { gInventory.purgeObject(item->getUUID()); } +#else + gInventory.purgeObject(item->getUUID()); } +#endif } } @@ -2981,13 +2998,27 @@ public: // Successful completion. /* virtual */ void result(const LLSD& content) { - llinfos << "request OK" << llendl; + LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + if (content["success"].asBoolean()) + { + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + } + else + { + onFailure(200); + } } // Error - /*virtual*/ void error(U32 status, const std::string& reason) + /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) { llwarns << "appearance update request failed, status: " << status << " reason: " << reason << llendl; + LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + onFailure(status); + } + + void onFailure(U32 status) + { F32 seconds_to_wait; if (mRetryPolicy->shouldRetry(status,seconds_to_wait)) { @@ -3001,7 +3032,7 @@ public: { llwarns << "giving up after too many retries" << llendl; } - } + } LLPointer mRetryPolicy; }; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5763fe307e..6c773368d3 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1161,7 +1161,7 @@ void LLViewerFetchedTexture::destroyTexture() return ; } - LL_DEBUGS("Avatar") << mID << llendl; + //LL_DEBUGS("Avatar") << mID << llendl; destroyGLTexture() ; mFullyLoaded = FALSE ; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 8f118f5110..9b43db7087 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2256,7 +2256,7 @@ void LLVOAvatarSelf::sendAppearanceChangeMetrics() if (S32_MAX == ++report_sequence) report_sequence = 0; - LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL; +// LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL; std::string caps_url; if (getRegion()) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9078cce932..3831a13f41 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1146,9 +1146,10 @@ void LLVOVolume::sculpt() } else if (current_discard > MAX_DISCARD_LEVEL) { +#if 0 llwarns << "WARNING!!: Current discard of sculpty at " << current_discard << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; - +#endif // corrupted volume... don't update the sculpty return; } -- cgit v1.2.3 From 88639dd862be6558f0777e99c571dcd807efa4ba Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 11 Jan 2013 17:28:43 -0800 Subject: CHUI-650 : Revert : revert the change as it creates infinite recursive calls --- indra/llui/llfloater.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index e0e830f742..8f9be5285d 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2394,7 +2394,6 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { - child->setFocus(true); return; } -- cgit v1.2.3 From 23ffb7db1bb065b5afbdcb94eab57720d604ae8d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Sat, 12 Jan 2013 01:51:43 +0200 Subject: CHUI-618 ADD FIX User sees no indication of offline messages received with conversation log preference turned off: changed in accordance with a new requirements (open conv. floater instead flashing) --- indra/newview/llimview.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 067f0d1993..da811535e5 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -129,8 +129,14 @@ void process_dnd_im(const LLSD& notification) false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - //Flash toolbar button for now, eventually the user's preference will be taken into account - gToolBarView->flashCommand(LLCommandId("chat"), true); + // open conversation floater + LLFloaterIMContainer* container_floater = + LLFloaterReg::getTypedInstance("im_container"); + if (container_floater && !(container_floater->isFrontmost())) + { + container_floater->openFloater(); + container_floater->setFrontmost(TRUE); + } } @@ -2529,25 +2535,6 @@ void LLIMMgr::addMessage( new_session_id = computeSessionID(dialog, other_participant_id); } - // Open conversation log if offline messages are present and user allows a Call Log - if (is_offline_msg) - { - if (gSavedSettings.getBOOL("KeepConversationLogTranscripts")) - { - LLFloaterConversationLog* floater_log = - LLFloaterReg::getTypedInstance("conversation"); - if (floater_log && !(floater_log->isFrontmost())) - { - floater_log->openFloater(); - floater_log->setFrontmost(TRUE); - } - } - else - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } - } - //*NOTE session_name is empty in case of incoming P2P sessions std::string fixed_session_name = from; bool name_is_setted = false; @@ -2614,6 +2601,19 @@ void LLIMMgr::addMessage( { LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); } + + // Open conversation floater if offline messages are present + if (is_offline_msg) + { + LLFloaterIMContainer* container_floater = + LLFloaterReg::getTypedInstance("im_container"); + if (container_floater && !(container_floater->isFrontmost())) + { + container_floater->openFloater(); + container_floater->setFrontmost(TRUE); + } + } + } void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args) -- cgit v1.2.3 From 69497e645bbefe85d83e85bb353e5fb719263877 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Fri, 11 Jan 2013 18:20:29 -0800 Subject: CHUI-668: Not fully complete but as of this commit, have functionality to use the user's most intrusive chat notification upon exiting from DND mode with IM's. Also if in DND mode, clicking on a conversation line item or floater, will flush the DND notifications system of storing that conversation. This way upon existing DND mode already responded conversations won't be notified to the user. --- indra/newview/llcommunicationchannel.cpp | 8 +++- indra/newview/llcommunicationchannel.h | 1 + .../newview/lldonotdisturbnotificationstorage.cpp | 53 ++++++++++++++++++++++ indra/newview/lldonotdisturbnotificationstorage.h | 1 + indra/newview/llfloaterimcontainer.cpp | 10 ++++ indra/newview/llfloaterpreference.cpp | 30 ++++++++++++ indra/newview/llfloaterpreference.h | 1 + indra/newview/llimview.cpp | 42 +++++++++++++++-- 8 files changed, 142 insertions(+), 4 deletions(-) diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index 4b0a70ffd8..a99047c163 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -67,12 +67,18 @@ void LLCommunicationChannel::clearHistory() mHistory.clear(); } +void LLCommunicationChannel::removeItem(history_list_t::const_iterator itemToRemove) +{ + mHistory.erase(itemToRemove); +} + void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) { std::string notificationType = pNotificationPtr->getType(); if ((notificationType == "groupnotify") || (notificationType == "offer") - || (notificationType == "notifytoast")) + || (notificationType == "notifytoast") + && !pNotificationPtr->isCancelled()) { mHistory.insert(std::make_pair(pNotificationPtr->getDate(), pNotificationPtr)); } diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index 0e15e1cd15..c07933118d 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -48,6 +48,7 @@ public: history_list_t::const_iterator endHistory() const; void clearHistory(); + void removeItem(history_list_t::const_iterator itemToRemove); protected: virtual void onFilterFail(LLNotificationPtr pNotificationPtr); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index ac41a3804f..764da25b08 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -41,6 +41,8 @@ #include "llsingleton.h" #include "lluuid.h" +extern void useMostItrusiveIMNotification(); + LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) @@ -103,15 +105,22 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); notification_it != data.endArray(); ++notification_it) { LLSD notification_params = *notification_it; + const std::string notificationName = notification_params["name"].asString(); const LLUUID& notificationID = notification_params["id"]; LLNotificationPtr notification = instance.find(notificationID); + if(notificationName == "IMToast") + { + imToastExists = true; + } + //Notification already exists in notification pipeline (same instance of app running) if (notification) { @@ -138,6 +147,11 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } } + if(imToastExists) + { + useMostItrusiveIMNotification(); + } + // Clear the communication channel history and rewrite the save file to empty it as well LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); @@ -154,6 +168,45 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan return channelPtr; } +void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id) +{ + LLNotifications& instance = LLNotifications::instance(); + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); + LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); + LLNotificationPtr notification; + LLSD substitutions; + LLUUID notificationSessionID; + LLCommunicationChannel::history_list_t::const_iterator it; + std::vector itemsToRemove; + + //Find notification with the matching session id + for (it = commChannel->beginHistory(); + it != commChannel->endHistory(); + ++it) + { + notification = it->second; + substitutions = notification->getSubstitutions(); + notificationSessionID = substitutions["SESSION_ID"].asUUID(); + + if(session_id == notificationSessionID) + { + itemsToRemove.push_back(it); + } + } + + //Remove the notification + while(itemsToRemove.size()) + { + it = itemsToRemove.back(); + notification = it->second; + commChannel->removeItem(it); + //instance.cancel triggers onChannelChanged to be called within LLNotificationChannelBase::updateItem (which save changes to the .xml file) + //but this means that saveNotifications write a file each time as well, BAD! Will find a way to prevent this. + instance.cancel(notification); + itemsToRemove.pop_back(); + } +} + bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) { diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 60bcd89ec3..8edb8569b4 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -45,6 +45,7 @@ public: void saveNotifications(); void loadNotifications(); + void removeIMNotification(const LLUUID& session_id); protected: diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a17b89af0d..376144951d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -39,6 +39,7 @@ #include "llavatariconctrl.h" #include "llavatarnamecache.h" #include "llcallbacklist.h" +#include "lldonotdisturbnotificationstorage.h" #include "llgroupactions.h" #include "llgroupiconctrl.h" #include "llflashtimer.h" @@ -1291,6 +1292,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } } @@ -1312,6 +1317,11 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } + + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } // Set the focus on the selected floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d4a1c44d8..9c836489f3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1624,6 +1624,36 @@ void LLFloaterPreference::selectChatPanel() selectPanel("chat"); } +S32 LLFloaterPreference::getHighestNotificationIndex() //change this name +{ + static const S32 comboBoxNamesLength = 5; + static std::string comboBoxNames[comboBoxNamesLength] = {"NearbyChatOptions", + "FriendIMOptions", + "NonFriendIMOptions", + "ConferenceIMOptions", + "GroupChatOptions"}; + S32 selectedIndex; + S32 priorityindex = 3; + LLComboBox * comboBox; + + for(S32 i = 0; i < comboBoxNamesLength; ++i) + { + comboBox = getChild(comboBoxNames[i]); + + if(comboBox) + { + selectedIndex = comboBox->getCurrentIndex(); + + if(selectedIndex < priorityindex) + { + priorityindex = selectedIndex; + } + } + } + + return priorityindex; +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 37a531e99e..3d5d49294e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -86,6 +86,7 @@ public: void saveAvatarProperties( void ); void selectPrivacyPanel(); void selectChatPanel(); + S32 getHighestNotificationIndex(); protected: void onBtnOK(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 067f0d1993..e513d2e6d1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -52,6 +52,7 @@ #include "llchat.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" +#include "llfloaterpreference.h" #include "llgroupiconctrl.h" #include "llmd5.h" #include "llmutelist.h" @@ -128,11 +129,46 @@ void process_dnd_im(const LLSD& notification) false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - - //Flash toolbar button for now, eventually the user's preference will be taken into account - gToolBarView->flashCommand(LLCommandId("chat"), true); } +void useMostItrusiveIMNotification() +{ + LLFloaterPreference * instance = LLFloaterReg::getTypedInstance("preferences"); + if (instance) + { + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); + + //conv. floater is closed + bool conversation_floater_is_closed = + !( im_box + && im_box->isInVisibleChain() + && !im_box->isMinimized()); + + //conversation floater not focused (visible or not) + bool conversation_floater_not_focused = + conversation_floater_is_closed || !im_box->hasFocus(); + + switch(instance->getHighestNotificationIndex()) + { + //Highest priority to lowest (cases correspond to options in drop down box inside Preferences->Chat) + + //open conversation floater + case 0: + LLFloaterReg::showInstance("im_container"); + break; + //pop up message + case 1: + //flash toolbar button + case 2: + if(conversation_floater_not_focused) + { + gToolBarView->flashCommand(LLCommandId("chat"), true); + } + break; + } + } + +} static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, -- cgit v1.2.3 From e42755dd16195244a6743fc3970f24fec08f03b9 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Fri, 11 Jan 2013 19:43:12 -0800 Subject: CHUI-668: Now when exiting DND mode, the user's most intrusive notification will be used to notify that user (if received IM's during DND mode). Nearby chat messages/settings are ignored. --- indra/newview/llfloaterpreference.cpp | 11 +++---- indra/newview/llimview.cpp | 59 ++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 9c836489f3..4c74d3a8ef 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1626,12 +1626,11 @@ void LLFloaterPreference::selectChatPanel() S32 LLFloaterPreference::getHighestNotificationIndex() //change this name { - static const S32 comboBoxNamesLength = 5; - static std::string comboBoxNames[comboBoxNamesLength] = {"NearbyChatOptions", - "FriendIMOptions", - "NonFriendIMOptions", - "ConferenceIMOptions", - "GroupChatOptions"}; + static const S32 comboBoxNamesLength = 4; + static std::string comboBoxNames[comboBoxNamesLength] = {"FriendIMOptions", + "NonFriendIMOptions", + "ConferenceIMOptions", + "GroupChatOptions"}; S32 selectedIndex; S32 priorityindex = 3; LLComboBox * comboBox; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index e513d2e6d1..b29c1484cc 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -134,36 +134,32 @@ void process_dnd_im(const LLSD& notification) void useMostItrusiveIMNotification() { LLFloaterPreference * instance = LLFloaterReg::getTypedInstance("preferences"); - if (instance) - { - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance("im_container"); - //conv. floater is closed - bool conversation_floater_is_closed = - !( im_box - && im_box->isInVisibleChain() - && !im_box->isMinimized()); + //conv. floater is closed + bool conversation_floater_is_closed = + !( im_box + && im_box->isInVisibleChain() + && !im_box->isMinimized()); - //conversation floater not focused (visible or not) - bool conversation_floater_not_focused = - conversation_floater_is_closed || !im_box->hasFocus(); + //conversation floater not focused (visible or not) + bool conversation_floater_not_focused = + conversation_floater_is_closed || !im_box->hasFocus(); + //Only notify user of stored DND IM messages when conversation floater isn't focused + if (instance && conversation_floater_not_focused) + { switch(instance->getHighestNotificationIndex()) { - //Highest priority to lowest (cases correspond to options in drop down box inside Preferences->Chat) - //open conversation floater case 0: - LLFloaterReg::showInstance("im_container"); + LLFloaterReg::showInstance("im_container"); break; //pop up message case 1: //flash toolbar button case 2: - if(conversation_floater_not_focused) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } + gToolBarView->flashCommand(LLCommandId("chat"), true); break; } } @@ -284,13 +280,22 @@ void on_new_message(const LLSD& msg) { if (conversation_floater_not_focused) { - if(session_floater_not_focused) + if(session_floater_not_focused && !gAgent.isDoNotDisturb()) { //User is not focused on conversation containing the message gToolBarView->flashCommand(LLCommandId("chat"), true); } im_box->flashConversationItemWidget(session_id, true); + + //If a DND message, allow notification to be stored so upon DND exit + //useMostItrusiveIMNotification will be called to notify user a message exists + if(session_id.notNull() + && participant_id.notNull() + && gAgent.isDoNotDisturb()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } } @@ -302,8 +307,20 @@ void on_new_message(const LLSD& msg) //Flash line item im_box->flashConversationItemWidget(session_id, true); - //Surface conversations floater - LLFloaterReg::showInstance("im_container"); + if(!gAgent.isDoNotDisturb()) + { + //Surface conversations floater + LLFloaterReg::showInstance("im_container"); + } + + //If in DND mode, allow notification to be stored so upon DND exit + //useMostItrusiveIMNotification will be called to notify user a message exists + if(session_id.notNull() + && participant_id.notNull() + && gAgent.isDoNotDisturb()) + { + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } } } } -- cgit v1.2.3 From b47a7751990b240198d4e868f5a35bbd1b34e4ee Mon Sep 17 00:00:00 2001 From: Cho Date: Mon, 14 Jan 2013 18:37:29 +0000 Subject: reverted test commit --- indra/llaudio/lllistener.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp index de5adace5d..df2366c8c2 100644 --- a/indra/llaudio/lllistener.cpp +++ b/indra/llaudio/lllistener.cpp @@ -42,7 +42,6 @@ LLListener::LLListener() //----------------------------------------------------------------------- LLListener::~LLListener() { - // temporarily adding unnecessary comment to test committing to the repository and builds on TeamCity } //----------------------------------------------------------------------- -- cgit v1.2.3 From e44677ee79a38741d641fae74ba661b7e6b59794 Mon Sep 17 00:00:00 2001 From: maximbproductengine Date: Mon, 14 Jan 2013 21:48:37 +0200 Subject: CHUI-662 (Multi select across conversations can result in (???) (???) in the conversation list) --- indra/newview/llfloaterimcontainer.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a17b89af0d..f825e253d4 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -893,7 +893,18 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) for (; it != it_end; ++it) { conversationItem = static_cast((*it)->getViewModelItem()); - selected_uuids.push_back(conversationItem->getUUID()); + + //When a one-on-one conversation exists, retrieve the participant id from the conversation floater + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversationItem->getUUID()); + LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); + selected_uuids.push_back(participant_id); + } + else + { + selected_uuids.push_back(conversationItem->getUUID()); + } } } @@ -929,17 +940,7 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) return; } - if (conversation_item->getType() == LLConversationItem::CONV_PARTICIPANT) - { - getSelectedUUIDs(selected_uuids); - } - //When a one-on-one conversation exists, retrieve the participant id from the conversation floater - else if(conversation_item->getType() == LLConversationItem::CONV_SESSION_1_ON_1) - { - LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversation_item->getUUID()); - LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); - selected_uuids.push_back(participant_id); - } + getSelectedUUIDs(selected_uuids); } void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) -- cgit v1.2.3 From 6390188ff35c47c93748c6fe3023d0bad219dea6 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 14 Jan 2013 16:02:28 -0500 Subject: removed yet another logcontrol.xml commit --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 1259039010..64122bbb6c 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - Avatar -- cgit v1.2.3 From 85e993224cfc67830f9586c1767a860a1d0c0deb Mon Sep 17 00:00:00 2001 From: prep Date: Mon, 14 Jan 2013 17:21:13 -0500 Subject: SH-3632:Undo change is now disabled after you save and return to the edit out fit panel (this behavior is now make sunshine-internal consistent with 3.4.1) --- indra/newview/llsidepanelappearance.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index f0844dd9a4..60ea675da4 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -410,6 +410,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearab { // Save changes if closing. mEditWearable->saveChanges(); + LLAppearanceMgr::getInstance()->setOutfitDirty( FALSE ); if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. { LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); -- cgit v1.2.3 From cefcdd445b6bad0e2382d848cd73b20a1a51cc01 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 14 Jan 2013 15:26:59 -0800 Subject: CHUI-458 : WIP : Allow change of the general conversations panel when the selected conversation needs it (e.g. P2P is typing) --- indra/newview/llfloaterimcontainer.cpp | 6 ++++++ indra/newview/llfloaterimcontainer.h | 1 + indra/newview/llfloaterimsession.cpp | 2 +- indra/newview/llfloaterimsession.h | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f825e253d4..cf81a2b046 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -238,6 +238,9 @@ BOOL LLFloaterIMContainer::postBuild() // Init the sort order now that the root had been created setSortOrder(LLConversationSort(gSavedSettings.getU32("ConversationSortOrder"))); + // Keep the xml set title around for when we have to overwrite it + mGeneralTitle = getTitle(); + mInitialized = true; // Add callbacks: @@ -515,6 +518,9 @@ void LLFloaterIMContainer::draw() current_participant_model++; } + // is P2P? Test if we can change the title + LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID()); + setTitle(conversation_floaterp && conversation_floaterp->hasSpecialTitle() ? conversation_floaterp->getSpecialTitle() : mGeneralTitle); } LLFloater::draw(); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 85d950c58b..06af6c7b51 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -169,6 +169,7 @@ private: bool mInitialized; LLUUID mSelectedSession; + std::string mGeneralTitle; // Conversation list implementation public: diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index d36b138c21..931ee0dc66 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -705,7 +705,7 @@ BOOL LLFloaterIMSession::getVisible() // getVisible() returns TRUE when Tabbed IM window is minimized. visible = is_active && !im_container->isMinimized() && im_container->getVisible(); - } + } } else { diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 6a2f4b29eb..7239481e56 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -132,6 +132,8 @@ public: static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; + bool hasSpecialTitle() { return mOtherTyping; } + std::string getSpecialTitle() { return getTitle(); } private: /*virtual*/ void refresh(); -- cgit v1.2.3 From 0e90e94a4d5cbac2d186f0056821a51078e8d1bd Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Mon, 14 Jan 2013 17:23:06 -0800 Subject: CHUI-668: The user's most intrusive notification is not used anymore when coming out of DND mode with IMs. Adjusted code to just open the converseation floater (which was changed also in a prior fix by PE). --- indra/newview/lldonotdisturbnotificationstorage.cpp | 13 +++++++++++++ indra/newview/llimview.cpp | 19 +++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 5cc0ab2081..12ff308a77 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -33,6 +33,7 @@ #include "lldir.h" #include "llerror.h" #include "llfasttimer_class.h" +#include "llfloaterreg.h" #include "llnotifications.h" #include "llnotificationhandler.h" #include "llnotificationstorage.h" @@ -103,6 +104,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; for (LLSD::array_const_iterator notification_it = data.beginArray(); notification_it != data.endArray(); @@ -110,8 +112,14 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() { LLSD notification_params = *notification_it; const LLUUID& notificationID = notification_params["id"]; + std::string notificationName = notification_params["name"]; LLNotificationPtr notification = instance.find(notificationID); + if(notificationName == "IMToast") + { + imToastExists = true; + } + //Notification already exists in notification pipeline (same instance of app running) if (notification) { @@ -138,6 +146,11 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() } } + if(imToastExists) + { + LLFloaterReg::showInstance("im_container"); + } + // Clear the communication channel history and rewrite the save file to empty it as well LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 32b4afcfef..ff171fc0f8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -128,18 +128,11 @@ void process_dnd_im(const LLSD& notification) false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) } - - // open conversation floater - LLFloaterIMContainer* container_floater = - LLFloaterReg::getTypedInstance("im_container"); - if (container_floater && !(container_floater->isFrontmost())) - { - container_floater->openFloater(); - container_floater->setFrontmost(TRUE); - } } + + static void on_avatar_name_cache_toast(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD msg) @@ -2626,13 +2619,7 @@ void LLIMMgr::addMessage( // Open conversation floater if offline messages are present if (is_offline_msg) { - LLFloaterIMContainer* container_floater = - LLFloaterReg::getTypedInstance("im_container"); - if (container_floater && !(container_floater->isFrontmost())) - { - container_floater->openFloater(); - container_floater->setFrontmost(TRUE); - } + LLFloaterReg::showInstance("im_container"); } } -- cgit v1.2.3 From b7f4916b3e4af149d6212a701c556915e23e7c0a Mon Sep 17 00:00:00 2001 From: Cho Date: Tue, 15 Jan 2013 02:48:52 +0000 Subject: CHUI-679 FIX Crash when script floater appears in CHUI viewer LLPostponedNotification now inherits from LLMortician so it can postpone its deletion. This prevents a crash when looking up an avatar name in the case where the name already exists in the cache. --- indra/llui/llnotifications.cpp | 3 ++- indra/llui/llnotifications.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index a5492b46f7..ea52bee184 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1852,6 +1852,7 @@ void LLPostponedNotification::fetchAvatarName(const LLUUID& id) { mAvatarNameCacheConnection.disconnect(); } + mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2)); } } @@ -1860,7 +1861,7 @@ void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); - + std::string name = av_name.getCompleteName(); // from PE merge - we should figure out if this is the right thing to do diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 236c2a42d1..e02c58de44 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,6 +92,7 @@ #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" +#include "llmortician.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" @@ -981,7 +982,7 @@ private: * 1 create class derived from LLPostponedNotification; * 2 call LLPostponedNotification::add method; */ -class LLPostponedNotification +class LLPostponedNotification : public LLMortician { public: /** @@ -1014,7 +1015,7 @@ private: void cleanup() { - delete this; + die(); } protected: -- cgit v1.2.3 From a49d3b14254fa5cfac3900e86b2287a016eaf9cc Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Tue, 15 Jan 2013 14:07:55 +0200 Subject: CHUI-567 FIXED "Translate chat", "Translation settings..." menu items are added. --- indra/newview/app_settings/settings_per_account.xml | 13 ++++++++++++- indra/newview/llfloaterimsessiontab.cpp | 20 ++++++++++++++++++++ indra/newview/llfloaterimsessiontab.h | 4 ++++ indra/newview/llfloatertranslationsettings.cpp | 18 +++++++++++++----- indra/newview/llfloatertranslationsettings.h | 1 + .../default/xui/en/menu_im_session_showmodes.xml | 20 ++++++++++++++++++-- 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 4ff494fbfb..6864328339 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -270,7 +270,18 @@ Value 0 - ShowFavoritesOnLogin + TranslatingEnabled + + Comment + Translation prefs are set + Persist + 1 + Type + Boolean + Value + 0 + + ShowFavoritesOnLogin Comment Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index d4eb03f95d..06a79836db 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -72,6 +72,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); + mEnableCallbackRegistrar.add("Translating.Enabled", + boost::bind(&LLFloaterIMSessionTab::isTranslatingEnabled, this, _2)); + mEnableCallbackRegistrar.add("Translating.On", + boost::bind(&LLFloaterIMSessionTab::isTranslationOn, this, _2)); + mCommitCallbackRegistrar.add("Translating.Toggle", + boost::bind(&LLFloaterIMSessionTab::toggleTranslation, this, _2)); // Right click menu handling mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); @@ -552,6 +558,10 @@ void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata) LLFloaterIMSessionTab::processChatHistoryStyleUpdate(); } +void LLFloaterIMSessionTab::toggleTranslation(const LLSD& userdata) +{ + gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); +} bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) { @@ -576,6 +586,16 @@ bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } +bool LLFloaterIMSessionTab::isTranslatingEnabled(const LLSD& userdata) +{ + return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); +} + +bool LLFloaterIMSessionTab::isTranslationOn(const LLSD& userdata) +{ + return gSavedSettings.getBOOL("TranslateChat"); +} + void LLFloaterIMSessionTab::hideOrShowTitle() { const LLFloater::Params& default_params = LLFloater::getDefaultParams(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 0fa99a46be..05da0f98bc 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -109,8 +109,12 @@ protected: // bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); + bool isTranslatingEnabled(const LLSD& userdata); + bool isTranslationOn(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); + void toggleTranslation(const LLSD& userdata); + // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 6a9236ce0c..33f2c35239 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -225,11 +225,10 @@ void LLFloaterTranslationSettings::updateControlsEnabledState() mGoogleVerifyBtn->setEnabled(on && google_selected && !mGoogleKeyVerified && !getEnteredGoogleKey().empty()); - mOKBtn->setEnabled( - !on || ( - (bing_selected && mBingKeyVerified) || - (google_selected && mGoogleKeyVerified) - )); + bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); + gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); + + mOKBtn->setEnabled(!on || service_verified); } void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert) @@ -285,7 +284,16 @@ void LLFloaterTranslationSettings::onBtnGoogleVerify() verifyKey(LLTranslate::SERVICE_GOOGLE, key); } } +void LLFloaterTranslationSettings::onClose(bool app_quitting) +{ + std::string service = gSavedSettings.getString("TranslationService"); + bool bing_selected = service == "bing"; + bool google_selected = service == "google"; + + bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); + gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); +} void LLFloaterTranslationSettings::onBtnOK() { gSavedSettings.setBOOL("TranslateChat", mMachineTranslationCB->getValue().asBoolean()); diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h index 9b47ad72ed..b9bfd6265a 100644 --- a/indra/newview/llfloatertranslationsettings.h +++ b/indra/newview/llfloatertranslationsettings.h @@ -44,6 +44,7 @@ public: void setBingVerified(bool ok, bool alert); void setGoogleVerified(bool ok, bool alert); + void onClose(bool app_quitting); private: std::string getSelectedService() const; diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml index 483f24afd0..f2a8b39b04 100644 --- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -44,7 +44,23 @@ parameter="IMShowNamesForP2PConv" /> - + parameter="IMShowNamesForP2PConv" /> + + + + + + + + + + -- cgit v1.2.3 From 235a3477364c6747d7724a090ca61adbcbeac272 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 15 Jan 2013 14:13:36 -0800 Subject: CHUI-458 : Fixed : Tidy up the title overwrite by the selected conversation --- indra/newview/llfloaterimcontainer.cpp | 6 +++--- indra/newview/llfloaterimsession.cpp | 2 ++ indra/newview/llfloaterimsession.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cf81a2b046..8264a90325 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -505,10 +505,10 @@ void LLFloaterIMContainer::draw() collapseMessagesPane(true); } - //Update moderator options visibility const LLConversationItem *current_session = getCurSelectedViewModelItem(); if (current_session) { + // Update moderator options visibility LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd(); while (current_participant_model != end_participant_model) @@ -518,9 +518,9 @@ void LLFloaterIMContainer::draw() current_participant_model++; } - // is P2P? Test if we can change the title + // Update floater's title as required by the currently selected session or use the default title LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID()); - setTitle(conversation_floaterp && conversation_floaterp->hasSpecialTitle() ? conversation_floaterp->getSpecialTitle() : mGeneralTitle); + setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle); } LLFloater::draw(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 931ee0dc66..a09dc1914f 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -70,6 +70,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id) mShouldSendTypingState(false), mMeTyping(false), mOtherTyping(false), + mSessionNameUpdatedForTyping(false), mTypingTimer(), mTypingTimeoutTimer(), mPositioned(false), @@ -556,6 +557,7 @@ void LLFloaterIMSession::updateSessionName(const std::string& name) LLFloaterIMSessionTab::updateSessionName(name); mTypingStart.setArg("[NAME]", name); setTitle (mOtherTyping ? mTypingStart.getString() : name); + mSessionNameUpdatedForTyping = mOtherTyping; } } diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 7239481e56..2049cedfd7 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -132,8 +132,7 @@ public: static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; - bool hasSpecialTitle() { return mOtherTyping; } - std::string getSpecialTitle() { return getTitle(); } + bool needsTitleOverwrite() { return mSessionNameUpdatedForTyping && mOtherTyping; } private: /*virtual*/ void refresh(); @@ -184,6 +183,7 @@ private: bool mShouldSendTypingState; LLFrameTimer mTypingTimer; LLFrameTimer mTypingTimeoutTimer; + bool mSessionNameUpdatedForTyping; bool mSessionInitialized; LLSD mQueuedMsgsForInit; -- cgit v1.2.3 From f34ef33e5ceb7f94ee8ca8586880d7be0e5ced82 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 15 Jan 2013 17:43:16 -0500 Subject: Fixed spelling error. --- indra/newview/llviewerinventory.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 13e95c57cb..83f0486f01 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -211,7 +211,7 @@ public: // Returns true if a fetch was issued. bool fetch(); - // used to help make cacheing more robust - for example, if + // used to help make caching more robust - for example, if // someone is getting 4 packets but logs out after 3. the viewer // may never know the cache is wrong. enum { DESCENDENT_COUNT_UNKNOWN = -1 }; @@ -219,7 +219,7 @@ public: void setDescendentCount(S32 descendents) { mDescendentCount = descendents; } // file handling on the viewer. These are not meant for anything - // other than cacheing. + // other than caching. bool exportFileLocal(LLFILE* fp) const; bool importFileLocal(LLFILE* fp); void determineFolderType(); -- cgit v1.2.3 From f48011e4d04f744a93a18267bf7b78ec0b717b7c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 15 Jan 2013 20:30:20 -0500 Subject: SH-3339 WIP, SH-3645 WIP - added getActualDescription to obviate an obnoxious and widely-used workaround, re-create COF link after wearable edit to force COF version bump --- .hgignore | 0 indra/llinventory/llinventory.cpp | 5 ++++ indra/llinventory/llinventory.h | 1 + indra/newview/llappearancemgr.cpp | 49 +++++++++++++++++++++++++++-------- indra/newview/llappearancemgr.h | 3 +++ indra/newview/llpaneleditwearable.cpp | 22 +++++++++++++++- 6 files changed, 68 insertions(+), 12 deletions(-) mode change 100644 => 100755 .hgignore mode change 100644 => 100755 indra/llinventory/llinventory.cpp mode change 100644 => 100755 indra/llinventory/llinventory.h mode change 100644 => 100755 indra/newview/llpaneleditwearable.cpp diff --git a/.hgignore b/.hgignore old mode 100644 new mode 100755 diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp old mode 100644 new mode 100755 index 2dbc331036..3150a99a21 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -379,6 +379,11 @@ const std::string& LLInventoryItem::getDescription() const return mDescription; } +const std::string& LLInventoryItem::getActualDescription() const +{ + return mDescription; +} + time_t LLInventoryItem::getCreationDate() const { return mCreationDate; diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h old mode 100644 new mode 100755 index a5cfe59bda..44e7c0c34d --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -160,6 +160,7 @@ public: virtual const LLUUID& getCreatorUUID() const; virtual const LLUUID& getAssetUUID() const; virtual const std::string& getDescription() const; + virtual const std::string& getActualDescription() const; // Does not follow links virtual const LLSaleInfo& getSaleInfo() const; virtual LLInventoryType::EType getInventoryType() const; virtual U32 getFlags() const; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 7edba842b8..d1ed82cc98 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -451,7 +451,7 @@ public: item->getLinkedUUID(), mDstCatID, item->getName(), - item->LLInventoryItem::getDescription(), + item->getActualDescription(), LLAssetType::AT_LINK, new LLBoostFuncInventoryCallback( boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); @@ -1467,13 +1467,13 @@ void LLAppearanceMgr::shallowCopyCategoryContents(const LLUUID& src_id, const LL { case LLAssetType::AT_LINK: { - //LLInventoryItem::getDescription() is used for a new description + //getActualDescription() is used for a new description //to propagate ordering information saved in descriptions of links link_inventory_item(gAgent.getID(), item->getLinkedUUID(), dst_id, item->getName(), - item->LLInventoryItem::getDescription(), + item->getActualDescription(), LLAssetType::AT_LINK, cb); break; } @@ -1718,7 +1718,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, item->getLinkedUUID(), cat_uuid, item->getName(), - item->LLInventoryItem::getDescription(), + item->getActualDescription(), LLAssetType::AT_LINK, cb); @@ -1910,7 +1910,7 @@ bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* it return true; } - return item1->LLInventoryItem::getDescription() < item2->LLInventoryItem::getDescription(); + return item1->getActualDescription() < item2->getActualDescription(); } void item_array_diff(LLInventoryModel::item_array_t& full_list, @@ -2486,6 +2486,33 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update return; } +LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) +{ + + LLInventoryModel::item_array_t result; + const LLViewerInventoryItem *vitem = + dynamic_cast(gInventory.getItem(item_id)); + + if (vitem) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceMgr::getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; igetLinkedUUID() == vitem->getLinkedUUID()) + { + result.put(item_array.get(i)); + } + } + } + return result; +} + void LLAppearanceMgr::removeAllClothesFromAvatar() { // Fetch worn clothes (i.e. the ones in COF). @@ -2644,7 +2671,7 @@ void LLAppearanceMgr::updateIsDirty() if (item1->getLinkedUUID() != item2->getLinkedUUID() || item1->getName() != item2->getName() || - item1->LLInventoryItem::getDescription() != item2->LLInventoryItem::getDescription()) + item1->getActualDescription() != item2->getActualDescription()) { mOutfitIsDirty = true; return; @@ -2855,8 +2882,8 @@ struct WearablesOrderComparator return true; } - const std::string& desc1 = item1->LLInventoryItem::getDescription(); - const std::string& desc2 = item2->LLInventoryItem::getDescription(); + const std::string& desc1 = item1->getActualDescription(); + const std::string& desc2 = item2->getActualDescription(); bool item1_valid = (desc1.size() == mControlSize) && (ORDER_NUMBER_SEPARATOR == desc1[0]); bool item2_valid = (desc2.size() == mControlSize) && (ORDER_NUMBER_SEPARATOR == desc2[0]); @@ -2914,7 +2941,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (!item) continue; std::string new_order_str = build_order_string((LLWearableType::EType)type, i); - if (new_order_str == item->LLInventoryItem::getDescription()) continue; + if (new_order_str == item->getActualDescription()) continue; item->setDescription(new_order_str); item->setComplete(TRUE); @@ -3179,8 +3206,8 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b closer_to_body ? --it : ++it; LLViewerInventoryItem* swap_item = *it; if (!swap_item) return false; - std::string tmp = swap_item->LLInventoryItem::getDescription(); - swap_item->setDescription(item->LLInventoryItem::getDescription()); + std::string tmp = swap_item->getActualDescription(); + swap_item->setDescription(item->getActualDescription()); item->setDescription(tmp); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 31dbce892a..01a2d41458 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -132,6 +132,9 @@ public: void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL); void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL); + // Find COF entries referencing the given item. + LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id); + // Remove COF entries void removeCOFItemLinks(const LLUUID& item_id); void removeCOFLinksOfType(LLWearableType::EType type); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp old mode 100644 new mode 100755 index 606e78bd58..cca3b90329 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1065,7 +1065,27 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) } else { - gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); + LLInventoryModel::item_array_t links = + LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); + if (links.size()>0) + { + // Make another copy of this link, with the same description. + LLInventoryItem *item = links.get(0).get(); + if (item) + { + const std::string description = item->getIsLinkType() ? item->getActualDescription() : ""; + link_inventory_item( gAgent.getID(), + item->getLinkedUUID(), + LLAppearanceMgr::instance().getCOF(), + item->getName(), + description, + LLAssetType::AT_LINK, + NULL); + gInventory.purgeObject(item->getUUID()); + } + } + gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); + } } -- cgit v1.2.3 From de9e2c38126682e5c6215151e3389380a93b8bc0 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Tue, 15 Jan 2013 20:36:48 -0800 Subject: CHUI-668: Code review changes --- indra/newview/llagent.cpp | 2 +- indra/newview/llcommunicationchannel.cpp | 32 +++++- indra/newview/llcommunicationchannel.h | 8 +- .../newview/lldonotdisturbnotificationstorage.cpp | 108 +++++++++++++++++---- indra/newview/lldonotdisturbnotificationstorage.h | 21 +++- 5 files changed, 146 insertions(+), 25 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d28af3eff9..094d502078 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1397,7 +1397,7 @@ void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb); if (isDoNotDisturbSwitchedOff) { - LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); + LLDoNotDisturbNotificationStorage::getInstance()->updateNotifications(); } } diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index a99047c163..0821510645 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -52,6 +52,11 @@ bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr) return !gAgent.isDoNotDisturb(); } +S32 LLCommunicationChannel::getHistorySize() const +{ + return mHistory.size(); +} + LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const { return mHistory.begin(); @@ -62,14 +67,37 @@ LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::e return mHistory.end(); } +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::beginHistory() +{ + return mHistory.begin(); +} + +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::endHistory() +{ + return mHistory.end(); +} + void LLCommunicationChannel::clearHistory() { mHistory.clear(); } -void LLCommunicationChannel::removeItem(history_list_t::const_iterator itemToRemove) +void LLCommunicationChannel::removeItemFromHistory(LLNotificationPtr p) +{ + //Find the notification and removes it from mHistory + for(history_list_t::iterator it = beginHistory(); it != endHistory(); ++it) + { + if(it->second == p) + { + mHistory.erase(it); + break; + } + } +} + +void LLCommunicationChannel::onDelete(LLNotificationPtr p) { - mHistory.erase(itemToRemove); + removeItemFromHistory(p); } void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr) diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index c07933118d..0d8f7f4387 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -44,13 +44,17 @@ public: static bool filterByDoNotDisturbStatus(LLNotificationPtr); typedef std::multimap history_list_t; + S32 getHistorySize() const; history_list_t::const_iterator beginHistory() const; history_list_t::const_iterator endHistory() const; - + history_list_t::iterator beginHistory(); + history_list_t::iterator endHistory(); + void clearHistory(); - void removeItem(history_list_t::const_iterator itemToRemove); + void removeItemFromHistory(LLNotificationPtr p); protected: + virtual void onDelete(LLNotificationPtr p); virtual void onFilterFail(LLNotificationPtr pNotificationPtr); private: diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 12ff308a77..42b455c1ce 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -42,9 +42,34 @@ #include "llsingleton.h" #include "lluuid.h" +static const F32 DND_TIMER = 3.0; + +LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) +{ + mEventTimer.start(); +} + +LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() +{ + mEventTimer.stop(); +} + +BOOL LLDoNotDisturbNotificationStorageTimer::tick() +{ + LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage = LLDoNotDisturbNotificationStorage::getInstance(); + + if(doNotDisturbNotificationStorage + && doNotDisturbNotificationStorage->getDirty()) + { + doNotDisturbNotificationStorage->saveNotifications(); + } + return FALSE; +} + LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) + , mDirty(false) { } @@ -57,6 +82,16 @@ void LLDoNotDisturbNotificationStorage::initialize() getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); } +bool LLDoNotDisturbNotificationStorage::getDirty() +{ + return mDirty; +} + +void LLDoNotDisturbNotificationStorage::resetDirty() +{ + mDirty = false; +} + static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications"); void LLDoNotDisturbNotificationStorage::saveNotifications() @@ -83,6 +118,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications() } writeNotifications(output); + + resetDirty(); } static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications"); @@ -120,15 +157,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() imToastExists = true; } - //Notification already exists in notification pipeline (same instance of app running) - if (notification) - { - notification->setDND(true); - instance.update(notification); - } - //Notification doesn't exist (different instance since restarted app while in DND mode) - else - { + //New notification needs to be added notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); if (responder == NULL) @@ -144,21 +173,58 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() instance.add(notification); } - } if(imToastExists) { LLFloaterReg::showInstance("im_container"); } - // Clear the communication channel history and rewrite the save file to empty it as well + //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty) + saveNotifications(); +} + +void LLDoNotDisturbNotificationStorage::updateNotifications() +{ + LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); llassert(commChannel != NULL); + + LLNotifications& instance = LLNotifications::instance(); + bool imToastExists = false; + + for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory(); + it != commChannel->endHistory(); + ++it) + { + LLNotificationPtr notification = it->second; + std::string notificationName = notification->getName(); + + if(notificationName == "IMToast") + { + imToastExists = true; + } + + //Notification already exists in notification pipeline (same instance of app running) + if (notification) + { + notification->setDND(true); + instance.update(notification); + } + } + + if(imToastExists) + { + LLFloaterReg::showInstance("im_container"); + } + + //When exit DND mode, write empty notifications file + if(commChannel->getHistorySize()) + { commChannel->clearHistory(); - saveNotifications(); } +} LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const { @@ -175,8 +241,8 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi LLNotificationPtr notification; LLSD substitutions; LLUUID notificationSessionID; - LLCommunicationChannel::history_list_t::const_iterator it; - std::vector itemsToRemove; + LLCommunicationChannel::history_list_t::iterator it; + std::vector itemsToRemove; //Find notification with the matching session id for (it = commChannel->beginHistory(); @@ -193,17 +259,21 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi } } - //Remove the notification + + //Remove the notifications + if(itemsToRemove.size()) + { while(itemsToRemove.size()) { it = itemsToRemove.back(); notification = it->second; - commChannel->removeItem(it); - //instance.cancel triggers onChannelChanged to be called within LLNotificationChannelBase::updateItem (which save changes to the .xml file) - //but this means that saveNotifications write a file each time as well, BAD! Will find a way to prevent this. + commChannel->removeItemFromHistory(notification); instance.cancel(notification); itemsToRemove.pop_back(); } + //Trigger saving of notifications to xml once all have been removed + saveNotifications(); + } } @@ -211,7 +281,7 @@ bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload) { if (pPayload["sigtype"].asString() != "load") { - saveNotifications(); + mDirty = true; } return false; diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 8edb8569b4..fd03b71357 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -28,12 +28,26 @@ #define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H #include "llerror.h" +#include "lleventtimer.h" #include "llnotifications.h" #include "llnotificationstorage.h" #include "llsingleton.h" class LLSD; +class LLDoNotDisturbNotificationStorageTimer : public LLEventTimer +{ +public: + LLDoNotDisturbNotificationStorageTimer(); + ~LLDoNotDisturbNotificationStorageTimer(); + +public: + void startTimer(); + void stopTimer(); + bool isRunning(); + BOOL tick(); +}; + class LLDoNotDisturbNotificationStorage : public LLSingleton, public LLNotificationStorage { LOG_CLASS(LLDoNotDisturbNotificationStorage); @@ -42,14 +56,19 @@ public: ~LLDoNotDisturbNotificationStorage(); void initialize(); - + bool getDirty(); + void resetDirty(); void saveNotifications(); void loadNotifications(); + void updateNotifications(); void removeIMNotification(const LLUUID& session_id); protected: private: + bool mDirty; + LLDoNotDisturbNotificationStorageTimer mTimer; + LLNotificationChannelPtr getCommunicationChannel() const; bool onChannelChanged(const LLSD& pPayload); }; -- cgit v1.2.3 From b0774ec9147ddc2c2e5e93e5a74c929c802c32af Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 16 Jan 2013 17:37:13 +0200 Subject: CHUI-650 (Floaters not returning to active transparency after becoming inactive) - Checking is added(comparing to previous fix) to avoid crash. --- indra/llui/llfloater.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8f9be5285d..d2aae11191 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -655,7 +655,7 @@ void LLFloater::openFloater(const LLSD& key) { llinfos << "Opening floater " << getName() << llendl; mKey = key; // in case we need to open ourselves again - + if (getSoundFlags() != SILENT // don't play open sound for hosted (tabbed) windows && !getHost() @@ -2394,6 +2394,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { if (mFrontChild == child) { + + if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) + { + child->setFocus(TRUE); + } return; } -- cgit v1.2.3 From 8c3d3d4b07f12e3462af7745016536389ab7cf73 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 16 Jan 2013 16:40:59 +0200 Subject: CHUI-618 ADD FIX User sees no indication of offline messages received with conversation log preference turned off: forced flashing of conversation's item when offline message is present --- indra/newview/llimview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ff171fc0f8..d0a8dfc0c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2620,8 +2620,9 @@ void LLIMMgr::addMessage( if (is_offline_msg) { LLFloaterReg::showInstance("im_container"); + LLFloaterReg::getTypedInstance("im_container")-> + flashConversationItemWidget(session_id, true); } - } void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args) -- cgit v1.2.3 From 6a8947679cdb3a3d6ce9d4d175a2bdfed4b7eee3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 16 Jan 2013 11:34:42 -0500 Subject: SH-3645 WIP - preserve item order after wearable save as --- indra/newview/llagentwearables.cpp | 12 +++++--- indra/newview/llagentwearables.h | 6 ++-- indra/newview/llappearancemgr.cpp | 26 ++++++++++------- indra/newview/llappearancemgr.h | 4 +-- indra/newview/llinventorylistitem.cpp | 2 +- indra/newview/llpaneleditwearable.cpp | 55 +++++++++++++++++++++-------------- 6 files changed, 64 insertions(+), 41 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e79fda2459..70f4de8db2 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -210,12 +210,13 @@ LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCal * @param todo Bitmask of actions to take on completion. */ LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback( - LLPointer cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo) : + LLPointer cb, LLWearableType::EType type, U32 index, LLViewerWearable* wearable, U32 todo, const std::string description) : mType(type), mIndex(index), mWearable(wearable), mTodo(todo), - mCB(cb) + mCB(cb), + mDescription(description) { llinfos << "constructor" << llendl; } @@ -255,7 +256,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_WEARITEM) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item, true); + LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription); } } @@ -455,6 +456,7 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, + const std::string& description, BOOL save_in_lost_and_found) { if (!isWearableCopyable(type, index)) @@ -486,7 +488,9 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, type, index, new_wearable, - addWearableToAgentInventoryCallback::CALL_WEARITEM); + addWearableToAgentInventoryCallback::CALL_WEARITEM, + description + ); LLUUID category_id; if (save_in_lost_and_found) { diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index a60fbc969b..5be4648636 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -183,7 +183,7 @@ private: // Save Wearables //-------------------------------------------------------------------- public: - void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found); + void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, const std::string& description, BOOL save_in_lost_and_found); void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE, const std::string new_name = ""); void saveAllWearables(); @@ -270,7 +270,8 @@ private: LLWearableType::EType type, U32 index, LLViewerWearable* wearable, - U32 todo = CALL_NONE); + U32 todo = CALL_NONE, + const std::string description = ""); virtual void fire(const LLUUID& inv_item); private: LLWearableType::EType mType; @@ -278,6 +279,7 @@ private: LLViewerWearable* mWearable; U32 mTodo; LLPointer mCB; + std::string mDescription; }; }; // LLAgentWearables diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d1ed82cc98..2b1e78c899 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1902,7 +1902,7 @@ static void remove_non_link_items(LLInventoryModel::item_array_t &items) } //a predicate for sorting inventory items by actual descriptions -bool sort_by_description(const LLInventoryItem* item1, const LLInventoryItem* item2) +bool sort_by_actual_description(const LLInventoryItem* item1, const LLInventoryItem* item2) { if (!item1 || !item2) { @@ -2345,10 +2345,11 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer cb = NULL): + LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer cb = NULL, std::string description = ""): mItemID(item_id), mDoUpdate(do_update), - mCallback(cb) + mCallback(cb), + mDescription(description) { } @@ -2370,23 +2371,24 @@ public: private: const LLUUID mItemID; bool mDoUpdate; + std::string mDescription; LLPointer mCallback; }; // BAP - note that this runs asynchronously if the item is not already loaded from inventory. // Dangerous if caller assumes link will exist after calling the function. -void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer cb) +void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer cb, const std::string description) { const LLInventoryItem *item = gInventory.getItem(item_id); if (!item) { - LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb); + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description); gInventory.addObserver(observer); } else { - addCOFItemLink(item, do_update, cb); + addCOFItemLink(item, do_update, cb, description); } } @@ -2409,8 +2411,9 @@ void modified_cof_cb(const LLUUID& inv_item) } } -void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer cb) +void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer cb, const std::string description) { + std::string link_description = description; const LLViewerInventoryItem *vitem = dynamic_cast(item); if (!vitem) { @@ -2474,12 +2477,15 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update { cb = new LLBoostFuncInventoryCallback(modified_cof_cb); } - const std::string description = vitem->getIsLinkType() ? vitem->getDescription() : ""; + if (vitem->getIsLinkType()) + { + link_description = vitem->getActualDescription(); + } link_inventory_item( gAgent.getID(), vitem->getLinkedUUID(), getCOF(), vitem->getName(), - description, + link_description, LLAssetType::AT_LINK, cb); } @@ -3240,7 +3246,7 @@ void LLAppearanceMgr::sortItemsByActualDescription(LLInventoryModel::item_array_ { if (items.size() < 2) return; - std::sort(items.begin(), items.end(), sort_by_description); + std::sort(items.begin(), items.end(), sort_by_actual_description); } //#define DUMP_CAT_VERBOSE diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 01a2d41458..bb4c9ee5a2 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -129,8 +129,8 @@ public: LLPointer cb); // Add COF link to individual item. - void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL); - void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL); + void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); // Find COF entries referencing the given item. LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id); diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index 26041767fd..0601796436 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -231,7 +231,7 @@ const std::string& LLPanelInventoryListItemBase::getDescription() const { return LLStringUtil::null; } - return inv_item->getDescription(); + return inv_item->getActualDescription(); } time_t LLPanelInventoryListItemBase::getCreationDate() const diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index cca3b90329..fe4b55bb5a 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1056,36 +1056,47 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) U32 index = gAgentWearables.getWearableIndex(mWearablePtr); std::string new_name = mNameEditor->getText(); + + // Find an existing link to this wearable's inventory item, if any, and its description field. + LLInventoryItem *link_item = NULL; + std::string description; + LLInventoryModel::item_array_t links = + LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); + if (links.size()>0) + { + link_item = links.get(0).get(); + if (link_item && link_item->getIsLinkType()) + { + description = link_item->getActualDescription(); + } + } + if (force_save_as) { - // the name of the wearable has changed, re-save wearable with new name - LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); - gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, FALSE); - mNameEditor->setText(mWearableItem->getName()); + // the name of the wearable has changed, re-save wearable with new name + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); + gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); + mNameEditor->setText(mWearableItem->getName()); } else { - LLInventoryModel::item_array_t links = - LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); - if (links.size()>0) + // Make another copy of this link, with the same + // description. This is needed to bump the COF + // version so texture baking service knows appearance has changed. + if (link_item) { - // Make another copy of this link, with the same description. - LLInventoryItem *item = links.get(0).get(); - if (item) - { - const std::string description = item->getIsLinkType() ? item->getActualDescription() : ""; - link_inventory_item( gAgent.getID(), - item->getLinkedUUID(), - LLAppearanceMgr::instance().getCOF(), - item->getName(), - description, - LLAssetType::AT_LINK, - NULL); - gInventory.purgeObject(item->getUUID()); - } + // Create new link + link_inventory_item( gAgent.getID(), + link_item->getLinkedUUID(), + LLAppearanceMgr::instance().getCOF(), + link_item->getName(), + description, + LLAssetType::AT_LINK, + NULL); + // Remove old link + gInventory.purgeObject(link_item->getUUID()); } gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); - } } -- cgit v1.2.3 From f43f51406b024ed2423e068114ae818bac5c6df5 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 16 Jan 2013 14:53:23 -0800 Subject: CHUI-683 : Default sort order for Blocked was wrong, unrecognized value was not tested. --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llpanelblockedlist.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 126df69519..fd4d1df894 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10215,7 +10215,7 @@ Type U32 Value - 2 + 0 CallLogSortOrder diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index df1ccdd9fc..115114bb53 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -89,6 +89,9 @@ BOOL LLPanelBlockedList::postBuild() case E_SORT_BY_TYPE: mBlockedList->sortByType(); break; + default: + llwarns << "Unrecognized sort order for blocked list" << llendl; + break; } // Use the context menu of the Block list for the Block tab gear menu. -- cgit v1.2.3 From 5083517c7cd6b91b8920ab0f698600abed955280 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 17 Jan 2013 01:57:19 +0000 Subject: CHUI-292 FIX Extra space in object chiclet toasts in CHUI viewer compared with release viewer In LLToastNotifyPanel, moved mInfoPanel->SetFollowsAll() immediately before call to snapToMessageHeight() as was previously the case in release viewer --- indra/newview/lltoastnotifypanel.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d494d12903..268b68b539 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -356,9 +356,8 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if(rect != LLRect::null) { this->setShape(rect); - } + } mInfoPanel = getChild("info_panel"); - mInfoPanel->setFollowsAll(); mControlPanel = getChild("control_panel"); BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); @@ -453,10 +452,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if(h_pad < 2*HPAD) { /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ S32 button_per_row = button_panel_width / BUTTON_WIDTH; h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row if(h_pad < 2*HPAD) // still not enough space between buttons ? @@ -491,10 +490,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) //mButtons.assign(buttons.begin(), buttons.end()); } } + // adjust panel's height to the text size + mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); - - } -- cgit v1.2.3 From 90adfec715eb93663b424a2ac28a70e965247df4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 16 Jan 2013 19:22:36 -0800 Subject: CHUI-682 : WIP : Instrument the menu display (or lack thereof). --- indra/newview/llpaneloutfitedit.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index d690a18477..c11539353a 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -155,6 +155,8 @@ class LLPanelOutfitEditGearMenu public: static LLToggleableMenu* create() { + llinfos << "Merov debug : Create wearable gear menu" << llendl; + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Wearable.Create", boost::bind(onCreate, _2)); @@ -169,6 +171,12 @@ public: return menu; } + + static void pressed(LLToggleableMenu* menu) + { + menu->toggleVisibility(); + llinfos << "Merov debug : The button is pressed! Show the menu!!!" << llendl; + } private: static void onCreate(const LLSD& param) @@ -189,6 +197,8 @@ private: LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); + llinfos << "Merov debug : Populate wearable gear menu" << llendl; + for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { LLWearableType::EType type = (LLWearableType::EType) i; @@ -197,6 +207,7 @@ private: LLMenuItemCallGL::Params p; p.name = type_name; p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); + llinfos << "Merov debug : menu label = " << LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)) << llendl; p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); @@ -204,6 +215,8 @@ private: menu_clothes : menu_bp; LLUICtrlFactory::create(p, parent); } + + llinfos << "Merov debug : clothes size = " << menu_clothes->getChildCount() << ", body part size = " << menu_bp->getChildCount() << llendl; } }; @@ -564,6 +577,7 @@ BOOL LLPanelOutfitEdit::postBuild() mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu); mGearMenu = LLPanelOutfitEditGearMenu::create(); + mGearMenuBtn->setMouseDownCallback(boost::bind(&LLPanelOutfitEditGearMenu::pressed, mGearMenu)); mGearMenuBtn->setMenu(mGearMenu); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); -- cgit v1.2.3 From 7ec0d837dd2f364a775757b808351fa81c2468a8 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Thu, 17 Jan 2013 19:05:22 +0200 Subject: CHUI-631 (Next conversation in list should be selected in Conversations floater after closing a conversation) Don't force selecting nearby chat after closing conversation --- indra/newview/llfloaterimsessiontab.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 06a79836db..bc5b8c334d 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -88,13 +88,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; - - // Select Nearby Chat session - LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance("im_container"); - if (container) - { - container->selectConversationPair(LLUUID(NULL), true); - } } //static -- cgit v1.2.3 From aabfce7d9f14ff18ea073708d79c6f62118b3453 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 17 Jan 2013 21:40:49 -0800 Subject: CHUI-682 : Fixed : Added LLMenuGL as a possible child of a toggle or contextual menu (for dynamic submenus). --- indra/llui/llmenugl.cpp | 28 +++++++++++++++++++++------- indra/newview/llpaneloutfitedit.cpp | 14 -------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 93dc13475b..7dcc39950b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1751,16 +1751,18 @@ void LLMenuGL::setCanTearOff(BOOL tear_off) bool LLMenuGL::addChild(LLView* view, S32 tab_group) { - if (LLMenuGL* menup = dynamic_cast(view)) + LLMenuGL* menup = dynamic_cast(view); + if (menup) { - appendMenu(menup); - return true; + return appendMenu(menup); } - else if (LLMenuItemGL* itemp = dynamic_cast(view)) + + LLMenuItemGL* itemp = dynamic_cast(view); + if (itemp) { - append(itemp); - return true; + return append(itemp); } + return false; } @@ -1771,16 +1773,28 @@ bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) { LLContextMenu* context = dynamic_cast(view); if (context) + { return appendContextSubMenu(context); + } LLMenuItemSeparatorGL* separator = dynamic_cast(view); if (separator) + { return append(separator); + } LLMenuItemGL* item = dynamic_cast(view); if (item) + { return append(item); - + } + + LLMenuGL* menup = dynamic_cast(view); + if (menup) + { + return appendMenu(menup); + } + return false; } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c11539353a..f5db98f831 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -155,8 +155,6 @@ class LLPanelOutfitEditGearMenu public: static LLToggleableMenu* create() { - llinfos << "Merov debug : Create wearable gear menu" << llendl; - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Wearable.Create", boost::bind(onCreate, _2)); @@ -172,12 +170,6 @@ public: return menu; } - static void pressed(LLToggleableMenu* menu) - { - menu->toggleVisibility(); - llinfos << "Merov debug : The button is pressed! Show the menu!!!" << llendl; - } - private: static void onCreate(const LLSD& param) { @@ -197,8 +189,6 @@ private: LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); - llinfos << "Merov debug : Populate wearable gear menu" << llendl; - for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { LLWearableType::EType type = (LLWearableType::EType) i; @@ -207,7 +197,6 @@ private: LLMenuItemCallGL::Params p; p.name = type_name; p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)); - llinfos << "Merov debug : menu label = " << LLTrans::getString(LLWearableType::getTypeDefaultNewName(type)) << llendl; p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); @@ -215,8 +204,6 @@ private: menu_clothes : menu_bp; LLUICtrlFactory::create(p, parent); } - - llinfos << "Merov debug : clothes size = " << menu_clothes->getChildCount() << ", body part size = " << menu_bp->getChildCount() << llendl; } }; @@ -577,7 +564,6 @@ BOOL LLPanelOutfitEdit::postBuild() mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu); mGearMenu = LLPanelOutfitEditGearMenu::create(); - mGearMenuBtn->setMouseDownCallback(boost::bind(&LLPanelOutfitEditGearMenu::pressed, mGearMenu)); mGearMenuBtn->setMenu(mGearMenu); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); -- cgit v1.2.3 From 3938f99b5ede5b87315fa18ca24d2deece28b34d Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 18 Jan 2013 14:18:51 +0200 Subject: CHUI-681 FIXED Clear flash state only for selected widget --- indra/newview/llconversationview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 903dd2a407..126c73c283 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -246,7 +246,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) if(result && getRoot()->getCurSelectedItem() == this) { LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance("im_container"); - im_container->clearAllFlashStates(); + im_container->flashConversationItemWidget(session_id,false); im_container->selectConversationPair(session_id, false); im_container->collapseMessagesPane(false); } -- cgit v1.2.3 From be7835eec6b6cae12656fede44fc2cda1729e20d Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Thu, 17 Jan 2013 16:25:21 +0200 Subject: CHUI-625 Participant drop down icon not visible when conversation is highlighted orange: redraw the arrow slightly later --- indra/newview/llconversationview.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 126c73c283..16dd0e4565 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -202,14 +202,6 @@ void LLConversationViewSession::draw() const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams(); const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - // we don't draw the open folder arrow in minimized mode - if (mHasArrow && !mCollapsedMode) - { - // update the rotation angle of open folder arrow - updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); - } - // Indicate that flash can start (moot operation if already started, done or not flashing) startFlashing(); @@ -232,6 +224,14 @@ void LLConversationViewSession::draw() (*iit)->setVisible(draw_children); } + // we don't draw the open folder arrow in minimized mode + if (mHasArrow && !mCollapsedMode) + { + // update the rotation angle of open folder arrow + updateLabelRotation(); + drawOpenFolderArrow(default_params, sFgColor); + } + LLView::draw(); } -- cgit v1.2.3 From fdf774f51fd24bb62d1e1fc580bd04df4547b9f8 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 17 Jan 2013 13:52:51 -0800 Subject: CHUI-685 Problem: The notifications .xml file was cleared upon exit because removeIMNotification was being called and deleting inventory offers becaus they did not have a session id. Resolution: Now check to make sure that removeIMNotification only removes IMs (IMToast). --- .../newview/lldonotdisturbnotificationstorage.cpp | 62 ++++++++++++---------- indra/newview/lldonotdisturbnotificationstorage.h | 3 -- indra/newview/llfloaterimcontainer.cpp | 16 +++--- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 42b455c1ce..5bea7d41f6 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -43,15 +43,16 @@ #include "lluuid.h" static const F32 DND_TIMER = 3.0; +const std::string toastName = "IMToast"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { - mEventTimer.start(); + //mEventTimer.start(); } LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() { - mEventTimer.stop(); + //mEventTimer.stop(); } BOOL LLDoNotDisturbNotificationStorageTimer::tick() @@ -152,27 +153,27 @@ void LLDoNotDisturbNotificationStorage::loadNotifications() std::string notificationName = notification_params["name"]; LLNotificationPtr notification = instance.find(notificationID); - if(notificationName == "IMToast") + if(notificationName == toastName) { imToastExists = true; } //New notification needs to be added - notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); - LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); - if (responder == NULL) - { - LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" - << notification->getType() << "'" << LL_ENDL; - } - else - { - LLNotificationResponderPtr responderPtr(responder); - notification->setResponseFunctor(responderPtr); - } - - instance.add(notification); + notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true)); + LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]); + if (responder == NULL) + { + LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '" + << notification->getType() << "'" << LL_ENDL; + } + else + { + LLNotificationResponderPtr responderPtr(responder); + notification->setResponseFunctor(responderPtr); } + + instance.add(notification); + } if(imToastExists) { @@ -200,7 +201,7 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() LLNotificationPtr notification = it->second; std::string notificationName = notification->getName(); - if(notificationName == "IMToast") + if(notificationName == toastName) { imToastExists = true; } @@ -221,9 +222,9 @@ void LLDoNotDisturbNotificationStorage::updateNotifications() //When exit DND mode, write empty notifications file if(commChannel->getHistorySize()) { - commChannel->clearHistory(); - saveNotifications(); -} + commChannel->clearHistory(); + saveNotifications(); + } } LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const @@ -241,6 +242,7 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi LLNotificationPtr notification; LLSD substitutions; LLUUID notificationSessionID; + std::string notificationName; LLCommunicationChannel::history_list_t::iterator it; std::vector itemsToRemove; @@ -252,8 +254,10 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi notification = it->second; substitutions = notification->getSubstitutions(); notificationSessionID = substitutions["SESSION_ID"].asUUID(); + notificationName = notification->getName(); - if(session_id == notificationSessionID) + if(notificationName == toastName + && session_id == notificationSessionID) { itemsToRemove.push_back(it); } @@ -263,14 +267,14 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi //Remove the notifications if(itemsToRemove.size()) { - while(itemsToRemove.size()) - { - it = itemsToRemove.back(); - notification = it->second; + while(itemsToRemove.size()) + { + it = itemsToRemove.back(); + notification = it->second; commChannel->removeItemFromHistory(notification); - instance.cancel(notification); - itemsToRemove.pop_back(); - } + instance.cancel(notification); + itemsToRemove.pop_back(); + } //Trigger saving of notifications to xml once all have been removed saveNotifications(); } diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index fd03b71357..fd7cc7ee82 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -42,9 +42,6 @@ public: ~LLDoNotDisturbNotificationStorageTimer(); public: - void startTimer(); - void stopTimer(); - bool isRunning(); BOOL tick(); }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index cc23449449..8f290ae7c1 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1299,11 +1299,14 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool if (widget && widget->getParentFolder()) { widget->getParentFolder()->setSelection(widget, FALSE, FALSE); - if(gAgent.isDoNotDisturb()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); - } } + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && session_id.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + } } /* floater processing */ @@ -1324,11 +1327,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool // Switch to the conversation floater that is being selected selectFloater(session_floater); } - - if(gAgent.isDoNotDisturb()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); - } } // Set the focus on the selected floater -- cgit v1.2.3 From 6a134c92d82746a2bfbf011e53aa04bdec67655f Mon Sep 17 00:00:00 2001 From: mberezhnoy Date: Fri, 18 Jan 2013 00:05:51 +0200 Subject: CHUI-661 User cannot select multiple p2p conversation names in list to start conference chat --- indra/newview/llfloaterimcontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8264a90325..ac5ecc4b80 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1290,9 +1290,9 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool { BOOL handled = TRUE; LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - + /* widget processing */ - if (select_widget) + if (select_widget && mConversationsRoot->getSelectedCount() <= 1) { LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id); if (widget && widget->getParentFolder()) -- cgit v1.2.3 From 68adda3627b0583e01796b229e1c1f920f28ff37 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 17 Jan 2013 14:12:48 -0800 Subject: CHUI-685 removing some commented out code --- indra/newview/lldonotdisturbnotificationstorage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 5bea7d41f6..824ff67972 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -47,12 +47,12 @@ const std::string toastName = "IMToast"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { - //mEventTimer.start(); + } LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() { - //mEventTimer.stop(); + } BOOL LLDoNotDisturbNotificationStorageTimer::tick() -- cgit v1.2.3 From 6c79873d8dcb08c891ecd04f5706e69fe3a75b7d Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 17 Jan 2013 15:14:02 -0800 Subject: CHUI-680: Adjusted LLResponderRegistry to be derived from LLRegistrySingleton instead of LLResponderRegistry making its over version. --- indra/newview/llnotificationstorage.cpp | 93 ++++++++++++--------------------- 1 file changed, 33 insertions(+), 60 deletions(-) diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 4c5b7cc198..b6184f09bf 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -38,30 +38,43 @@ #include "llsd.h" #include "llsdserialize.h" #include "llsingleton.h" -#include "llviewermessage.h" +#include "llregistry.h" +#include "llviewermessage.h" +typedef boost::function responder_constructor_t; -class LLResponderRegistry : public LLSingleton +class LLResponderRegistry : public LLRegistrySingleton { -public: - LLResponderRegistry(); - ~LLResponderRegistry(); - - LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams); - -protected: - -private: - template static LLNotificationResponderInterface* create(const LLSD& pParams); - - typedef boost::function responder_constructor_t; - - void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor); - - typedef std::map build_map_t; - build_map_t mBuildMap; + public: + template static LLNotificationResponderInterface * create(const LLSD& pParams); + LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); }; +template LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} + + +LLNotificationResponderInterface * LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + responder_constructor_t * factoryFunc = (LLResponderRegistry::getValue(pNotificationName)); + + if(factoryFunc) + { + return (*factoryFunc)(pParams); + } + + return NULL; +} + +LLResponderRegistry::StaticRegistrar sRegisterObjectGiveItem("ObjectGiveItem", &LLResponderRegistry::create); +LLResponderRegistry::StaticRegistrar sRegisterUserGiveItem("UserGiveItem", &LLResponderRegistry::create); +LLResponderRegistry::StaticRegistrar sRegisterOfferInfo("offer_info", &LLResponderRegistry::create); + + LLNotificationStorage::LLNotificationStorage(std::string pFileName) : mFileName(pFileName) { @@ -116,47 +129,7 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const return didFileRead; } -LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const +LLNotificationResponderInterface * LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const { return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); } - -LLResponderRegistry::LLResponderRegistry() - : LLSingleton() - , mBuildMap() -{ - add("ObjectGiveItem", &create); - add("UserGiveItem", &create); - add("offer_info", &create); -} - -LLResponderRegistry::~LLResponderRegistry() -{ -} - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) -{ - build_map_t::const_iterator it = mBuildMap.find(pNotificationName); - if(mBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(pParams); -} - -template LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams) -{ - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(pParams); - return responder; -} - -void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor) -{ - if (mBuildMap.find(pNotificationName) != mBuildMap.end()) - { - LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL; - } - mBuildMap.insert(std::make_pair(pNotificationName, pConstructor)); -} -- cgit v1.2.3 From d0235ad1789d05524065307f4514a76d55f4e847 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Thu, 17 Jan 2013 16:06:08 -0800 Subject: CHUI-604: Problem: DND response was inside of the responder for the inventory offer. Resolution: DND response is now sent upon receiving an offer notification from an agent. --- indra/newview/llviewermessage.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index db81e057de..9878f9bc81 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1618,12 +1618,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { opener = discard_agent_offer; } - - - if (gAgent.isDoNotDisturb() && (!mFromGroup && !mFromObject)) - { - send_do_not_disturb_message(gMessageSystem, mFromID); - } if (modified_form != NULL) { @@ -1991,6 +1985,11 @@ void inventory_offer_handler(LLOfferInfo* info) // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). info->send_auto_receive_response(); + if (gAgent.isDoNotDisturb()) + { + send_do_not_disturb_message(gMessageSystem, info->mFromID); + } + // Inform user that there is a script floater via toast system { payload["give_inventory_notification"] = TRUE; -- cgit v1.2.3 From 1780e78884c1b111f4a48bea578e28b370fbe45c Mon Sep 17 00:00:00 2001 From: Cho Date: Fri, 18 Jan 2013 02:05:09 +0000 Subject: CHUI-688 FIX Viewer crash when blocked user sends friend request Added a check for notification_ptr being null in friendship_offer_callback --- indra/newview/llviewermessage.cpp | 132 ++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 64 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index db81e057de..4bff0222bd 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -189,70 +189,74 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) const LLSD& payload = notification["payload"]; LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - // add friend to recent people list - LLRecentPeople::instance().add(payload["from_id"]); - - switch(option) - { - case 0: - { - // accept - LLAvatarTracker::formFriendship(payload["from_id"]); - - const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); - - // This will also trigger an onlinenotification if the user is online - msg->newMessageFast(_PREHASH_AcceptFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, fid); - msg->sendReliable(LLHost(payload["sender"].asString())); - - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipAcceptedByMe", - notification["substitutions"], payload); - break; - } - case 1: // Decline - { - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipDeclinedByMe", - notification["substitutions"], payload); - } - // fall-through - case 2: // Send IM - decline and start IM session - { - // decline - // We no longer notify other viewers, but we DO still send - // the rejection to the simulator to delete the pending userop. - msg->newMessageFast(_PREHASH_DeclineFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->sendReliable(LLHost(payload["sender"].asString())); - - // start IM session - if(2 == option) - { - LLAvatarActions::startIM(payload["from_id"].asUUID()); - } - } - default: - // close button probably, possibly timed out - break; - } - - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); - modified_form->setElementEnabled("Accept", false); - modified_form->setElementEnabled("Decline", false); - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + // this will be skipped if the user offering friendship is blocked + if (notification_ptr) + { + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + + switch(option) + { + case 0: + { + // accept + LLAvatarTracker::formFriendship(payload["from_id"]); + + const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + + // This will also trigger an onlinenotification if the user is online + msg->newMessageFast(_PREHASH_AcceptFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + msg->sendReliable(LLHost(payload["sender"].asString())); + + LLSD payload = notification["payload"]; + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + break; + } + case 1: // Decline + { + LLSD payload = notification["payload"]; + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + // fall-through + case 2: // Send IM - decline and start IM session + { + // decline + // We no longer notify other viewers, but we DO still send + // the rejection to the simulator to delete the pending userop. + msg->newMessageFast(_PREHASH_DeclineFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->sendReliable(LLHost(payload["sender"].asString())); + + // start IM session + if(2 == option) + { + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } + } + default: + // close button probably, possibly timed out + break; + } + + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Accept", false); + modified_form->setElementEnabled("Decline", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + } return false; } -- cgit v1.2.3 From 5eef65e99476b716985eeccfbbcdafdfb664cb1a Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 18 Jan 2013 03:52:42 +0200 Subject: CHUI-379 FIXED Restore Voice Morphing menu --- indra/llui/llmenugl.cpp | 53 ++++++++++- indra/llui/llmenugl.h | 6 ++ indra/newview/llviewermenu.cpp | 16 +++- indra/newview/llvoicevivox.cpp | 100 +++++++++++++++++++++ indra/newview/llvoicevivox.h | 3 + .../skins/default/xui/en/floater_voice_effect.xml | 3 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 39 +++++--- 7 files changed, 207 insertions(+), 13 deletions(-) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7dcc39950b..2ea25648df 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2461,6 +2461,56 @@ void LLMenuGL::empty( void ) deleteAllChildren(); } +// erase group of items from menu +void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) +{ + S32 items = mItems.size(); + + if ( items == 0 || begin >= end || begin < 0 || end > items ) + { + return; + } + + item_list_t::const_iterator start_position = mItems.begin(); + std::advance(start_position, begin); + + item_list_t::const_iterator end_position = mItems.begin(); + std::advance(end_position, end); + + for (item_list_t::const_iterator position_iter = start_position; position_iter != end_position; position_iter++) + { + LLUICtrl::removeChild(*position_iter); + } + + mItems.erase(start_position, end_position); + + if (arrange) + { + needsArrange(); + } +} + +// add new item at position +void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) +{ + LLMenuItemGL * item = dynamic_cast(ctrl); + + if (NULL == item || position < 0 || position >= mItems.size()) + { + return; + } + + item_list_t::const_iterator position_iter = mItems.begin(); + std::advance(position_iter, position); + mItems.insert(position_iter, item); + LLUICtrl::addChild(item); + + if (arrange) + { + needsArrange(); + } +} + // Adjust rectangle of the menu void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom) { @@ -2502,7 +2552,8 @@ BOOL LLMenuGL::append( LLMenuItemGL* item ) // add a separator to this menu BOOL LLMenuGL::addSeparator() { - LLMenuItemGL* separator = new LLMenuItemSeparatorGL(); + LLMenuItemSeparatorGL::Params p; + LLMenuItemGL* separator = LLUICtrlFactory::create(p); return addChild(separator); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 3e03232e92..c57e0f0267 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -478,6 +478,12 @@ public: // remove all items on the menu void empty( void ); + // erase group of items from menu + void erase( S32 begin, S32 end, bool arrange = true ); + + // add new item at position + void insert( S32 begin, LLView * ctrl, bool arrange = true ); + void setItemLastSelected(LLMenuItemGL* item); // must be in menu U32 getItemCount(); // number of menu items LLMenuItemGL* getItem(S32 number); // 0 = first item diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a0aa639ac6..8b45c44ed0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -108,6 +108,7 @@ #include "llviewerparcelmgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" +#include "llvoicevivox.h" #include "llworldmap.h" #include "pipeline.h" #include "llviewerjoystick.h" @@ -8152,6 +8153,11 @@ public: } }; +void handle_voice_morphing_subscribe() +{ + LLWeb::loadURLExternal(LLTrans::getString("voice_morphing_url")); +} + class LLToggleUIHints : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8337,7 +8343,15 @@ void initialize_menus() // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); - + + // Communicate > Voice morphing > Subscribe... + commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe)); + LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance(); + enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check" + , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing")); + commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click" + , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing")); + // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 5e121bbcee..f3342b7ff1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -34,6 +34,7 @@ #include "llvoavatarself.h" #include "llbufferstream.h" #include "llfile.h" +#include "llmenugl.h" #ifdef LL_STANDALONE # include "expat.h" #else @@ -70,6 +71,9 @@ #define USE_SESSION_GROUPS 0 +extern LLMenuBarGL* gMenuBarView; +extern void handle_voice_morphing_subscribe(); + const F32 VOLUME_SCALE_VIVOX = 0.01f; const F32 SPEAKING_TIMEOUT = 1.f; @@ -6739,10 +6743,106 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) mVoiceFontObservers.erase(observer); } +// method checks the item in VoiceMorphing menu for appropriate current voice font +bool LLVivoxVoiceClient::onCheckVoiceEffect(const std::string& voice_effect_name) +{ + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (NULL != effect_interfacep) + { + const LLUUID& currect_voice_effect_id = effect_interfacep->getVoiceEffect(); + + if (currect_voice_effect_id.isNull()) + { + if (voice_effect_name == "NoVoiceMorphing") + { + return true; + } + } + else + { + const LLSD& voice_effect_props = effect_interfacep->getVoiceEffectProperties(currect_voice_effect_id); + if (voice_effect_props["name"].asString() == voice_effect_name) + { + return true; + } + } + } + + return false; +} + +// method changes voice font for selected VoiceMorphing menu item +void LLVivoxVoiceClient::onClickVoiceEffect(const std::string& voice_effect_name) +{ + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (NULL != effect_interfacep) + { + if (voice_effect_name == "NoVoiceMorphing") + { + effect_interfacep->setVoiceEffect(LLUUID()); + return; + } + const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList(); + if (!effect_list.empty()) + { + for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) + { + if (voice_effect_name == it->first) + { + effect_interfacep->setVoiceEffect(it->second); + return; + } + } + } + } +} + +// it updates VoiceMorphing menu items in accordance with purchased properties +void LLVivoxVoiceClient::updateVoiceMorphingMenu() +{ + if (mVoiceFontListDirty) + { + LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface(); + if (effect_interfacep) + { + const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList(); + if (!effect_list.empty()) + { + LLMenuGL * voice_morphing_menup = gMenuBarView->findChildMenuByName("VoiceMorphing", TRUE); + + if (NULL != voice_morphing_menup) + { + S32 items = voice_morphing_menup->getItemCount(); + if (items > 0) + { + voice_morphing_menup->erase(1, items - 3, false); + + S32 pos = 1; + for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) + { + LLMenuItemCheckGL::Params p; + p.name = it->first; + p.label = it->first; + p.on_check.function(boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, this, it->first)); + p.on_click.function(boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, this, it->first)); + LLMenuItemCheckGL * voice_effect_itemp = LLUICtrlFactory::create(p); + voice_morphing_menup->insert(pos++, voice_effect_itemp, false); + } + + voice_morphing_menup->needsArrange(); + } + } + } + } + } +} + void LLVivoxVoiceClient::notifyVoiceFontObservers() { LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL; + updateVoiceMorphingMenu(); + for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); it != mVoiceFontObservers.end(); ) diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 69f33df94b..574027de42 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -246,6 +246,8 @@ public: //@} + bool onCheckVoiceEffect(const std::string& voice_effect_name); + void onClickVoiceEffect(const std::string& voice_effect_name); protected: ////////////////////// @@ -854,6 +856,7 @@ private: void accountGetTemplateFontsSendMessage(); void sessionSetVoiceFontSendMessage(sessionState *session); + void updateVoiceMorphingMenu(); void notifyVoiceFontObservers(); typedef enum e_voice_font_type diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 35cb2670d0..146c3d7e30 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -5,12 +5,13 @@ height="500" name="voice_effects" help_topic="voice_effects" - title="VOICE MORPHING" + title="VOICE MORPHING PREVIEW" background_visible="true" label="Places" layout="topleft" min_height="360" min_width="200" + save_rect="true" width="300"> (No Voice Morph) diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 8d5e3f0b5d..10fd8138d2 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -268,17 +268,36 @@ parameter="conversation" /> - - - - + + + + + + + + + + + + + Date: Fri, 18 Jan 2013 21:22:18 +0000 Subject: Moving appearance utility deb to private repo --- autobuild.xml | 4 ++-- build.sh | 54 ++++++++++++++++-------------------------------------- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 3c503997cc..eaafc45427 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@ archive hash - 17bcc2481fe362e297376d9c46888de8 + 376738111ec9ba6f1b0d0dee0a3c784d url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/268501/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121220.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/269218/arch/Linux/installer/llappearanceutility_source-0.1-linux-20130118.tar.bz2 name linux diff --git a/build.sh b/build.sh index 307dda85eb..d779a1a34b 100755 --- a/build.sh +++ b/build.sh @@ -334,51 +334,29 @@ then done fi # Move any .deb results. - mv ${build_dir}/packages/*.deb ../ 2>/dev/null || true + mkdir -p ../packages_public + mkdir -p ../packages_private + mv ${build_dir}/packages/*.deb ../packages_public 2>/dev/null || true + mv ${build_dir}/packages/packages_private/*.deb ../packages_private 2>/dev/null || true # upload debian package and create repository begin_section "Upload Debian Repository" - for deb_file in ../*.deb; do + for deb_file in `/bin/ls ../packages_public/*.deb ../*.deb 2>/dev/null`; do upload_item debian $deb_file binary/octet-stream done - if [ -d "$build_log_dir/debian_repo" ] - then - pushd "$build_log_dir/debian_repo" - cat > Release < Packages.gz \ - && dpkg-scansources . /dev/null | gzip -9c > Sources.gz - then - begin_section Packages.gz - gunzip --stdout Packages.gz - for file in *.deb - do - stat "$file" | sed 2q - md5sum "$file" - done - end_section Packages.gz - - for file in * - do - upload_item debian_repo "$file" binary/octet-stream - done - else - record_failure 'Unable to generate Packages.gz or Sources.gz' - fi - popd - - process_pending_uploads + for deb_file in `/bin/ls ../packages_private/*.deb 2>/dev/null`; do + upload_item debian_private $deb_file binary/octet-stream + done - # Rename the local debian_repo directory so that the master buildscript - # doesn't make a remote repo again. + create_deb_repo - mv $build_log_dir/debian_repo $build_log_dir/debian_repo_pushed - fi + # Rename the local debian_repo* directories so that the master buildscript + # doesn't make a remote repo again. + for debian_repo_type in debian_repo debian_repo_private; do + if [ -d "$build_log_dir/$debian_repo_type" ]; then + mv $build_log_dir/$debian_repo_type $build_log_dir/${debian_repo_type}_pushed + fi + done end_section "Upload Debian Repository" else -- cgit v1.2.3 From b3cbe35532b365e223df14921532a6e587695dec Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 18 Jan 2013 16:51:03 -0500 Subject: SH-3344 WIP - more texture load monitoring --- indra/newview/llvoavatar.cpp | 96 +++++++++++++++++++++++++++++++++++----- indra/newview/llvoavatar.h | 16 ++++--- indra/newview/llvoavatarself.cpp | 1 + 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index df0b8171a6..54bb755ad5 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2888,7 +2888,11 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { central_bake_version = getRegion()->getCentralBakeVersion(); } - addDebugText(llformat("mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); + bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); + addDebugText(llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + all_local_downloaded ? "L" : "l", + all_baked_downloaded ? "B" : "b", mUseLocalAppearance, mIsEditingAppearance, mUseServerBakes, central_bake_version)); } @@ -4001,10 +4005,48 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) return 6; } -//------------------------------------------------------------------------ -// LLVOAvatar::updateTextures() -//------------------------------------------------------------------------ -void LLVOAvatar::collectTextureUUIDs(std::set& ids, S32& local_mem, S32& baked_mem) +bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) +{ + for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep && imagep->getDiscardLevel()!=0) + { + return false; + } + } + return true; +} + +bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() +{ + std::set local_ids; + collectLocalTextureUUIDs(local_ids); + return allTexturesCompletelyDownloaded(local_ids); +} + +bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() +{ + std::set baked_ids; + collectLocalTextureUUIDs(baked_ids); + return allTexturesCompletelyDownloaded(baked_ids); +} + +S32 LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) +{ + S32 result = 0; + for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); + if (imagep) + { + result += imagep->getTextureMemory(); + } + } + return result; +} + +void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { @@ -4020,17 +4062,26 @@ void LLVOAvatar::collectTextureUUIDs(std::set& ids, S32& local_mem, S32& const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); if (texture_dict->mIsLocalTexture) { - local_mem += imagep->getTextureMemory(); ids.insert(imagep->getID()); } } } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); +} + +void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) +{ + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLViewerFetchedTexture *imagep = NULL; if (isIndexBakedTexture((ETextureIndex) texture_index)) { imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); if (imagep) { - baked_mem += imagep->getTextureMemory(); ids.insert(imagep->getID()); } } @@ -4040,15 +4091,36 @@ void LLVOAvatar::collectTextureUUIDs(std::set& ids, S32& local_mem, S32& ids.erase(IMG_INVISIBLE); } +void LLVOAvatar::collectTextureUUIDs(std::set& ids) +{ + collectLocalTextureUUIDs(ids); + collectBakedTextureUUIDs(ids); +} + void LLVOAvatar::releaseOldTextures() { S32 current_texture_mem = 0; // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" + std::set baked_texture_ids; + collectBakedTextureUUIDs(baked_texture_ids); + S32 new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); + + std::set local_texture_ids; + collectLocalTextureUUIDs(local_texture_ids); + S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); + std::set new_texture_ids; - S32 local_mem = 0, baked_mem = 0; - collectTextureUUIDs(new_texture_ids, local_mem, baked_mem); - LL_DEBUGS("Avatar") << getFullname() << " local_mem: " << local_mem << " baked_mem: " << baked_mem << llendl; + new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); + new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); + S32 new_total_mem = totalTextureMemForUUIDS(new_texture_ids); + + S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); + LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << llendl; + if (!isSelf() && new_total_mem > new_baked_mem) + { + llwarns << "extra local textures stored for non-self av" << llendl; + } for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) { if (new_texture_ids.find(*it) == new_texture_ids.end()) @@ -4062,8 +4134,8 @@ void LLVOAvatar::releaseOldTextures() // This will allow the texture to be deleted if not in use. imagep->forceActive(); - // This resets the clock to being flagged as - // unused, preventing the texture from being + // This resets the clock to texture being flagged + // as unused, preventing the texture from being // deleted immediately. If other avatars or // objects are using it, it can still be flagged // no-delete by them. diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 5b1395e566..2c64b9695e 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -124,17 +124,23 @@ protected: public: /*virtual*/ void updateGL(); /*virtual*/ LLVOAvatar* asAvatar(); - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp); - virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ BOOL updateLOD(); - BOOL updateJointLODs(); - void updateLODRiggedAttachments( void ); + BOOL updateJointLODs(); + void updateLODRiggedAttachments( void ); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - void collectTextureUUIDs(std::set& ids, S32& local_mem, S32& baked_mem); + S32 totalTextureMemForUUIDS(std::set& ids); + bool allTexturesCompletelyDownloaded(std::set& ids); + bool allLocalTexturesCompletelyDownloaded(); + bool allBakedTexturesCompletelyDownloaded(); + void collectLocalTextureUUIDs(std::set& ids); + void collectBakedTextureUUIDs(std::set& ids); + void collectTextureUUIDs(std::set& ids); void releaseOldTextures(); /*virtual*/ void updateTextures(); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 9b43db7087..19534bde59 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2066,6 +2066,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV << " ts: " << image->getTextureState() << " bl: " << image->getBoostLevel() << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. + << " cl: " << (image->isFullyLoaded() && image->getDiscardLevel()==0) // "completely loaded" << " mvs: " << image->getMaxVirtualSize() << " mvsc: " << image->getMaxVirtualSizeResetCounter() << " mem: " << image->getTextureMemory(); -- cgit v1.2.3 From b13d0b7a658784f015256576b71643827c572bb5 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 19 Jan 2013 02:00:39 +0000 Subject: Adding stub for private artifacts --- build.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.sh b/build.sh index d779a1a34b..964f9ef0a6 100755 --- a/build.sh +++ b/build.sh @@ -312,6 +312,7 @@ then if $build_viewer_deb && [ "$last_built_variant" == "Release" ] then begin_section "Build Viewer Debian Package" + local have_private_repo=false # mangle the changelog dch --force-bad-version \ --distribution unstable \ @@ -346,6 +347,7 @@ then done for deb_file in `/bin/ls ../packages_private/*.deb 2>/dev/null`; do upload_item debian_private $deb_file binary/octet-stream + have_private_repo=true done create_deb_repo @@ -357,6 +359,14 @@ then mv $build_log_dir/$debian_repo_type $build_log_dir/${debian_repo_type}_pushed fi done + + if [ $have_private_repo = true ]; then + eval "$python_command \"$redirect\" '\${private_S3PROXY_URL}${S3PREFIX}repo/$repo/rev/$revision/index.html'"\ + >"$build_log_dir/private.html" || fatal generating redirect + upload_item global_redirect "$build_log_dir/private.html" text/html + + fi + end_section "Upload Debian Repository" else -- cgit v1.2.3 From 52018b79bdd715dbb7bd42792447566347b641d5 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Sun, 20 Jan 2013 14:16:53 -0800 Subject: CHUI-379 : Fix Mac and Linux build failures --- indra/llui/llmenugl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 2ea25648df..27f6ac5b80 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2471,13 +2471,13 @@ void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/) return; } - item_list_t::const_iterator start_position = mItems.begin(); + item_list_t::iterator start_position = mItems.begin(); std::advance(start_position, begin); - item_list_t::const_iterator end_position = mItems.begin(); + item_list_t::iterator end_position = mItems.begin(); std::advance(end_position, end); - for (item_list_t::const_iterator position_iter = start_position; position_iter != end_position; position_iter++) + for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++) { LLUICtrl::removeChild(*position_iter); } @@ -2500,7 +2500,7 @@ void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ ) return; } - item_list_t::const_iterator position_iter = mItems.begin(); + item_list_t::iterator position_iter = mItems.begin(); std::advance(position_iter, position); mItems.insert(position_iter, item); LLUICtrl::addChild(item); -- cgit v1.2.3 From 824457f98c93a2f48f402740982a410b9fbc3487 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Mon, 21 Jan 2013 14:10:12 +0200 Subject: CHUI-567 FIXED Menu items are moved to Participant view menu --- indra/newview/llfloaterimcontainer.cpp | 13 ++++++++++++- indra/newview/llfloaterimsessiontab.cpp | 21 --------------------- indra/newview/llfloaterimsessiontab.h | 4 ---- .../default/xui/en/menu_im_session_showmodes.xml | 19 +------------------ .../skins/default/xui/en/menu_participant_view.xml | 20 ++++++++++++++++++++ 5 files changed, 33 insertions(+), 44 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8f290ae7c1..f73db6b166 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -813,6 +813,10 @@ void LLFloaterIMContainer::onCustomAction(const LLSD& userdata) floater_prefp->selectPrivacyPanel(); } } + if ("Translating.Toggle" == command) + { + gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); + } } BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata) @@ -843,7 +847,14 @@ BOOL LLFloaterIMContainer::isActionChecked(const LLSD& userdata) { return (order.getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE); } - + if ("Translating.Enabled" == command) + { + return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); + } + if ("Translating.On" == command) + { + return gSavedSettings.getBOOL("TranslateChat"); + } return FALSE; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index bc5b8c334d..0cdfde3975 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -72,12 +72,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); - mEnableCallbackRegistrar.add("Translating.Enabled", - boost::bind(&LLFloaterIMSessionTab::isTranslatingEnabled, this, _2)); - mEnableCallbackRegistrar.add("Translating.On", - boost::bind(&LLFloaterIMSessionTab::isTranslationOn, this, _2)); - mCommitCallbackRegistrar.add("Translating.Toggle", - boost::bind(&LLFloaterIMSessionTab::toggleTranslation, this, _2)); // Right click menu handling mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); @@ -551,11 +545,6 @@ void LLFloaterIMSessionTab::onIMSessionMenuItemClicked(const LLSD& userdata) LLFloaterIMSessionTab::processChatHistoryStyleUpdate(); } -void LLFloaterIMSessionTab::toggleTranslation(const LLSD& userdata) -{ - gSavedSettings.setBOOL("TranslateChat", !gSavedSettings.getBOOL("TranslateChat")); -} - bool LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) { std::string item = userdata.asString(); @@ -579,16 +568,6 @@ bool LLFloaterIMSessionTab::onIMShowModesMenuItemEnable(const LLSD& userdata) return (plain_text && (is_not_names || mIsP2PChat)); } -bool LLFloaterIMSessionTab::isTranslatingEnabled(const LLSD& userdata) -{ - return gSavedPerAccountSettings.getBOOL("TranslatingEnabled"); -} - -bool LLFloaterIMSessionTab::isTranslationOn(const LLSD& userdata) -{ - return gSavedSettings.getBOOL("TranslateChat"); -} - void LLFloaterIMSessionTab::hideOrShowTitle() { const LLFloater::Params& default_params = LLFloater::getDefaultParams(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 05da0f98bc..0fa99a46be 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -109,12 +109,8 @@ protected: // bool onIMShowModesMenuItemCheck(const LLSD& userdata); bool onIMShowModesMenuItemEnable(const LLSD& userdata); - bool isTranslatingEnabled(const LLSD& userdata); - bool isTranslationOn(const LLSD& userdata); static void onSlide(LLFloaterIMSessionTab *self); - void toggleTranslation(const LLSD& userdata); - // refresh a visual state of the Call button void updateCallBtnState(bool callIsActive); diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml index f2a8b39b04..b0adca0e0e 100644 --- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -45,22 +45,5 @@ - - - - - - - - - - - + diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml index 2f2bafb95d..7ea87ee05c 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_view.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -89,4 +89,24 @@ function="Avatar.EnableItem" parameter="conversation_log" /> + + + + + + + + + + -- cgit v1.2.3 From dc19930f1586dcc879a8e9c1653be8f1b47e4795 Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Mon, 21 Jan 2013 18:24:59 +0200 Subject: CHUI-655, CHUI-648 ADD FIX Conversation is not opened while first click on message from object; "Nearby Chat" dialog does not open while first attempt when pressing Ctrl+H keyboard shortcut : Fixed forced change visibility. --- indra/newview/llfloaterimcontainer.cpp | 4 +++- indra/newview/llfloaterimsessiontab.cpp | 11 +++++++---- indra/newview/llfloaterimsessiontab.h | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f73db6b166..565063a0ea 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -431,7 +431,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event) return false; } LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance("nearby_chat")) : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); + LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ? + (LLFloaterIMSessionTab*)(LLFloaterReg::findTypedInstance("nearby_chat")) + : (LLFloaterIMSessionTab*)(LLFloaterIMSession::findInstance(session_id))); if (type == "remove_participant") { diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0cdfde3975..37404ab716 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -60,6 +60,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mInputEditorTopPad(0) , mRefreshTimer(new LLTimer()) , mIsHostAttached(false) + , mHasVisibleBeenInitialized(false) { setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); @@ -120,12 +121,14 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid void LLFloaterIMSessionTab::setVisible(BOOL visible) { - LLTransientDockableFloater::setVisible(visible); - - if(visible) + if(visible && !mHasVisibleBeenInitialized) { - LLFloaterIMSessionTab::addToHost(mSessionID); + mHasVisibleBeenInitialized = true; + LLFloaterReg::getTypedInstance("im_container")->setVisible(true); + LLFloaterIMSessionTab::addToHost(mSessionID); } + + LLTransientDockableFloater::setVisible(visible); } /*virtual*/ diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 0fa99a46be..beaffc14a6 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -182,6 +182,7 @@ private: bool checkIfTornOff(); bool mIsHostAttached; + bool mHasVisibleBeenInitialized; LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. }; -- cgit v1.2.3 From b40fad02de170b5da179cacc22f32f5f25ffd7cb Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 22 Jan 2013 09:19:23 -0500 Subject: Add debug level logging for Avatar by default. Will need to turn this off before general release, but will give us better debugging info during testing --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 64122bbb6c..1259039010 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - -- cgit v1.2.3 From 9e6677ffc29b779f7b47228cf96c5bcdc867669c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Tue, 22 Jan 2013 17:53:18 +0200 Subject: CHUI-692 FIXED Arrow keys will move avatar while IM container, nearby chat or IM session floater is in focus. --- indra/newview/llviewerwindow.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2d5634a41d..36ddf26c82 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2503,22 +2503,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) return TRUE; } - LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); + LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); + std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); - // Traverses up the hierarchy if( keyboard_focus ) { - if (nearby_chat) - { - LLChatEntry* chat_editor = nearby_chat->getChatBox(); - - // arrow keys move avatar while chatting hack - if (chat_editor && chat_editor->hasFocus()) + if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) { - // If text field is empty, there's no point in trying to move - // cursor with arrow keys, so allow movement - if (chat_editor->getText().empty() - || gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) + if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) { // let Control-Up and Control-Down through for chat line history, if (!(key == KEY_UP && mask == MASK_CONTROL) @@ -2540,7 +2532,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) break; } } - } } } @@ -2575,6 +2566,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) { // Initialize nearby chat if it's missing + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (!nearby_chat) { LLSD name("im_container"); -- cgit v1.2.3 From e378effca36a0a6efd6036586c3259ba5367b012 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 22 Jan 2013 21:47:35 -0500 Subject: Added cof version information to DebugAvatarAppearanceMessage output --- indra/newview/llappearancemgr.cpp | 18 +++++++++++++++++- indra/newview/llappearancemgr.h | 7 +++++++ indra/newview/llvoavatar.cpp | 18 ++++++++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2b1e78c899..e7fa56466d 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1184,6 +1184,21 @@ S32 LLAppearanceMgr::getCOFVersion() const } } +S32 LLAppearanceMgr::getLastUpdateRequestCOFVersion() const +{ + return mLastUpdateRequestCOFVersion; +} + +S32 LLAppearanceMgr::getLastAppearanceUpdateCOFVersion() const +{ + return mLastAppearanceUpdateCOFVersion; +} + +void LLAppearanceMgr::setLastAppearanceUpdateCOFVersion(S32 new_val) +{ + mLastAppearanceUpdateCOFVersion = new_val; +} + const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() { const LLUUID& current_outfit_cat = getCOF(); @@ -3293,7 +3308,8 @@ LLAppearanceMgr::LLAppearanceMgr(): mOutfitIsDirty(false), mOutfitLocked(false), mIsInUpdateAppearanceFromCOF(false), - mLastUpdateRequestCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) + mLastUpdateRequestCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), + mLastAppearanceUpdateCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index bb4c9ee5a2..1a1ca1ca7d 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -94,7 +94,14 @@ public: const LLUUID getCOF() const; S32 getCOFVersion() const; + // COF version of last viewer-initiated appearance update request. S32 mLastUpdateRequestCOFVersion; + S32 getLastUpdateRequestCOFVersion() const; + + // COF version of last appearance message received for self av. + S32 mLastAppearanceUpdateCOFVersion; + S32 getLastAppearanceUpdateCOFVersion() const; + void setLastAppearanceUpdateCOFVersion(S32 new_val); // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 54bb755ad5..83667c8c55 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2890,11 +2890,23 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); - addDebugText(llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + S32 curr_cof_version = -1; + S32 last_request_cof_version = -1; + S32 last_received_cof_version = -1; + if (isSelf()) + { + curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); + last_request_cof_version = LLAppearanceMgr::instance().getLastUpdateRequestCOFVersion(); + last_received_cof_version = LLAppearanceMgr::instance().getLastAppearanceUpdateCOFVersion(); + } + + addDebugText(llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d - cof: %d req: %d rcv:%d", all_local_downloaded ? "L" : "l", all_baked_downloaded ? "B" : "b", mUseLocalAppearance, mIsEditingAppearance, - mUseServerBakes, central_bake_version)); + mUseServerBakes, central_bake_version, + curr_cof_version, last_request_cof_version, last_received_cof_version + )); } if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) { @@ -6613,6 +6625,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) << " last_update_request_cof_version " << last_update_request_cof_version << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << llendl; + LLAppearanceMgr::instance().setLastAppearanceUpdateCOFVersion(this_update_cof_version); + if (getRegion() && (getRegion()->getCentralBakeVersion()==0)) { llwarns << avString() << "Received AvatarAppearance message for self in non-server-bake region" << llendl; -- cgit v1.2.3 From 651f230500646dfcd695a9caa0650f81fa29b9bf Mon Sep 17 00:00:00 2001 From: mberezhnoy Date: Wed, 23 Jan 2013 10:23:16 +0200 Subject: CHUI-678 (Voice indicators not shown for participants in torn off conference conversations) --- indra/newview/llconversationview.cpp | 32 ++++++++++++++++++++++++++-- indra/newview/llconversationview.h | 4 ++++ indra/newview/llspeakingindicatormanager.cpp | 13 ++--------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 903dd2a407..bdd5dfc51a 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -82,6 +82,7 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes mVoiceClientObserver(NULL), mCollapsedMode(false), mHasArrow(true), + mIsInActiveVoiceChannel(false), mFlashStateOn(false), mFlashStarted(false) { @@ -178,6 +179,7 @@ BOOL LLConversationViewSession::postBuild() LLIconCtrl* icon = mItemPanel->getChild("nearby_chat_icon"); icon->setVisible(true); mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); + mIsInActiveVoiceChannel = true; if(LLVoiceClient::instanceExists()) { LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); @@ -232,6 +234,8 @@ void LLConversationViewSession::draw() (*iit)->setVisible(draw_children); } + refresh(); + LLView::draw(); } @@ -351,6 +355,25 @@ void LLConversationViewSession::refresh() // Update all speaking indicators LLSpeakingIndicatorManager::updateSpeakingIndicators(); + + // we should show indicator for specified voice session only if this is current channel. EXT-5562. + if (!mIsInActiveVoiceChannel) + { + if (mSpeakingIndicator) + { + mSpeakingIndicator->setVisible(false); + } + LLConversationViewParticipant* participant = NULL; + items_t::const_iterator iter; + for (iter = getItemsBegin(); iter != getItemsEnd(); iter++) + { + participant = dynamic_cast(*iter); + if (participant) + { + participant->hideSpeakingIndicator(); + } + } + } // Do the regular upstream refresh LLFolderViewFolder::refresh(); @@ -362,8 +385,8 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi if (vmi) { - bool is_active = vmi->getUUID() == session_id; - mCallIconLayoutPanel->setVisible(is_active); + mIsInActiveVoiceChannel = vmi->getUUID() == session_id; + mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel); } } @@ -623,5 +646,10 @@ LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildInde return child_view; } +void LLConversationViewParticipant::hideSpeakingIndicator() +{ + mSpeakingIndicator->setVisible(false); +} + // EOF diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 5f6acfb9ab..f2fa2fb042 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -102,6 +102,8 @@ private: bool mCollapsedMode; bool mHasArrow; + bool mIsInActiveVoiceChannel; + LLVoiceClientStatusObserver* mVoiceClientObserver; boost::signals2::connection mActiveVoiceChannelConnection; @@ -137,6 +139,8 @@ public: /*virtual*/ S32 getLabelXPos(); + void hideSpeakingIndicator(); + protected: friend class LLUICtrlFactory; LLConversationViewParticipant( const Params& p ); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 76da7d1aee..07e9371124 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -237,18 +237,9 @@ void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& spea { was_found = true; LLSpeakingIndicator* indicator = (*it_indicator).second; + was_switched_on = was_switched_on || switch_on; - BOOL switch_current_on = switch_on; - - // we should show indicator for specified voice session only if this is current channel. EXT-5562. - if (switch_current_on) - { - switch_current_on = indicator->getTargetSessionID() == session_id; - LL_DEBUGS("SpeakingIndicator") << "Session: " << session_id << ", target: " << indicator->getTargetSessionID() << ", the same? = " << switch_current_on << LL_ENDL; - } - was_switched_on = was_switched_on || switch_current_on; - - indicator->switchIndicator(switch_current_on); + indicator->switchIndicator(switch_on); } if (was_found) -- cgit v1.2.3 From e6000d5930dd646bb15951336670bab4950515d8 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 23 Jan 2013 14:32:18 +0200 Subject: CHUI-424 FIXED Args for appendMessage() are added to respect Compact/Expanded mode --- indra/newview/llfloaterconversationpreview.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index c93181c0a1..48e0caa0ce 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -152,7 +152,13 @@ void LLFloaterConversationPreview::showHistory() chat.mSourceType = LLFloaterIMNearbyChat::isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT; } - mChatHistory->appendMessage(chat); + LLSD chat_args; + chat_args["use_plain_text_chat_history"] = + gSavedSettings.getBOOL("PlainTextChatHistory"); + chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); + chat_args["show_names_for_p2p_conv"] = gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + + mChatHistory->appendMessage(chat,chat_args); } } -- cgit v1.2.3 From d56009af85cd3807dbaaf23e4f4ce9539a637602 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 23 Jan 2013 11:04:23 -0500 Subject: fixes and updates to DebugAvatarAppearanceMessage status line --- indra/newview/llvoavatar.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 83667c8c55..6aad3c8918 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2890,23 +2890,20 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); - S32 curr_cof_version = -1; - S32 last_request_cof_version = -1; - S32 last_received_cof_version = -1; + std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + all_local_downloaded ? "L" : "l", + all_baked_downloaded ? "B" : "b", + mUseLocalAppearance, mIsEditingAppearance, + mUseServerBakes, central_bake_version); if (isSelf()) { - curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); - last_request_cof_version = LLAppearanceMgr::instance().getLastUpdateRequestCOFVersion(); - last_received_cof_version = LLAppearanceMgr::instance().getLastAppearanceUpdateCOFVersion(); + S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); + S32 last_request_cof_version = LLAppearanceMgr::instance().getLastUpdateRequestCOFVersion(); + S32 last_received_cof_version = LLAppearanceMgr::instance().getLastAppearanceUpdateCOFVersion(); + debug_line += llformat(" - cof: %d req: %d rcv:%d", + curr_cof_version, last_request_cof_version, last_received_cof_version); } - - addDebugText(llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d - cof: %d req: %d rcv:%d", - all_local_downloaded ? "L" : "l", - all_baked_downloaded ? "B" : "b", - mUseLocalAppearance, mIsEditingAppearance, - mUseServerBakes, central_bake_version, - curr_cof_version, last_request_cof_version, last_received_cof_version - )); + addDebugText(debug_line); } if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) { @@ -4040,7 +4037,7 @@ bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() { std::set baked_ids; - collectLocalTextureUUIDs(baked_ids); + collectBakedTextureUUIDs(baked_ids); return allTexturesCompletelyDownloaded(baked_ids); } -- cgit v1.2.3 From d0204ab367f5ceb5eab89e2273b897975acbfe5a Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 23 Jan 2013 09:51:17 -0800 Subject: CHUI-687: Problem: User sees inventory offer notifications for deleted items when logging in from do not disturb mode. Resolution: If an item that is deletes has a DND notification saved, then remove that notification so that it doesn't appear onec the user exists DND mode. --- indra/llui/llfolderview.cpp | 6 +++++- indra/llui/llfolderview.h | 3 ++- .../newview/lldonotdisturbnotificationstorage.cpp | 22 +++++++++++++--------- indra/newview/lldonotdisturbnotificationstorage.h | 6 +++++- indra/newview/llfloaterimcontainer.cpp | 2 +- indra/newview/llimview.cpp | 2 +- indra/newview/llinventoryfunctions.cpp | 22 ++++++++++++++++++++++ indra/newview/llinventoryfunctions.h | 1 + 8 files changed, 50 insertions(+), 14 deletions(-) diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 324142f6c3..7c1ca017d7 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -399,6 +399,10 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) return NULL; } +LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) +{ + return mSelectedItems; +} // Record the selected item and pass it down the hierachy. BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -752,8 +756,8 @@ void LLFolderView::removeSelectedItems() { // change selection on successful delete setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel->hasFocus()); - } } + } arrangeAll(); } else if (count > 1) diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index a6e0a3b4c0..05b2abb9d3 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -101,6 +101,7 @@ public: }; friend class LLFolderViewScrollContainer; + typedef std::deque selected_items_t; LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -138,6 +139,7 @@ public: // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); + selected_items_t& getSelectedItems( void ); // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, @@ -261,7 +263,6 @@ protected: protected: LLHandle mPopupMenuHandle; - typedef std::deque selected_items_t; selected_items_t mSelectedItems; BOOL mKeyboardSelection; BOOL mAllowMultiSelect; diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 824ff67972..abceb5c10d 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -43,7 +43,8 @@ #include "lluuid.h" static const F32 DND_TIMER = 3.0; -const std::string toastName = "IMToast"; +const char * LLDoNotDisturbNotificationStorage::toastName = "IMToast"; +const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem"; LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) { @@ -72,6 +73,8 @@ LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) , mDirty(false) { + nameToPayloadParameterMap[toastName] = "SESSION_ID"; + nameToPayloadParameterMap[offerName] = "object_id"; } LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() @@ -234,15 +237,16 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan return channelPtr; } -void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id) +void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, const LLUUID& id) { LLNotifications& instance = LLNotifications::instance(); LLNotificationChannelPtr channelPtr = getCommunicationChannel(); LLCommunicationChannel *commChannel = dynamic_cast(channelPtr.get()); LLNotificationPtr notification; - LLSD substitutions; - LLUUID notificationSessionID; + LLSD payload; + LLUUID notificationObjectID; std::string notificationName; + std::string payloadVariable = nameToPayloadParameterMap[name]; LLCommunicationChannel::history_list_t::iterator it; std::vector itemsToRemove; @@ -252,18 +256,18 @@ void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& sessi ++it) { notification = it->second; - substitutions = notification->getSubstitutions(); - notificationSessionID = substitutions["SESSION_ID"].asUUID(); + payload = notification->getPayload(); + notificationObjectID = payload[payloadVariable].asUUID(); notificationName = notification->getName(); - if(notificationName == toastName - && session_id == notificationSessionID) + if(notificationName == name + && id == notificationObjectID) { itemsToRemove.push_back(it); } } - + //Remove the notifications if(itemsToRemove.size()) { diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index fd7cc7ee82..6e68b0d1be 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -49,6 +49,9 @@ class LLDoNotDisturbNotificationStorage : public LLSingleton nameToPayloadParameterMap; }; #endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index f73db6b166..6e9f7a380f 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1316,7 +1316,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal if(gAgent.isDoNotDisturb() && session_id.notNull()) { - LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d0a8dfc0c8..cb03c1d234 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -144,7 +144,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, args["FROM"] = av_name.getCompleteName(); args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); + LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID())); } void on_new_message(const LLSD& msg) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 6474d56414..7f9474ae70 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -46,6 +46,7 @@ #include "llappearancemgr.h" #include "llappviewer.h" #include "llclipboard.h" +#include "lldonotdisturbnotificationstorage.h" #include "llfloaterinventory.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" @@ -1132,11 +1133,32 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } } +void LLInventoryAction::removeItemFromDND(LLFolderView* root) +{ + //Get selected items + LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); + LLFolderViewModelItemInventory * viewModel = NULL; + + //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification + //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. + for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + viewModel = dynamic_cast((*it)->getViewModelItem()); + + if(viewModel && viewModel->getUUID().notNull()) + { + //Will remove the item offer notification + LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + } + } +} + void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { + removeItemFromDND(root); root->removeSelectedItems(); } } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 11fc17ce9b..f1066a4dc9 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -433,6 +433,7 @@ struct LLInventoryAction static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root); + static void removeItemFromDND(LLFolderView* root); }; -- cgit v1.2.3 From 6bb1c88db2b329665d547eb86d083a062732a8dd Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 23 Jan 2013 10:13:20 -0800 Subject: CHUI-480 : Fixed : Fetch group membership when starting group chat and populate speakers list --- indra/newview/llspeakers.cpp | 51 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 88f29d7587..a90d9111cb 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llappviewer.h" #include "llimview.h" +#include "llgroupmgr.h" #include "llsdutil.h" #include "lluicolortable.h" #include "llviewerobjectlist.h" @@ -321,7 +322,11 @@ LLSpeakerMgr::~LLSpeakerMgr() LLPointer LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) { - if (id.isNull()) return NULL; + LLUUID session_id = getSessionID(); + if (id.isNull() || (id == session_id)) + { + return NULL; + } LLPointer speakerp; if (mSpeakers.find(id) == mSpeakers.end()) @@ -527,22 +532,52 @@ void LLSpeakerMgr::updateSpeakerList() LLUUID session_id = getSessionID(); if ((mSpeakers.size() == 0) && (!session_id.isNull())) { - // If the list is empty, we update it with whatever was used to initiate the call so that it doesn't stay empty too long. + // If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long. // *TODO: Fix the server side code that sometimes forgets to send back the list of agents after a chat started // (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply) LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) + if (session->isGroupSessionType()) + { + // For groups, we need to hit the group manager + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); + if (!gdatap) + { + // Request the data the first time around + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); + } + else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) + { + LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); + while (member_it != gdatap->mMembers.end()) + { + LLGroupMemberData* member = member_it->second; + // Add only the members who are online + if (member->getOnlineStatus() == "Online") + { + setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } + ++member_it; + } + // Always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } + } + else { - // Add buddies if they are on line, add any other avatar. - if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) + // For all other types (ad-hoc, P2P, avaline), we use the initial targets list + for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { - setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + // Add buddies if they are on line, add any other avatar. + if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it)) + { + setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + } } + // Always add the current agent (it has to be there no matter what...) + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } } - // Finally, always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) -- cgit v1.2.3 From 0911dafd81b8360235eb6f6b85fac7153a5d4a02 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 23 Jan 2013 11:39:33 -0800 Subject: CHUI-687: post code review changes. Now upon deletion of an item, DND mode must be enabled in order to remove a notification from the DND history. --- .../newview/lldonotdisturbnotificationstorage.cpp | 2 +- indra/newview/llinventoryfunctions.cpp | 27 +++++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index abceb5c10d..15c42e8285 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -260,7 +260,7 @@ void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, co notificationObjectID = payload[payloadVariable].asUUID(); notificationName = notification->getName(); - if(notificationName == name + if((notificationName == name) && id == notificationObjectID) { itemsToRemove.push_back(it); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 7f9474ae70..ad0a730dd1 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1135,20 +1135,23 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root void LLInventoryAction::removeItemFromDND(LLFolderView* root) { - //Get selected items - LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); - LLFolderViewModelItemInventory * viewModel = NULL; - - //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification - //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. - for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + if(gAgent.isDoNotDisturb()) { - viewModel = dynamic_cast((*it)->getViewModelItem()); + //Get selected items + LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); + LLFolderViewModelItemInventory * viewModel = NULL; - if(viewModel && viewModel->getUUID().notNull()) + //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification + //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. + for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) { - //Will remove the item offer notification - LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + viewModel = dynamic_cast((*it)->getViewModelItem()); + + if(viewModel && viewModel->getUUID().notNull()) + { + //Will remove the item offer notification + LLDoNotDisturbNotificationStorage::instance().removeNotification(LLDoNotDisturbNotificationStorage::offerName, viewModel->getUUID()); + } } } } @@ -1158,6 +1161,8 @@ void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, co S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { + //Need to remove item from DND before item is removed from root folder view + //because once removed from root folder view the item is no longer a selected item removeItemFromDND(root); root->removeSelectedItems(); } -- cgit v1.2.3 From 46a74c4e01e19c07b5ee966ebe9882c4209dc89c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 23 Jan 2013 17:45:25 -0800 Subject: CHUI-480 : Fixed : Flagged when local update is made and prevent doing it multiple times, allow group to graw by 1 (me) then the rest (prevent having group remaining hidden). --- indra/newview/llspeakers.cpp | 34 +++++++++++++++++++++------------- indra/newview/llspeakers.h | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index a90d9111cb..a2d8874cea 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -306,9 +306,10 @@ private: // LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : - mVoiceChannel(channelp) -, mVoiceModerated(false) -, mModerateModeHandledFirstTime(false) + mVoiceChannel(channelp), + mVoiceModerated(false), + mModerateModeHandledFirstTime(false), + mSpeakerListUpdated(false) { static LLUICachedControl remove_delay ("SpeakerParticipantRemoveDelay", 10.0); @@ -530,15 +531,16 @@ void LLSpeakerMgr::updateSpeakerList() { // If not, check if the list is empty, except if it's Nearby Chat (session_id NULL). LLUUID session_id = getSessionID(); - if ((mSpeakers.size() == 0) && (!session_id.isNull())) + if (!session_id.isNull() && !mSpeakerListUpdated) { // If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long. - // *TODO: Fix the server side code that sometimes forgets to send back the list of agents after a chat started + // *TODO: Fix the server side code that sometimes forgets to send back the list of participants after a chat started. // (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply) LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); - if (session->isGroupSessionType()) + if (session->isGroupSessionType() && (mSpeakers.size() <= 1)) { - // For groups, we need to hit the group manager + // For groups, we need to hit the group manager. + // Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); if (!gdatap) { @@ -547,6 +549,7 @@ void LLSpeakerMgr::updateSpeakerList() } else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) { + // Add group members when we get the complete list (note: can take a while before we get that list) LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); while (member_it != gdatap->mMembers.end()) { @@ -558,13 +561,12 @@ void LLSpeakerMgr::updateSpeakerList() } ++member_it; } - // Always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + mSpeakerListUpdated = true; } } - else + else if (mSpeakers.size() == 0) { - // For all other types (ad-hoc, P2P, avaline), we use the initial targets list + // For all other session type (ad-hoc, P2P, avaline), we use the initial participants targets list for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { // Add buddies if they are on line, add any other avatar. @@ -573,11 +575,17 @@ void LLSpeakerMgr::updateSpeakerList() setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } } - // Always add the current agent (it has to be there no matter what...) - setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); + mSpeakerListUpdated = true; + } + else + { + // The list has been updated the normal way (i.e. by a ChatterBoxSessionAgentListUpdates received from the server) + mSpeakerListUpdated = true; } } } + // Always add the current agent (it has to be there...). Will do nothing if already there. + setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); } void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 7d518fe07b..5f5095097e 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -263,6 +263,7 @@ protected: typedef std::map > speaker_map_t; speaker_map_t mSpeakers; + bool mSpeakerListUpdated; speaker_list_t mSpeakersSorted; LLFrameTimer mSpeechTimer; -- cgit v1.2.3 From a6c4d127dd6ad66f9953344387e100bcff000ce5 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 25 Jan 2013 14:33:44 +0200 Subject: CHUI-697 FIXED We don't need to update form for Inventory offer notification --- indra/newview/llviewermessage.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d235ba5f96..8489e92d15 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1649,12 +1649,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& delete this; } - if (notification_ptr != NULL) - { - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); - } - return false; } -- cgit v1.2.3 From daa9db305a5ae2c0c5b0c2425d6482de6dee7b2c Mon Sep 17 00:00:00 2001 From: AlexanderP ProductEngine Date: Wed, 23 Jan 2013 19:47:01 +0200 Subject: CHUI-695 Viewer crashes after attempt to accept a friendship in IM: remove an infinity loop of reshape() --- indra/newview/lltoastnotifypanel.cpp | 6 ++---- indra/newview/lltoastpanel.cpp | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 268b68b539..0aab514531 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -537,11 +537,9 @@ LLIMToastNotifyPanel::~LLIMToastNotifyPanel() } void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) - { - LLToastPanel::reshape(width, height, called_from_parent); - +{ snapToMessageHeight(mTextBox, MAX_LENGTH); - } +} void LLIMToastNotifyPanel::compactButtons() { diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 187aee207c..54d3912136 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -81,7 +81,9 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); heightDelta = newTextHeight - oldTextHeight; - S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); + S32 new_panel_height = llmin( + llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT), + maxTextHeight); //reshape the panel with new height if (new_panel_height != getRect().getHeight()) -- cgit v1.2.3 From 977d318ac8ccb756bb90a8572f01bc6825b5d0a3 Mon Sep 17 00:00:00 2001 From: Cho Date: Wed, 23 Jan 2013 20:22:28 +0000 Subject: CHUI-291 FIX New auto-replace feature does not work with chui text input boxes in conversation floater Moved autoreplace hooks from LLLineEditor to LLTextEditor, and modified LLAutoReplace accordingly --- indra/llui/lllineeditor.cpp | 9 +----- indra/llui/lllineeditor.h | 3 -- indra/llui/lltexteditor.cpp | 10 ++++++- indra/llui/lltexteditor.h | 5 ++++ indra/newview/llautoreplace.cpp | 50 ++++++++++++-------------------- indra/newview/llautoreplace.h | 51 +++++++++++++++------------------ indra/newview/llfloaterimnearbychat.cpp | 2 ++ indra/newview/llfloaterimsession.cpp | 6 ---- 8 files changed, 58 insertions(+), 78 deletions(-) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 48d49af588..2e64be89fa 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -157,8 +157,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mHighlightColor(p.highlight_color()), mPreeditBgColor(p.preedit_bg_color()), mGLFont(p.font), - mContextMenuHandle(), - mAutoreplaceCallback() + mContextMenuHandle() { llassert( mMaxLengthBytes > 0 ); @@ -971,12 +970,6 @@ void LLLineEditor::addChar(const llwchar uni_char) LLUI::reportBadKeystroke(); } - if (!mReadOnly && mAutoreplaceCallback != NULL) - { - // call callback - mAutoreplaceCallback(mText, mCursorPos); - } - getWindow()->hideCursorUntilMouseMove(); } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 71dd53f608..40f931ecc1 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -189,9 +189,6 @@ public: virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - typedef boost::function autoreplace_callback_t; - autoreplace_callback_t mAutoreplaceCallback; - void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index d42d6473ed..d297e54f2f 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -246,7 +246,8 @@ LLTextEditor::Params::Params() } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : - LLTextBase(p), + LLTextBase(p), + mAutoreplaceCallback(), mBaseDocIsPristine(TRUE), mPristineCmd( NULL ), mLastCmd( NULL ), @@ -1097,7 +1098,14 @@ void LLTextEditor::addChar(llwchar wc) } setCursorPos(mCursorPos + addChar( mCursorPos, wc )); + + if (!mReadOnly && mAutoreplaceCallback != NULL) + { + // call callback + mAutoreplaceCallback(getViewModel()->getEditableDisplay(), mCursorPos); + } } + void LLTextEditor::addLineBreakChar() { if( !getEnabled() ) diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index f8f636b876..ae5a983b60 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -157,6 +157,11 @@ public: BOOL isPristine() const; BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; } + // Autoreplace (formerly part of LLLineEditor) + typedef boost::function autoreplace_callback_t; + autoreplace_callback_t mAutoreplaceCallback; + void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } + // // Text manipulation // diff --git a/indra/newview/llautoreplace.cpp b/indra/newview/llautoreplace.cpp index d71cf290d6..94773e312c 100644 --- a/indra/newview/llautoreplace.cpp +++ b/indra/newview/llautoreplace.cpp @@ -30,29 +30,17 @@ #include "llviewercontrol.h" #include "llnotificationsutil.h" -LLAutoReplace* LLAutoReplace::sInstance; - const char* LLAutoReplace::SETTINGS_FILE_NAME = "autoreplace.xml"; -LLAutoReplace::LLAutoReplace() -{ -} - -LLAutoReplace::~LLAutoReplace() -{ - sInstance = NULL; -} - -void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) +void LLAutoReplace::autoreplaceCallback(LLWString& inputText, S32& cursorPos) { static LLCachedControl perform_autoreplace(gSavedSettings, "AutoReplace"); if(perform_autoreplace) { S32 wordEnd = cursorPos-1; - LLWString text = inputText.getWString(); - bool atSpace = (text[wordEnd] == ' '); - bool haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + bool atSpace = (inputText[wordEnd] == ' '); + bool haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); if (atSpace || haveWord) { @@ -60,7 +48,7 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) { // find out if this space immediately follows a word wordEnd--; - haveWord = (LLWStringUtil::isPartOfWord(text[wordEnd])); + haveWord = (LLWStringUtil::isPartOfWord(inputText[wordEnd])); } if (haveWord) { @@ -68,14 +56,14 @@ void LLAutoReplace::autoreplaceCallback(LLUIString& inputText, S32& cursorPos) std::string word; S32 wordStart = wordEnd; for ( S32 backOne = wordStart - 1; - backOne >= 0 && LLWStringUtil::isPartOfWord(text[backOne]); + backOne >= 0 && LLWStringUtil::isPartOfWord(inputText[backOne]); backOne-- ) { wordStart--; // walk wordStart back to the beginning of the word } LL_DEBUGS("AutoReplace")<<"wordStart: "<loadFromSettings(); - } - return sInstance; -} - std::string LLAutoReplace::getUserSettingsFileName() { std::string path=gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); @@ -147,6 +124,15 @@ void LLAutoReplace::setSettings(const LLAutoReplaceSettings& newSettings) saveToUserSettings(); } +LLAutoReplace::LLAutoReplace() +{ +} + +void LLAutoReplace::initSingleton() +{ + loadFromSettings(); +} + void LLAutoReplace::loadFromSettings() { std::string filename=getUserSettingsFileName(); @@ -220,7 +206,7 @@ void LLAutoReplace::saveToUserSettings() std::string filename=getUserSettingsFileName(); llofstream file; file.open(filename.c_str()); - LLSDSerialize::toPrettyXML(mSettings.getAsLLSD(), file); + LLSDSerialize::toPrettyXML(mSettings.asLLSD(), file); file.close(); LL_INFOS("AutoReplace") << "settings saved to '" << filename << "'" << LL_ENDL; } @@ -801,7 +787,7 @@ LLSD LLAutoReplaceSettings::getExampleLLSD() return example; } -const LLSD& LLAutoReplaceSettings::getAsLLSD() +const LLSD& LLAutoReplaceSettings::asLLSD() { return mLists; } diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index f720cc4eda..bbb86294bc 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -132,7 +132,7 @@ class LLAutoReplaceSettings LLSD getExampleLLSD(); /// Get the actual settings as LLSD - const LLSD& getAsLLSD(); + const LLSD& asLLSD(); ///< @note for use only in AutoReplace::saveToUserSettings private: @@ -190,42 +190,37 @@ class LLAutoReplaceSettings */ class LLAutoReplace : public LLSingleton { - public: - LLAutoReplace(); - ~LLAutoReplace(); - - /// @return a pointer to the active instance - static LLAutoReplace* getInstance(); +public: + /// Callback that provides the hook for use in text entry methods + void autoreplaceCallback(LLWString& inputText, S32& cursorPos); - /// Callback that provides the hook for use in text entry methods - void autoreplaceCallback(LLUIString& inputText, S32& cursorPos); + /// Get a copy of the current settings + LLAutoReplaceSettings getSettings(); - /// Get a copy of the current settings - LLAutoReplaceSettings getSettings(); + /// Commit new settings after making changes + void setSettings(const LLAutoReplaceSettings& settings); - /// Commit new settings after making changes - void setSettings(const LLAutoReplaceSettings& settings); - - private: - friend class LLSingleton; - static LLAutoReplace* sInstance; ///< the active settings instance +private: + friend class LLSingleton; + LLAutoReplace(); + /*virtual*/ void initSingleton(); - LLAutoReplaceSettings mSettings; ///< configuration information + LLAutoReplaceSettings mSettings; ///< configuration information - /// Read settings from persistent storage - void loadFromSettings(); + /// Read settings from persistent storage + void loadFromSettings(); - /// Make the newSettings active and write them to user storage - void saveToUserSettings(); + /// Make the newSettings active and write them to user storage + void saveToUserSettings(); - /// Compute the user settings file name - std::string getUserSettingsFileName(); + /// Compute the user settings file name + std::string getUserSettingsFileName(); - /// Compute the (read-ony) application settings file name - std::string getAppSettingsFileName(); + /// Compute the (read-ony) application settings file name + std::string getAppSettingsFileName(); - /// basename for the settings files - static const char* SETTINGS_FILE_NAME; + /// basename for the settings files + static const char* SETTINGS_FILE_NAME; }; #endif /* LLAUTOREPLACE_H */ diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 797d590e1f..73eb822036 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -66,6 +66,7 @@ #include "llrootview.h" #include "llviewerchat.h" #include "lltranslate.h" +#include "llautoreplace.h" S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; @@ -112,6 +113,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); + mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this)); mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this)); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a09dc1914f..a2c7bacb5d 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -332,13 +332,7 @@ BOOL LLFloaterIMSession::postBuild() BOOL result = LLFloaterIMSessionTab::postBuild(); mInputEditor->setMaxTextLength(1023); - // enable line history support for instant message bar - // XXX stinson TODO : resolve merge by adding autoreplace to text editors -#if 0 - // *TODO Establish LineEditor with autoreplace callback mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -#endif - mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); -- cgit v1.2.3 From 878e31dce2483cea0a1a38f076d4558c04ec9642 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 23 Jan 2013 16:04:08 -0500 Subject: SH-3534 WIP - better encapsulation of mUseServerBakes --- indra/newview/llagent.cpp | 12 +++++------- indra/newview/llvoavatar.cpp | 7 ++++++- indra/newview/llvoavatar.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e15b4d071f..5796c34e25 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4286,12 +4286,6 @@ void LLAgent::requestLeaveGodMode() //----------------------------------------------------------------------------- void LLAgent::sendAgentSetAppearance() { - // FIXME DRANO - problems around new-style appearance in an old-style region. - // - does this get called? - // - need to change mUseServerBakes->FALSE in that case - // - need to call processAvatarAppearance as if server had returned this result? - // gAgentAvatarp->mUseServerBakes = FALSE; - if (gAgentQueryManager.mNumPendingQueries > 0) { return; @@ -4308,6 +4302,10 @@ void LLAgent::sendAgentSetAppearance() if (!isAgentAvatarValid() || (getRegion() && getRegion()->getCentralBakeVersion())) return; + // At this point we have a complete appearance to send and are in a non-baking region. + // DRANO FIXME + //gAgentAvatarp->setIsUsingServerBakes(FALSE); + LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL; //dumpAvatarTEs( "sendAgentSetAppearance()" ); @@ -4408,7 +4406,7 @@ void LLAgent::sendAgentSetAppearance() } } -// llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; + //llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl; sendReliableMessage(); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6aad3c8918..3d58c50eba 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6651,7 +6651,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) return; } - mUseServerBakes = (appearance_version > 0); + setIsUsingServerBakes(appearance_version > 0); applyParsedTEMessage(tec); @@ -7276,6 +7276,11 @@ void LLVOAvatar::bodySizeChanged() } } +BOOL LLVOAvatar::isUsingServerBakes() const +{ + return mUseServerBakes; +} + void LLVOAvatar::setIsUsingServerBakes(BOOL newval) { mUseServerBakes = newval; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 2c64b9695e..c5064e4a52 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -653,7 +653,7 @@ public: // True if this avatar should fetch its baked textures via the new // appearance mechanism. - /*virtual*/ BOOL isUsingServerBakes() const { return mUseServerBakes; } + BOOL isUsingServerBakes() const; void setIsUsingServerBakes(BOOL newval); -- cgit v1.2.3 From 9f5e1d601c86e7036d3ecbae063ea637f0cdc7ca Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 23 Jan 2013 18:31:21 -0500 Subject: SH-3779 WIP - fully parse appearance message before trying to do anything with it --- indra/newview/llvoavatar.cpp | 130 +++++++++++++++++++++++++++++++------------ indra/newview/llvoavatar.h | 2 + 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3d58c50eba..cb9b1aa5cc 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -6574,6 +6574,91 @@ void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, } } +struct LLAppearanceMessageContents +{ + LLAppearanceMessageContents(): + mAppearanceVersion(0), + mCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) + { + } + + LLTEContents mTEContents; + U8 mAppearanceVersion; + S32 mCOFVersion; + // For future use: + //U32 appearance_flags = 0; + std::vector mParams; +}; + +void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& contents) +{ + parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, contents.mTEContents); + + // Parse the AppearanceData field, if any. + if (mesgsys->has(_PREHASH_AppearanceData)) + { + mesgsys->getU8Fast(_PREHASH_AppearanceData, _PREHASH_AppearanceVersion, contents.mAppearanceVersion, 0); + mesgsys->getS32Fast(_PREHASH_AppearanceData, _PREHASH_CofVersion, contents.mCOFVersion, 0); + // For future use: + //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); + } + + // Parse visual params, if any. + S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); + bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing + if( num_blocks > 1 && !drop_visual_params_debug) + { + LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; + + LLVisualParam* param = getFirstVisualParam(); + llassert(param); // if this ever fires, we should do the same as when num_blocks<=1 + if (!param) + { + llwarns << "No visual params!" << llendl; + } + else + { + for( S32 i = 0; i < num_blocks; i++ ) + { + while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + { + param = getNextVisualParam(); + } + + if( !param ) + { + // more visual params supplied than expected - just process what we know about + break; + } + + U8 value; + mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); + F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + contents.mParams.push_back(newWeight); + + param = getNextVisualParam(); + } + } + + const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + if (num_blocks != expected_tweakable_count) + { + llinfos << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << llendl; + } + } + else + { + if (drop_visual_params_debug) + { + llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; + } + else + { + llinfos << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl; + } + } +} + //----------------------------------------------------------------------------- // processAvatarAppearance() //----------------------------------------------------------------------------- @@ -6598,22 +6683,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) ESex old_sex = getSex(); - LLTEContents tec; - parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, tec); + LLAppearanceMessageContents contents; + parseAppearanceMessage(mesgsys, contents); - U8 appearance_version = 0; - S32 this_update_cof_version = LLViewerInventoryCategory::VERSION_UNKNOWN; + U8 appearance_version = contents.mAppearanceVersion; + S32 this_update_cof_version = contents.mCOFVersion; S32 last_update_request_cof_version = LLAppearanceMgr::instance().mLastUpdateRequestCOFVersion; - // For future use: - //U32 appearance_flags = 0; - - if (mesgsys->has(_PREHASH_AppearanceData)) - { - mesgsys->getU8Fast(_PREHASH_AppearanceData, _PREHASH_AppearanceVersion, appearance_version, 0); - mesgsys->getS32Fast(_PREHASH_AppearanceData, _PREHASH_CofVersion, this_update_cof_version, 0); - // For future use: - //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); - } // Only now that we have result of appearance_version can we decide whether to bail out. if( isSelf() ) @@ -6634,7 +6709,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } } - // Check for stale update. if (isSelf() && (appearance_version>0) @@ -6653,7 +6727,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) setIsUsingServerBakes(appearance_version > 0); - applyParsedTEMessage(tec); + applyParsedTEMessage(contents.mTEContents); // prevent the overwriting of valid baked textures with invalid baked textures for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) @@ -6667,7 +6741,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } } - // runway - was // if (!is_first_appearance_message ) // which means it would be called on second appearance message - probably wrong. @@ -6680,9 +6753,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) gPipeline.markGLRebuild(this); // parse visual params - S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); - bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing - if( num_blocks > 1 && !drop_visual_params_debug) + S32 num_blocks = contents.mParams.size(); + if( num_blocks > 1) { LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; BOOL params_changed = FALSE; @@ -6696,7 +6768,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } else { - std::vector params_for_dump; for( S32 i = 0; i < num_blocks; i++ ) { while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT @@ -6710,14 +6781,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) break; } - U8 value; - mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); - F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); - params_for_dump.push_back(newWeight); + F32 newWeight = contents.mParams[i]; if (is_first_appearance_message || (param->getWeight() != newWeight)) { - //llinfos << "Received update for param " << param->getDisplayName() << " at value " << newWeight << llendl; params_changed = TRUE; if(is_first_appearance_message) { @@ -6732,7 +6799,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) param = getNextVisualParam(); } if (enable_verbose_dumps) - dumpAppearanceMsgParams(dump_prefix + "appearance_msg", params_for_dump, tec); + dumpAppearanceMsgParams(dump_prefix + "appearance_msg", contents.mParams, contents.mTEContents); } if (enable_verbose_dumps) { dumpArchetypeXML(dump_prefix + "process_post_set_weights"); } @@ -6764,14 +6831,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { // AvatarAppearance message arrived without visual params LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; - if (drop_visual_params_debug) - { - llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl; - } - else - { - llinfos << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl; - } const F32 LOADING_TIMEOUT_SECONDS = 60.f; // this isn't really a problem if we already have a non-default shape @@ -6802,7 +6861,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) updateMeshTextures(); if (enable_verbose_dumps) dumpArchetypeXML(dump_prefix + "process_end"); -// llinfos << "processAvatarAppearance end " << mID << llendl; } // static diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index c5064e4a52..784b08a782 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -70,6 +70,7 @@ class LLHUDNameTag; class LLHUDEffectSpiral; class LLTexGlobalColor; class LLViewerJoint; +struct LLAppearanceMessageContents; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -635,6 +636,7 @@ protected: **/ public: + void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg); void processAvatarAppearance(LLMessageSystem* mesgsys); void hideSkirt(); void startAppearanceAnimation(); -- cgit v1.2.3 From c3fd7ae17b67568a68ae967cd2d30e20db1f6b6c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Mon, 28 Jan 2013 19:59:13 +0200 Subject: CHUI-708 FIXED Call doToParticipants() only if selected conversation is p2p --- indra/newview/llfloaterimcontainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ff6234fa27..c272e5e391 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1086,7 +1086,10 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, } else { - doToParticipants(command, selectedIDS); + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + doToParticipants(command, selectedIDS); + } } } } -- cgit v1.2.3 From 2ac99f55f9e562e4ff8ebde4cba8270f1048c28d Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 24 Jan 2013 19:56:13 +0200 Subject: CHUI-578 FIXED Move preferences for conversation logs/transcripts to chat tab --- indra/llvfs/lldir.cpp | 13 +- indra/llvfs/lldir.h | 2 + indra/newview/app_settings/settings.xml | 4 +- indra/newview/llconversationlog.cpp | 60 +++-- indra/newview/llconversationlog.h | 11 +- indra/newview/llfloaterconversationlog.cpp | 14 +- indra/newview/llfloaterconversationlog.h | 2 +- indra/newview/llfloaterimcontainer.cpp | 6 +- indra/newview/llfloaterimnearbychat.cpp | 27 +- indra/newview/llfloaterimnearbychat.h | 2 +- indra/newview/llfloaterimsession.cpp | 12 +- indra/newview/llfloaterimsession.h | 2 +- indra/newview/llfloaterimsessiontab.cpp | 6 +- indra/newview/llfloaterimsessiontab.h | 2 +- indra/newview/llfloaterpreference.cpp | 109 +++++--- indra/newview/llfloaterpreference.h | 19 +- indra/newview/llimview.cpp | 37 +-- indra/newview/llimview.h | 2 + indra/newview/lllogchat.cpp | 235 ++++++++++------- indra/newview/lllogchat.h | 15 +- indra/newview/llviewermessage.cpp | 2 +- .../newview/skins/default/xui/en/notifications.xml | 26 ++ .../default/xui/en/panel_preferences_chat.xml | 284 ++++++++++++++------- .../default/xui/en/panel_preferences_privacy.xml | 226 +++++----------- 24 files changed, 641 insertions(+), 477 deletions(-) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 5e5aeefba1..f7bc19574a 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -90,7 +90,8 @@ LLDir::LLDir() mCAFile(""), mTempDir(""), mDirDelimiter("/"), // fallback to forward slash if not overridden - mLanguage("en") + mLanguage("en"), + mUserName("undefined") { } @@ -814,6 +815,11 @@ void LLDir::setChatLogsDir(const std::string &path) } } +void LLDir::updatePerAccountChatLogsDir() +{ + mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName); +} + void LLDir::setPerAccountChatLogsDir(const std::string &username) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -824,13 +830,14 @@ void LLDir::setPerAccountChatLogsDir(const std::string &username) std::string userlower(username); LLStringUtil::toLower(userlower); LLStringUtil::replaceChar(userlower, ' ', '_'); - mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); + + mUserName = userlower; + updatePerAccountChatLogsDir(); } else { llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl; } - } void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 300ff1eef6..95cab65149 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -186,6 +186,7 @@ class LLDir virtual std::string getSkinFolder() const; virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(); virtual void dumpCurrentDirectories(); @@ -243,6 +244,7 @@ protected: std::vector mSearchSkinDirs; std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell + std::string mUserName; // Current user name }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fd4d1df894..dd9a0100c0 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4674,9 +4674,9 @@ Persist 1 Type - Boolean + S32 Value - 1 + 2 LandBrushSize diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index ff1f819d7d..8de041f983 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -28,13 +28,14 @@ #include "llagent.h" #include "llavatarnamecache.h" #include "llconversationlog.h" +#include "llnotificationsutil.h" #include "lltrans.h" const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec -struct Conversation_params +struct ConversationParams { - Conversation_params(time_t time) + ConversationParams(time_t time) : mTime(time), mTimestamp(LLConversation::createTimestamp(time)) {} @@ -53,7 +54,7 @@ struct Conversation_params /* LLConversation implementation */ /************************************************************************/ -LLConversation::LLConversation(const Conversation_params& params) +LLConversation::LLConversation(const ConversationParams& params) : mTime(params.mTime), mTimestamp(params.mTimestamp), mConversationType(params.mConversationType), @@ -188,33 +189,24 @@ void LLConversationLogFriendObserver::changed(U32 mask) LLConversationLog::LLConversationLog() : mAvatarNameCacheConnection() { - LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); - bool is_log_message = false; - bool is_keep_log = false; + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + S32 log_mode = keep_log_ctrlp->getValue(); - if (log_instant_message) + if (log_mode > 0) { - log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_log_message = log_instant_message->getValue().asBoolean(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); + enableLogging(log_mode); } - if (keep_convers_log) - { - keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2)); - is_keep_log = keep_convers_log->getValue().asBoolean(); - } - - enableLogging(is_log_message && is_keep_log); } -void LLConversationLog::enableLogging(bool enable) +void LLConversationLog::enableLogging(S32 log_mode) { - if (enable) + if (log_mode > 0) { loadFromFile(getFileName()); LLIMMgr::instance().addSessionObserver(this); - newMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); + mNewMessageSignalConnection = LLIMModel::instance().addNewMsgCallback(boost::bind(&LLConversationLog::onNewMessageReceived, this, _1)); mFriendObserver = new LLConversationLogFriendObserver; LLAvatarTracker::instance().addObserver(mFriendObserver); @@ -224,7 +216,7 @@ void LLConversationLog::enableLogging(bool enable) saveToFile(getFileName()); LLIMMgr::instance().removeSessionObserver(this); - newMessageSignalConnection.disconnect(); + mNewMessageSignalConnection.disconnect(); LLAvatarTracker::instance().removeObserver(mFriendObserver); mConversations.clear(); } @@ -377,7 +369,7 @@ void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string void LLConversationLog::cache() { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 0) { saveToFile(getFileName()); } @@ -450,9 +442,9 @@ bool LLConversationLog::loadFromFile(const std::string& filename) char part_id_buffer[MAX_STRING]; char conv_id_buffer[MAX_STRING]; char history_file_name[MAX_STRING]; - int has_offline_ims; - int stype; - time_t time; + S32 has_offline_ims; + S32 stype; + S64 time; // before CHUI-348 it was a flag of conversation voice state int prereserved_unused; @@ -462,7 +454,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) part_id_buffer[0] = '\0'; conv_id_buffer[0] = '\0'; - sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|", + sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|", &time, &stype, &prereserved_unused, @@ -472,7 +464,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename) conv_id_buffer, history_file_name); - Conversation_params params(time); + ConversationParams params((time_t)time); params.mConversationType = (SessionType)stype; params.mHasOfflineIMs = has_offline_ims; params.mConversationName = std::string(conv_name_buffer); @@ -530,3 +522,17 @@ void LLConversationLog::onAvatarNameCache(const LLUUID& participant_id, const LL mAvatarNameCacheConnection.disconnect(); updateConversationName(session, av_name.getCompleteName()); } + +void LLConversationLog::onClearLog() +{ + LLNotificationsUtil::add("PreferenceChatClearLog", LLSD(), LLSD(), boost::bind(&LLConversationLog::onClearLogResponse, this, _1, _2)); +} + +void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + mConversations.clear(); + notifyObservers(); + } +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 35462ec3a4..65a18c02e5 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -31,7 +31,7 @@ #include "llimview.h" class LLConversationLogObserver; -struct Conversation_params; +struct ConversationParams; typedef LLIMModel::LLIMSession::SType SessionType; @@ -43,7 +43,7 @@ class LLConversation { public: - LLConversation(const Conversation_params& params); + LLConversation(const ConversationParams& params); LLConversation(const LLIMModel::LLIMSession& session); LLConversation(const LLConversation& conversation); @@ -138,6 +138,9 @@ public: */ void cache(); + void onClearLog(); + void onClearLogResponse(const LLSD& notification, const LLSD& response); + private: LLConversationLog(); @@ -149,7 +152,7 @@ private: } } - void enableLogging(bool enable); + void enableLogging(S32 log_mode); /** * adds conversation to the conversation list and notifies observers @@ -182,7 +185,7 @@ private: LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance - boost::signals2::connection newMessageSignalConnection; + boost::signals2::connection mNewMessageSignalConnection; boost::signals2::connection mAvatarNameCacheConnection; }; diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp index a40a000bab..a44ebcf6ab 100644 --- a/indra/newview/llfloaterconversationlog.cpp +++ b/indra/newview/llfloaterconversationlog.cpp @@ -63,13 +63,9 @@ BOOL LLFloaterConversationLog::postBuild() getChild("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); - LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get(); - if (ctrl) - { - ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); - onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean() - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")); - } + LLControlVariable * keep_log_ctrlp = gSavedSettings.getControl("KeepConversationLogTranscripts").get(); + keep_log_ctrlp->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2)); + onCallLoggingEnabledDisabled(keep_log_ctrlp->getValue()); return LLFloater::postBuild(); } @@ -139,8 +135,8 @@ bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) return false; } -void LLFloaterConversationLog::onCallLoggingEnabledDisabled(bool enabled) +void LLFloaterConversationLog::onCallLoggingEnabledDisabled(S32 log_mode) { - std::string no_items_msg = enabled ? "" : getString("logging_calls_disabled"); + std::string no_items_msg = log_mode > 0 ? "" : getString("logging_calls_disabled"); mConversationLogList->setNoItemsCommentText(no_items_msg); } diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h index 9e79cbd7d8..aa0f480aae 100644 --- a/indra/newview/llfloaterconversationlog.h +++ b/indra/newview/llfloaterconversationlog.h @@ -49,7 +49,7 @@ private: bool isActionEnabled(const LLSD& userdata); bool isActionChecked(const LLSD& userdata); - void onCallLoggingEnabledDisabled(bool enabled); + void onCallLoggingEnabledDisabled(S32 log_mode); LLConversationLogList* mConversationLogList; }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c272e5e391..54e5085490 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -224,7 +224,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed()) { @@ -1142,7 +1142,7 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) if ("conversation_log" == item) { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } //Enable Chat history item for ad-hoc and group conversations @@ -1793,7 +1793,7 @@ void LLFloaterIMContainer::updateSpeakBtnState() bool LLFloaterIMContainer::isConversationLoggingAllowed() { - return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); + return gSavedSettings.getS32("KeepConversationLogTranscripts") > 0; } void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id, bool is_flashes) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 797d590e1f..17d2341b3c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -148,8 +148,14 @@ void LLFloaterIMNearbyChat::refresh() } } -void LLFloaterIMNearbyChat::reloadMessages() +void LLFloaterIMNearbyChat::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + mMessageArchive.clear(); + loadHistory(); + } + mChatHistory->clear(); LLSD do_not_log; @@ -174,11 +180,11 @@ void LLFloaterIMNearbyChat::loadHistory() { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -189,8 +195,8 @@ void LLFloaterIMNearbyChat::loadHistory() LLChat chat; chat.mFromName = from; chat.mFromID = from_id; - chat.mText = msg[IM_TEXT].asString(); - chat.mTimeStr = msg[IM_TIME].asString(); + chat.mText = msg[LL_IM_TEXT].asString(); + chat.mTimeStr = msg[LL_IM_TIME].asString(); chat.mChatStyle = CHAT_STYLE_HISTORY; chat.mSourceType = CHAT_SOURCE_AGENT; @@ -519,20 +525,21 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) } } -void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) { appendMessage(chat, args); if(archive) { mMessageArchive.push_back(chat); - if(mMessageArchive.size()>200) + if(mMessageArchive.size() > 200) + { mMessageArchive.erase(mMessageArchive.begin()); + } } // logging - if (!args["do_not_log"].asBoolean() - && gSavedPerAccountSettings.getBOOL("LogNearbyChat")) + if (!args["do_not_log"].asBoolean() && gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = chat.mFromName; diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index f4213eda5a..14c7d01ecd 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -56,7 +56,7 @@ public: /*virtual*/ void setVisible(BOOL visible); void loadHistory(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); void removeScreenChat(); void show(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index a09dc1914f..07f5515582 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -853,8 +853,18 @@ void LLFloaterIMSession::updateMessages() } } -void LLFloaterIMSession::reloadMessages() +void LLFloaterIMSession::reloadMessages(bool clean_messages/* = false*/) { + if (clean_messages) + { + LLIMModel::LLIMSession * sessionp = LLIMModel::instance().findIMSession(mSessionID); + + if (NULL != sessionp) + { + sessionp->loadHistory(); + } + } + mChatHistory->clear(); mLastMessageIndex = -1; updateMessages(); diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index 2049cedfd7..e7fd6f9ff3 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -86,7 +86,7 @@ public: // get new messages from LLIMModel /*virtual*/ void updateMessages(); - void reloadMessages(); + void reloadMessages(bool clean_messages = false); static void onSendMsg(LLUICtrl*, void*); void sendMsgFromInputEditor(); void sendMsg(const std::string& msg); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 37404ab716..f7c6f19450 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -680,7 +680,7 @@ void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) } // static -void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() +void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* = false*/) { LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); @@ -689,14 +689,14 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate() LLFloaterIMSession* floater = dynamic_cast(*iter); if (floater) { - floater->reloadMessages(); + floater->reloadMessages(clean_messages); } } LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (nearby_chat) { - nearby_chat->reloadMessages(); + nearby_chat->reloadMessages(clean_messages); } } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index beaffc14a6..e90fcbb806 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -53,7 +53,7 @@ public: ~LLFloaterIMSessionTab(); // reload all message with new settings of visual modes - static void processChatHistoryStyleUpdate(); + static void processChatHistoryStyleUpdate(bool clean_messages = false); /** * Returns true if chat is displayed in multi tabbed floater diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3d4a1c44d8..7742e5b3c3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -306,7 +306,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mAvatarDataInitialized(false), mClickActionDirty(false) { - + LLConversationLog::instance().addObserver(this); + //Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); static bool registered_dialog = false; @@ -329,8 +330,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this)); mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this)); mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this)); -// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this)); -// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this)); mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this)); mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); @@ -351,13 +350,16 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) sSkin = gSavedSettings.getString("SkinCurrent"); - mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); + mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this)); gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + + mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); + mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) @@ -425,7 +427,7 @@ void LLFloaterPreference::saveAvatarProperties( void ) BOOL LLFloaterPreference::postBuild() { - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate)); + gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -455,9 +457,24 @@ BOOL LLFloaterPreference::postBuild() gSavedPerAccountSettings.setString("DoNotDisturbModeResponse", LLTrans::getString("DoNotDisturbModeResponseDefault")); } + // set 'enable' property for 'Clear log...' button + changed(); + + // set 'enable' property for 'Delete transcripts...' button + updateDeleteTranscriptsButton(); + + LLLogChat::setSaveHistorySignal(boost::bind(&LLFloaterPreference::onLogChatHistorySaved, this)); + return TRUE; } +void LLFloaterPreference::updateDeleteTranscriptsButton() +{ + std::vector list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); +} + void LLFloaterPreference::onDoNotDisturbResponseChanged() { // set "DoNotDisturbResponseChanged" TRUE if user edited message differs from default, FALSE otherwise @@ -476,6 +493,8 @@ LLFloaterPreference::~LLFloaterPreference() { ctrl_window_size->setCurrentByIndex(i); } + + LLConversationLog::instance().removeObserver(this); } void LLFloaterPreference::draw() @@ -833,12 +852,12 @@ void LLFloaterPreference::onBtnCancel() } // static -void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance("preferences"); if (instance) { - instance->setPersonalInfo(visibility, im_via_email, email); + instance->setPersonalInfo(visibility, im_via_email); } } @@ -1425,10 +1444,21 @@ void LLFloaterPreference::onClickLogPath() return; //Canceled! } - gSavedPerAccountSettings.setString("InstantMessageLogPath", picker.getDirName()); + std::string dir_name = picker.getDirName(); + gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); + + gDirUtilp->setChatLogsDir(dir_name); + gDirUtilp->updatePerAccountChatLogsDir(); + LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); + + // refresh IM floaters with new logs from files from new selected directory + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); } -void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email) +void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email) { mGotPersonalInfo = true; mOriginalIMViaEmail = im_via_email; @@ -1450,32 +1480,14 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im } getChild("online_searchresults")->setEnabled(TRUE); - - getChildView("include_im_in_chat_history")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("friends_online_notify_checkbox")->setEnabled(TRUE); - getChild("online_visibility")->setValue(mOriginalHideOnlineStatus); getChild("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility); getChildView("send_im_to_email")->setEnabled(TRUE); getChild("send_im_to_email")->setValue(im_via_email); - getChildView("log_instant_messages")->setEnabled(TRUE); -// getChildView("log_chat")->setEnabled(TRUE); -// getChildView("log_instant_messages_timestamp")->setEnabled(TRUE); -// getChildView("log_chat_timestamp")->setEnabled(TRUE); - getChildView("log_chat_IM")->setEnabled(TRUE); - getChildView("log_date_timestamp")->setEnabled(TRUE); - getChildView("favorites_on_login_check")->setEnabled(TRUE); - getChildView("log_nearby_chat")->setEnabled(TRUE); - getChildView("log_instant_messages")->setEnabled(TRUE); - getChildView("show_timestamps_check_im")->setEnabled(TRUE); getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case. getChildView("log_path_button")->setEnabled(TRUE); - childEnable("logfile_name_datestamp"); - std::string display_email(email); - getChild("email_address")->setValue(display_email); - } void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) @@ -1566,6 +1578,35 @@ void LLFloaterPreference::onClickActionChange() mClickActionDirty = true; } +void LLFloaterPreference::onDeleteTranscripts() +{ + LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2)); +} + +void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response) +{ + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + { + gDirUtilp->deleteFilesInDir(gDirUtilp->getPerAccountChatLogsDir(), "*." + LL_TRANSCRIPT_FILE_EXTENSION); + + std::vector list_of_transcriptions_file_names; + LLLogChat::getListOfTranscriptFiles(list_of_transcriptions_file_names); + getChild("delete_transcripts")->setEnabled(list_of_transcriptions_file_names.size() > 0); + + LLFloaterIMSessionTab::processChatHistoryStyleUpdate(true); + } +} + +void LLFloaterPreference::onLogChatHistorySaved() +{ + LLButton * delete_transcripts_buttonp = getChild("delete_transcripts"); + + if (!delete_transcripts_buttonp->getEnabled()) + { + delete_transcripts_buttonp->setEnabled(true); + } +} + void LLFloaterPreference::updateClickActionSettings() { const int single_clk_action = getChild("single_click_action_combo")->getValue().asInteger(); @@ -1624,6 +1665,11 @@ void LLFloaterPreference::selectChatPanel() selectPanel("chat"); } +void LLFloaterPreference::changed() +{ + getChild("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); +} + //------------------------------Updater--------------------------------------- static bool handleBandwidthChanged(const LLSD& newvalue) @@ -1717,11 +1763,6 @@ BOOL LLPanelPreference::postBuild() } - if (hasChild("online_visibility") && hasChild("send_im_to_email")) - { - getChild("email_address")->setValue(getString("log_in_to_change") ); - } - //////////////////////PanelPrivacy /////////////////// if (hasChild("media_enabled")) { @@ -1898,7 +1939,7 @@ public: for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) { const std::string setting = it->first->getName(); - if (std::find(mAccountIndependentSettings.begin(), + if (find(mAccountIndependentSettings.begin(), mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) { mSavedValues.erase(it++); @@ -2187,4 +2228,4 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings() otherHttpProxy->selectFirstItem(); } -}; +} diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 37a531e99e..f9f1d52244 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -35,7 +35,9 @@ #include "llfloater.h" #include "llavatarpropertiesprocessor.h" +#include "llconversationlog.h" +class LLConversationLogObserver; class LLPanelPreference; class LLPanelLCD; class LLPanelDebug; @@ -58,7 +60,7 @@ typedef enum // Floater to control preferences (display, audio, bandwidth, general. -class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver +class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver, public LLConversationLogObserver { public: LLFloaterPreference(const LLSD& key); @@ -70,9 +72,11 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void changed(); + /*virtual*/ void changed(const LLUUID& session_id, U32 mask) {}; // static data update, called from message handler - static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email); + static void updateUserInfo(const std::string& visibility, bool im_via_email); // refresh all the graphics preferences menus static void refreshEnabledGraphics(); @@ -134,15 +138,13 @@ public: void setKey(KEY key); void onClickSetMiddleMouse(); void onClickSetSounds(); -// void onClickSkipDialogs(); -// void onClickResetDialogs(); void onClickEnablePopup(); void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); void onClickLogPath(); void enableHistory(); - void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email); + void setPersonalInfo(const std::string& visibility, bool im_via_email); void refreshEnabledState(); void disableUnavailableSettings(); void onCommitWindowedMode(); @@ -166,12 +168,17 @@ public: void onClickSpellChecker(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); - + void onLogChatHistorySaved(); void buildPopupLists(); static void refreshSkin(void* data); void selectPanel(const LLSD& name); private: + + void onDeleteTranscripts(); + void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response); + void updateDeleteTranscriptsButton(); + static std::string sSkin; notifications_map mNotificationOptions; bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user. diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 433ddad35d..37c9ee8c99 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -378,15 +378,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& } buildHistoryFileName(); - - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - std::list chat_history; - - //involves parsing of a chat history - LLLogChat::loadChatHistory(mHistoryFileName, chat_history); - addMessagesFromHistory(chat_history); - } + loadHistory(); // Localizing name of ad-hoc session. STORM-153 // Changing name should happen here- after the history file was created, so that @@ -579,11 +571,11 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& histo { const LLSD& msg = *it; - std::string from = msg[IM_FROM]; + std::string from = msg[LL_IM_FROM]; LLUUID from_id; - if (msg[IM_FROM_ID].isDefined()) + if (msg[LL_IM_FROM_ID].isDefined()) { - from_id = msg[IM_FROM_ID].asUUID(); + from_id = msg[LL_IM_FROM_ID].asUUID(); } else { @@ -592,8 +584,8 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& histo gCacheName->getUUID(legacy_name, from_id); } - std::string timestamp = msg[IM_TIME]; - std::string text = msg[IM_TEXT]; + std::string timestamp = msg[LL_IM_TIME]; + std::string text = msg[LL_IM_TEXT]; addMessage(from, from_id, text, timestamp, true); @@ -617,6 +609,20 @@ void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const } } +void LLIMModel::LLIMSession::loadHistory() +{ + mMsgs.clear(); + + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + { + std::list chat_history; + + //involves parsing of a chat history + LLLogChat::loadChatHistory(mHistoryFileName, chat_history); + addMessagesFromHistory(chat_history); + } +} + LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const { return get_if_there(mId2SessionMap, session_id, @@ -921,8 +927,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { - if (gSavedPerAccountSettings.getBOOL("LogInstantMessages") - && gSavedSettings.getBOOL("KeepConversationLogTranscripts")) + if (gSavedSettings.getS32("KeepConversationLogTranscripts") > 1) { std::string from_name = from; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 8578fa8c06..da6039a3ae 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -101,6 +101,8 @@ public: /** ad-hoc sessions involve sophisticated chat history file naming schemes */ void buildHistoryFileName(); + void loadHistory(); + LLUUID mSessionID; std::string mName; EInstantMessage mType; diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 3692658e9e..545b44ef92 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -58,10 +58,11 @@ const S32 LOG_RECALL_SIZE = 2048; -const std::string IM_TIME("time"); -const std::string IM_TEXT("message"); -const std::string IM_FROM("from"); -const std::string IM_FROM_ID("from_id"); +const std::string LL_IM_TIME("time"); +const std::string LL_IM_TEXT("message"); +const std::string LL_IM_FROM("from"); +const std::string LL_IM_FROM_ID("from_id"); +const std::string LL_TRANSCRIPT_FILE_EXTENSION("ll.txt"); const static std::string IM_SEPARATOR(": "); const static std::string NEW_LINE("\n"); @@ -116,6 +117,15 @@ const static int IDX_TEXT = 3; using namespace boost::posix_time; using namespace boost::gregorian; +void append_to_last_message(std::list& messages, const std::string& line) +{ + if (!messages.size()) return; + + std::string im_text = messages.back()[LL_IM_TEXT].asString(); + im_text.append(line); + messages.back()[LL_IM_TEXT] = im_text; +} + class LLLogChatTimeScanner: public LLSingleton { public: @@ -191,15 +201,17 @@ private: std::stringstream mTimeStream; }; +LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; + //static std::string LLLogChat::makeLogFileName(std::string filename) { /** - * Testing for in bound and out bound ad-hoc file names - * if it is then skip date stamping. - **/ - //LL_INFOS("") << "Befor:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - boost::match_results matches; + * Testing for in bound and out bound ad-hoc file names + * if it is then skip date stamping. + **/ + + boost::match_results matches; bool inboundConf = boost::regex_match(filename, matches, INBOUND_CONFERENCE); bool outboundConf = boost::regex_match(filename, matches, OUTBOUND_CONFERENCE); if (!(inboundConf || outboundConf)) @@ -220,17 +232,17 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename += dbuffer; } } - //LL_INFOS("") << "After:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = cleanFileName(filename); - filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename); - filename += ".txt"; - //LL_INFOS("") << "Full:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ + filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + return filename; } std::string LLLogChat::cleanFileName(std::string filename) { - std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars + std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars std::string::size_type position = filename.find_first_of(invalidChars); while (position != filename.npos) { @@ -242,27 +254,24 @@ std::string LLLogChat::cleanFileName(std::string filename) std::string LLLogChat::timestamp(bool withdate) { - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr; - LLSD substitution; - substitution["datetime"] = (S32) utc_time; - if (withdate) { - timeStr = "["+LLTrans::getString ("TimeYear")+"]/[" - +LLTrans::getString ("TimeMonth")+"]/[" - +LLTrans::getString ("TimeDay")+"] [" - +LLTrans::getString ("TimeHour")+"]:[" - +LLTrans::getString ("TimeMin")+"]"; + timeStr = "[" + LLTrans::getString ("TimeYear") + "]/[" + + LLTrans::getString ("TimeMonth") + "]/[" + + LLTrans::getString ("TimeDay") + "] [" + + LLTrans::getString ("TimeHour") + "]:[" + + LLTrans::getString ("TimeMin") + "]"; } else { timeStr = "[" + LLTrans::getString("TimeHour") + "]:[" - + LLTrans::getString ("TimeMin")+"]"; + + LLTrans::getString ("TimeMin")+"]"; } + LLSD substitution; + substitution["datetime"] = (S32)time_corrected(); + LLStringUtil::format (timeStr, substitution); return timeStr; } @@ -270,9 +279,9 @@ std::string LLLogChat::timestamp(bool withdate) //static void LLLogChat::saveHistory(const std::string& filename, - const std::string& from, - const LLUUID& from_id, - const std::string& line) + const std::string& from, + const LLUUID& from_id, + const std::string& line) { std::string tmp_filename = filename; LLStringUtil::trim(tmp_filename); @@ -312,6 +321,11 @@ void LLLogChat::saveHistory(const std::string& filename, file << LLChatLogFormatter(item) << std::endl; file.close(); + + if (NULL != sSaveHistorySignal) + { + (*sSaveHistorySignal)(); + } } void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata) @@ -321,7 +335,7 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi llwarns << "Filename is Empty!" << llendl; return ; } - + LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/ if (!fptr) { @@ -377,15 +391,6 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi } } -void append_to_last_message(std::list& messages, const std::string& line) -{ - if (!messages.size()) return; - - std::string im_text = messages.back()[IM_TEXT].asString(); - im_text.append(line); - messages.back()[IM_TEXT] = im_text; -} - // static void LLLogChat::loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params) { @@ -397,19 +402,16 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; - //LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - //LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ if (!fptr) - { + { fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - if (!fptr) return; //No previous conversation with this name. - } + if (!fptr) + { + return; //No previous conversation with this name. + } } - //LL_INFOS("") << "Reading:" << file_name << LL_ENDL; char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ char *bptr; S32 len; @@ -454,7 +456,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m LLSD item; if (!LLChatLogParser::parse(line, item, load_params)) { - item[IM_TEXT] = line; + item[LL_IM_TEXT] = line; } messages.push_back(item); } @@ -462,9 +464,78 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m fclose(fptr); } +// static +std::string LLLogChat::oldLogFileName(std::string filename) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // lest make sure the file name has no invalid characters before making the pattern + filename = cleanFileName(filename); + + // create search pattern + std::string pattern = filename + ( filename == "chat" ? "-???\?-?\?-??.txt" : "-???\?-??.txt"); + + std::vector allfiles; + LLDirIterator iter(directory, pattern); + std::string scanResult; + + while (iter.next(scanResult)) + { + allfiles.push_back(scanResult); + } + + if (allfiles.size() == 0) // if no result from date search, return generic filename + { + scanResult = directory + filename + '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } + else + { + sort(allfiles.begin(), allfiles.end()); + scanResult = directory + allfiles.back(); + // this file is now the most recent version of the file. + } + + return scanResult; +} + +// static +void LLLogChat::getListOfTranscriptFiles(std::vector& list_of_transcriptions) +{ + // get Users log directory + std::string directory = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + directory += gDirUtilp->getDirDelimiter(); + + // create search pattern + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + + LLDirIterator iter(directory, pattern); + std::string scanResult; + while (iter.next(scanResult)) + { + list_of_transcriptions.push_back(scanResult); + } +} + +//static +boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb) +{ + if (NULL == sSaveHistorySignal) + { + sSaveHistorySignal = new save_history_signal_t(); + } + + return sSaveHistorySignal->connect(cb); +} + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) -//Example, an object's name can be writen like "Object " +//Example, an object's name can be written like "Object " void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const { if (!im.isMap()) @@ -473,19 +544,19 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const return; } - if (im[IM_TIME].isDefined()) + if (im[LL_IM_TIME].isDefined()) { - std::string timestamp = im[IM_TIME].asString(); + std::string timestamp = im[LL_IM_TIME].asString(); boost::trim(timestamp); ostr << '[' << timestamp << ']' << TWO_SPACES; } //*TODO mark object's names in a special way so that they will be distinguishable form avatar name //which are more strict by its nature (only firstname and secondname) - //Example, an object's name can be writen like "Object " - if (im[IM_FROM].isDefined()) + //Example, an object's name can be written like "Object " + if (im[LL_IM_FROM].isDefined()) { - std::string from = im[IM_FROM].asString(); + std::string from = im[LL_IM_FROM].asString(); boost::trim(from); if (from.size()) { @@ -493,9 +564,9 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const } } - if (im[IM_TEXT].isDefined()) + if (im[LL_IM_TEXT].isDefined()) { - std::string im_text = im[IM_TEXT].asString(); + std::string im_text = im[LL_IM_TEXT].asString(); //multilined text will be saved with prepended spaces boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX); @@ -528,12 +599,12 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp); } - im[IM_TIME] = timestamp; + im[LL_IM_TIME] = timestamp; } else { //timestamp is optional - im[IM_TIME] = ""; + im[LL_IM_TIME] = ""; } bool has_stuff = matches[IDX_STUFF].matched; @@ -559,8 +630,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name || name == SYSTEM_FROM) { //name is optional too - im[IM_FROM] = SYSTEM_FROM; - im[IM_FROM_ID] = LLUUID::null; + im[LL_IM_FROM] = SYSTEM_FROM; + im[LL_IM_FROM_ID] = LLUUID::null; } //possibly a case of complex object names consisting of 3+ words @@ -569,8 +640,8 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params U32 divider_pos = stuff.find(NAME_TEXT_DIVIDER); if (divider_pos != std::string::npos && divider_pos < (stuff.length() - NAME_TEXT_DIVIDER.length())) { - im[IM_FROM] = stuff.substr(0, divider_pos); - im[IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); + im[LL_IM_FROM] = stuff.substr(0, divider_pos); + im[LL_IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length()); return true; } } @@ -578,7 +649,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params if (!has_name) { //text is mandatory - im[IM_TEXT] = stuff; + im[LL_IM_TEXT] = stuff; return true; //parse as a message from Second Life } @@ -590,45 +661,15 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params { std::string agent_name; LLAgentUI::buildFullname(agent_name); - im[IM_FROM] = agent_name; - im[IM_FROM_ID] = gAgentID; + im[LL_IM_FROM] = agent_name; + im[LL_IM_FROM_ID] = gAgentID; } else { - im[IM_FROM] = name; + im[LL_IM_FROM] = name; } - im[IM_TEXT] = name_and_text[IDX_TEXT]; + im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } -std::string LLLogChat::oldLogFileName(std::string filename) -{ - std::string scanResult; - std::string directory = gDirUtilp->getPerAccountChatLogsDir();/* get Users log directory */ - directory += gDirUtilp->getDirDelimiter();/* add final OS dependent delimiter */ - filename=cleanFileName(filename);/* lest make shure the file name has no invalad charecters befor making the pattern */ - std::string pattern = (filename+(( filename == "chat" ) ? "-???\?-?\?-??.txt" : "-???\?-??.txt"));/* create search pattern*/ - //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - std::vector allfiles; - - LLDirIterator iter(directory, pattern); - while (iter.next(scanResult)) - { - //LL_INFOS("") << "Found :" << scanResult << LL_ENDL; - allfiles.push_back(scanResult); - } - - if (allfiles.size() == 0) // if no result from date search, return generic filename - { - scanResult = directory + filename + ".txt"; - } - else - { - std::sort(allfiles.begin(), allfiles.end()); - scanResult = directory + allfiles.back(); - // thisfile is now the most recent version of the file. - } - //LL_INFOS("") << "Reading:" << scanResult << LL_ENDL;/* uncomment if you want to verify step, delete on commit */ - return scanResult; -} diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index d3e9adcc37..b35a94b4b3 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -49,6 +49,7 @@ public: const std::string& from, const LLUUID& from_id, const std::string& line); + static void getListOfTranscriptFiles(std::vector& list); /** @deprecated @see loadChatHistory() */ static void loadHistory(const std::string& filename, @@ -56,8 +57,13 @@ public: void* userdata); static void loadChatHistory(const std::string& file_name, std::list& messages, const LLSD& load_params = LLSD()); + + typedef boost::signals2::signal save_history_signal_t; + static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); + private: static std::string cleanFileName(std::string filename); + static save_history_signal_t * sSaveHistorySignal; }; /** @@ -113,9 +119,10 @@ protected: }; // LLSD map lookup constants -extern const std::string IM_TIME; //("time"); -extern const std::string IM_TEXT; //("message"); -extern const std::string IM_FROM; //("from"); -extern const std::string IM_FROM_ID; //("from_id"); +extern const std::string LL_IM_TIME; //("time"); +extern const std::string LL_IM_TEXT; //("message"); +extern const std::string LL_IM_FROM; //("from"); +extern const std::string LL_IM_FROM_ID; //("from_id"); +extern const std::string LL_TRANSCRIPT_FILE_EXTENSION; //("ll.txt"); #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8489e92d15..f141419c43 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6943,7 +6943,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**) std::string dir_visibility; msg->getString( "UserData", "DirectoryVisibility", dir_visibility); - LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); + LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email); LLFloaterSnapshot::setAgentEmail(email); } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6a464ccdc4..9c36873141 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8316,4 +8316,30 @@ Attempt cancelled. yestext="Yes"/> + + This will delete the log of previous conversations, and all transcripts of those conversations. Proceed? + confirm + + + + + This will delete transcripts for all previous conversations. The list of conversations will not be affected. Proceed? + confirm + + + diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 37bfbae991..4f33699aa6 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -1,7 +1,7 @@ + width="330"> + + - + width="330"> + + + width="350"> + + + Font size: - - + - + - + - - - + name="Large" + value="2"/> + + + + + + + - Notifications: + Notifications + top_pad="13"> Friend IMs: - - - - + top_pad="9"> Non-friend IMs: - - - - + top_pad="9"> Conference IMs: - - - - + top_pad="9"> Group chat: - - - - + top_pad="9"> Nearby chat: - - - - To temporarily stop all notifications, use Communicate > Do Not Disturb. @@ -308,14 +297,13 @@ + + + + + + + Save: + + + + + + + + + + + + + + + Location: + + + + + + + + - - (Locations, images, web, search history) - - - - + border="true" + follows="left|top|right|bottom" + height="408" + label="Communication" + layout="topleft" + left="102" + name="im" + top="1" + width="517"> + + + log in to change + + + + + + (Locations, images, web, search history) + + + + + + - - Chat Logs: - - - - - - - - - Location of logs: - - - +