From 245eaa1fd96193a0944e41b0b2e355a6c4392e73 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Thu, 20 Dec 2012 08:58:18 -0500 Subject: [PATCH] Satisfy radar issues: 51(Avatar Age), 382(Time duration), 245(Hide columns on command) Overall: Extras tab added to radar. Activities given tool_tip strings, TODO: Get icon entries to have tool_tips. Added tab_min_width="0" to tab container so tabs take up only as much space as necessary. Issue 51: RadarAlertAge, AvatarAgeAlertDays debugs added. RadarTextYoung color added to colors_base and gemini. UI bits added to radar. ALERT_TYPE_AGE, LIST_AGE, and boost::lexical_cast added. LLAvatarListEntry is now derived from LLAvatarPropertiesObserver for processProperties and all that fun stuff. Also has mAgeAlert and mAge. processProperties is basically copied directly from LLAvatarPanel, it can probably be bettered. Issue 382: mTime, getTime(), LIST_TIME Time column. Issue 245: Hide columns text and checkboxes added to UI. assessColumns() now used to determine which columns to show. Also once used during postBuild() col_helper() function added to help decide to hide or resize a column based on given params. checkboxes all use assessColumns as callback. RadarColumn* debug settings added. If you read this all, that's a sign the 'pocalypse is coming. --- indra/newview/app_settings/settings.xml | 165 ++++++++++++++ indra/newview/llfloateravatarlist.cpp | 202 ++++++++++++++++-- indra/newview/llfloateravatarlist.h | 17 +- indra/newview/skins/default/colors_base.xml | 1 + .../skins/default/xui/en-us/floater_radar.xml | 30 ++- indra/newview/skins/gemini/colors.xml | 1 + 6 files changed, 395 insertions(+), 21 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f1994c6a0..46b54481b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6307,6 +6307,149 @@ This should be as low as possible, but too low may break functionality 0 + RadarColumnMarkWidth + + Comment + Width for radar's mark column + Persist + 1 + Type + S32 + Value + 12 + + RadarColumnPositionWidth + + Comment + Width for radar's position column + Persist + 1 + Type + S32 + Value + 60 + + RadarColumnAltitudeWidth + + Comment + Width for radar's altitude column + Persist + 1 + Type + S32 + Value + 48 + + RadarColumnActivityWidth + + Comment + Width for radar's activity column + Persist + 1 + Type + S32 + Value + 24 + + RadarColumnAgeWidth + + Comment + Width for radar's age column + Persist + 1 + Type + S32 + Value + 45 + + RadarColumnTimeWidth + + Comment + Width for radar's time column + Persist + 1 + Type + S32 + Value + 52 + + RadarColumnMarkHidden + + Comment + Hide radar's mark column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnPositionHidden + + Comment + Hide radar's position column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnAltitudeHidden + + Comment + Hide radar's altitude column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnActivityHidden + + Comment + Hide radar's activity column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnAgeHidden + + Comment + Hide radar's age column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnTimeHidden + + Comment + Hide radar's time column + Persist + 1 + Type + Boolean + Value + 1 + + RadarColumnClientHidden + + Comment + Hide radar's client column + Persist + 1 + Type + Boolean + Value + 0 + RadarKeepOpen Comment @@ -6373,6 +6516,28 @@ This should be as low as possible, but too low may break functionality Value 1 + RadarAlertAge + + Comment + Whether the radar emits chat alerts for avatars younger than AvatarAgeAlertDays appearing. + Persist + 1 + Type + Boolean + Value + 0 + + AvatarAgeAlertDays + + Comment + Age below which avatars will be made known to you + Persist + 1 + Type + U32 + Value + 3 + RadarChatAlerts Comment diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 887afe476..339b90f3c 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -53,6 +53,7 @@ #include #include +#include #include "llworld.h" #include "llsdutil.h" @@ -79,6 +80,7 @@ typedef enum e_radar_alert_type ALERT_TYPE_DRAW = 2, ALERT_TYPE_SHOUTRANGE = 4, ALERT_TYPE_CHATRANGE = 8, + ALERT_TYPE_AGE = 16, } ERadarAlertType; void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool entering) @@ -90,10 +92,12 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool static LLCachedControl radar_alert_draw(gSavedSettings, "RadarAlertDraw"); static LLCachedControl radar_alert_shout_range(gSavedSettings, "RadarAlertShoutRange"); static LLCachedControl radar_alert_chat_range(gSavedSettings, "RadarAlertChatRange"); + static LLCachedControl radar_alert_age(gSavedSettings, "RadarAlertAge"); static LLCachedControl radar_chat_keys(gSavedSettings, "RadarChatKeys"); LLFloaterAvatarList* self = LLFloaterAvatarList::getInstance(); LLStringUtil::format_map_t args; + args["[NAME]"] = name; switch(type) { case ALERT_TYPE_SIM: @@ -123,10 +127,21 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool args["[RANGE]"] = self->getString("chat_range"); } break; + + case ALERT_TYPE_AGE: + if (radar_alert_age) + { + LLChat chat; + chat.mFromName = name; + chat.mText = name + " " + self->getString("has_triggered_your_avatar_age_alert") + "."; + chat.mURL = llformat("secondlife:///app/agent/%s/about",key.asString().c_str()); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat); + } + break; } if (args.find("[RANGE]") != args.end()) { - args["[NAME]"] = name; args["[ACTION]"] = self->getString(entering ? "has_entered" : "has_left"); LLChat chat; chat.mText = self->getString("template", args); @@ -142,8 +157,40 @@ LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string &name, mUpdateTimer(), mFrame(gFrameCount), mInSimFrame(U32_MAX), mInDrawFrame(U32_MAX), mInChatFrame(U32_MAX), mInShoutFrame(U32_MAX), mActivityType(ACTIVITY_NEW), mActivityTimer(), - mIsInList(false) + mIsInList(false), mAge(-1), mAgeAlert(false), mTime(time(NULL)) { + if (mID.notNull()) + LLAvatarPropertiesProcessor::getInstance()->addObserver(mID, this); +} + +LLAvatarListEntry::~LLAvatarListEntry() +{ + if (mID.notNull()) + LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this); +} + +// virtual +void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type) +{ + if(type == APT_PROPERTIES) + { + const LLAvatarData* pAvatarData = static_cast(data); + if (pAvatarData && (pAvatarData->avatar_id != LLUUID::null)) + { + //Chalice - Show avatar age in days. + int year, month, day; + sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); + time_t now = time(NULL); + struct tm * timeinfo; + timeinfo=localtime(&now); + timeinfo->tm_mon = --month; + timeinfo->tm_year = year - 1900; + timeinfo->tm_mday = day; + time_t birth = mktime(timeinfo); + mAge = difftime(now,birth) / (60*60*24); + // If one wanted more information that gets displayed on profiles to be displayed, here would be the place to do it. + } + } } void LLAvatarListEntry::setPosition(LLVector3d position, bool this_sim, bool drawn, bool chatrange, bool shoutrange) @@ -354,6 +401,13 @@ BOOL LLFloaterAvatarList::postBuild() getChild("update_rate")->setSelectedIndex(gSavedSettings.getU32("RadarUpdateRate")); getChild("update_rate")->setCommitCallback(boost::bind(&LLFloaterAvatarList::onCommitUpdateRate, this)); + getChild("hide_mark")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_pos")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_alt")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_act")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_age")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_time")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + // Get a pointer to the scroll list from the interface mAvatarList = getChild("avatar_list"); mAvatarList->sortByColumn("distance", TRUE); @@ -365,20 +419,69 @@ BOOL LLFloaterAvatarList::postBuild() gIdleCallbacks.addFunction(LLFloaterAvatarList::callbackIdle); - if(gHippoGridManager->getConnectedGrid()->isSecondLife()){ - LLScrollListCtrl* list = getChild("avatar_list"); - list->getColumn(LIST_AVATAR_NAME)->setWidth(0); - list->getColumn(LIST_CLIENT)->setWidth(0); - list->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; - list->getColumn(LIST_CLIENT)->mRelWidth = 0; - list->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE; - list->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1; - list->updateLayout(); - } + assessColumns(); + + if(gHippoGridManager->getConnectedGrid()->isSecondLife()) + childSetVisible("hide_client", false); + else + getChild("hide_client")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); return TRUE; } +void col_helper(const bool hide, const std::string width_ctrl_name, LLScrollListColumn* col) +{ + // Brief Explanation: + // Check if we want the column hidden, and if it's still showing. If so, hide it, but save its width. + // Otherwise, if we don't want it hidden, but it is, unhide it to the saved width. + // We only store width of columns when hiding here for the purpose of hiding and unhiding. + const int width = col->getWidth(); + + if (hide && width) + { + gSavedSettings.setS32(width_ctrl_name, width); + col->setWidth(0); + } + else if(!hide && !width) + { + llinfos << "We got into the setter!!" << llendl; + col->setWidth(gSavedSettings.getS32(width_ctrl_name)); + } +} + +void LLFloaterAvatarList::assessColumns() +{ + static LLCachedControl hide_mark(gSavedSettings, "RadarColumnMarkHidden"); + col_helper(hide_mark, "RadarColumnMarkWidth", mAvatarList->getColumn(LIST_MARK)); + + static LLCachedControl hide_pos(gSavedSettings, "RadarColumnPositionHidden"); + col_helper(hide_pos, "RadarColumnPositionWidth", mAvatarList->getColumn(LIST_POSITION)); + + static LLCachedControl hide_alt(gSavedSettings, "RadarColumnAltitudeHidden"); + col_helper(hide_alt, "RadarColumnAltitudeWidth", mAvatarList->getColumn(LIST_ALTITUDE)); + + static LLCachedControl hide_act(gSavedSettings, "RadarColumnActivityHidden"); + col_helper(hide_act, "RadarColumnActivityWidth", mAvatarList->getColumn(LIST_ACTIVITY)); + + static LLCachedControl hide_age(gSavedSettings, "RadarColumnAgeHidden"); + col_helper(hide_age, "RadarColumnAgeWidth", mAvatarList->getColumn(LIST_AGE)); + + static LLCachedControl hide_time(gSavedSettings, "RadarColumnTimeHidden"); + col_helper(hide_time, "RadarColumnTimeWidth", mAvatarList->getColumn(LIST_TIME)); + + static LLCachedControl hide_client(gSavedSettings, "RadarColumnClientHidden"); + if (gHippoGridManager->getConnectedGrid()->isSecondLife() || hide_client){ + mAvatarList->getColumn(LIST_AVATAR_NAME)->setWidth(0); + mAvatarList->getColumn(LIST_CLIENT)->setWidth(0); + mAvatarList->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; + mAvatarList->getColumn(LIST_CLIENT)->mRelWidth = 0; + mAvatarList->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE; + mAvatarList->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1; + } + + mAvatarList->updateLayout(); +} + void updateParticleActivity(LLDrawable *drawablep) { if (LLFloaterAvatarList::instanceExists()) @@ -716,6 +819,10 @@ void LLFloaterAvatarList::refreshAvatarList() continue; } + //Request properties here, so we'll have them later on when we need them + LLAvatarPropertiesProcessor::getInstance()->addObserver(entry.mID, &entry); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(entry.mID); + element["id"] = av_id; element["columns"][LIST_MARK]["column"] = "marked"; @@ -755,6 +862,7 @@ void LLFloaterAvatarList::refreshAvatarList() static LLCachedControl sRadarTextChatRange(gColors, "RadarTextChatRange"); static LLCachedControl sRadarTextShoutRange(gColors, "RadarTextShoutRange"); static LLCachedControl sRadarTextDrawDist(gColors, "RadarTextDrawDist"); + static LLCachedControl sRadarTextYoung(gColors, "RadarTextYoung"); LLColor4 name_color = sDefaultListText; //Lindens are always more Linden than your friend, make that take precedence @@ -872,28 +980,50 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_ACTIVITY]["type"] = "icon"; std::string activity_icon = ""; + std::string activity_tip = ""; switch(entry.getActivity()) { case LLAvatarListEntry::ACTIVITY_MOVING: - activity_icon = "inv_item_animation.tga"; + { + activity_icon = "inv_item_animation.tga"; + activity_tip = getString("Moving"); + } break; case LLAvatarListEntry::ACTIVITY_GESTURING: - activity_icon = "inv_item_gesture.tga"; + { + activity_icon = "inv_item_gesture.tga"; + activity_tip = getString("Playing a gesture"); + } break; case LLAvatarListEntry::ACTIVITY_SOUND: - activity_icon = "inv_item_sound.tga"; + { + activity_icon = "inv_item_sound.tga"; + activity_tip = getString("Playing a sound"); + } break; case LLAvatarListEntry::ACTIVITY_REZZING: - activity_icon = "ff_edit_theirs.tga"; + { + activity_icon = "ff_edit_theirs.tga"; + activity_tip = getString("Rezzing objects"); + } break; case LLAvatarListEntry::ACTIVITY_PARTICLES: - activity_icon = "particles_scan.tga"; + { + activity_icon = "particles_scan.tga"; + activity_tip = getString("Creating particles"); + } break; case LLAvatarListEntry::ACTIVITY_NEW: - activity_icon = "avatar_new.tga"; + { + activity_icon = "avatar_new.tga"; + activity_tip = getString("Just arrived"); + } break; case LLAvatarListEntry::ACTIVITY_TYPING: - activity_icon = "avatar_typing.tga"; + { + activity_icon = "avatar_typing.tga"; + activity_tip = getString("Typing"); + } break; default: break; @@ -901,6 +1031,40 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_ACTIVITY]["value"] = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga"; //element["columns"][LIST_AVATAR_ACTIVITY]["color"] = icon_color.getValue(); + element["columns"][LIST_ACTIVITY]["tool_tip"] = activity_tip; + + element["columns"][LIST_AGE]["column"] = "age"; + element["columns"][LIST_AGE]["type"] = "text"; + color = sDefaultListText; + std::string age = boost::lexical_cast(entry.mAge); + if (entry.mAge > -1) + { + static LLCachedControl sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays"); + if (entry.mAge < sAvatarAgeAlertDays) + { + color = sRadarTextYoung; + if (!entry.mAgeAlert) //Only announce age once per entry. + { + entry.mAgeAlert = true; + chat_avatar_status(entry.getName().c_str(), av_id, ALERT_TYPE_AGE, true); + } + } + } + else + { + age = "?"; + } + element["columns"][LIST_AGE]["value"] = age; + element["columns"][LIST_AGE]["color"] = color.getValue(); + + int dur = difftime(time(NULL), entry.getTime()); + int hours = dur / 360; + int mins = (dur % 360) / 60; + int secs = (dur % 360) % 60; + + element["columns"][LIST_TIME]["column"] = "time"; + element["columns"][LIST_TIME]["type"] = "text"; + element["columns"][LIST_TIME]["value"] = llformat("%d:%02d:%02d", hours, mins, secs); element["columns"][LIST_CLIENT]["column"] = "client"; element["columns"][LIST_CLIENT]["type"] = "text"; diff --git a/indra/newview/llfloateravatarlist.h b/indra/newview/llfloateravatarlist.h index d9fe93581..8aa3d3665 100644 --- a/indra/newview/llfloateravatarlist.h +++ b/indra/newview/llfloateravatarlist.h @@ -11,6 +11,7 @@ // // #include "llavatarname.h" +#include "llavatarpropertiesprocessor.h" #include "llfloater.h" #include "llfloaterreporter.h" #include "lluuid.h" @@ -29,7 +30,8 @@ class LLFloaterAvatarList; * Instances are kept in a map. We keep track of the * frame where the avatar was last seen. */ -class LLAvatarListEntry { +class LLAvatarListEntry : public LLAvatarPropertiesObserver +{ public: @@ -52,6 +54,10 @@ enum ACTIVITY_TYPE * @param position Avatar's current position */ LLAvatarListEntry(const LLUUID& id = LLUUID::null, const std::string &name = "", const LLVector3d &position = LLVector3d::zero); + ~LLAvatarListEntry(); + + // Get properties, such as age and other niceties displayed on profiles. + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); /** * Update world position. @@ -78,6 +84,7 @@ enum ACTIVITY_TYPE * @brief Returns the name of the avatar */ const std::string& getName() const { return mName; } + const time_t& getTime() const { return mTime; } /** * @brief Returns the ID of the avatar @@ -132,11 +139,14 @@ private: LLUUID mID; std::string mName; + time_t mTime; LLVector3d mPosition; LLVector3d mDrawPosition; bool mMarked; bool mFocused; bool mIsInList; + bool mAgeAlert; + int mAge; /** * @brief Timer to keep track of whether avatars are still there @@ -202,6 +212,9 @@ public: static void showInstance(); + // Decides which user-chosen columns to show and hide. + void assessColumns(); + /** * @brief Updates the internal avatar list with the currently present avatars. */ @@ -245,6 +258,8 @@ private: LIST_POSITION, LIST_ALTITUDE, LIST_ACTIVITY, + LIST_AGE, + LIST_TIME, LIST_CLIENT, }; diff --git a/indra/newview/skins/default/colors_base.xml b/indra/newview/skins/default/colors_base.xml index eaed66c4d..651f4c232 100644 --- a/indra/newview/skins/default/colors_base.xml +++ b/indra/newview/skins/default/colors_base.xml @@ -153,6 +153,7 @@ + diff --git a/indra/newview/skins/default/xui/en-us/floater_radar.xml b/indra/newview/skins/default/xui/en-us/floater_radar.xml index 5a2c78cea..8b5117601 100644 --- a/indra/newview/skins/default/xui/en-us/floater_radar.xml +++ b/indra/newview/skins/default/xui/en-us/floater_radar.xml @@ -14,11 +14,13 @@ + + + name="actions_tab_container" tab_position="top" tab_min_width="0" follows="left|right|bottom"> @@ -337,7 +339,33 @@ follows="bottom|left" /> + + + + + Hide columns: + + + + + + + + + Moving + Playing a gesture + Playing a sound + Rezzing objects + Creating particles + Just arrived + Typing + has triggered your avatar age alert [NAME] [ACTION] [RANGE]. has entered diff --git a/indra/newview/skins/gemini/colors.xml b/indra/newview/skins/gemini/colors.xml index 7e5870fc8..331979419 100644 --- a/indra/newview/skins/gemini/colors.xml +++ b/indra/newview/skins/gemini/colors.xml @@ -151,6 +151,7 @@ +