diff options
-rw-r--r-- | .hgignore | 1 | ||||
-rw-r--r-- | indra/llmessage/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llmessage/llexperiencecache.cpp | 313 | ||||
-rw-r--r-- | indra/llmessage/llexperiencecache.h | 71 | ||||
-rwxr-xr-x | indra/newview/CMakeLists.txt | 4 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 50 | ||||
-rw-r--r-- | indra/newview/llappviewer.h | 5 | ||||
-rw-r--r-- | indra/newview/llfloaterexperiences.cpp | 14 | ||||
-rw-r--r-- | indra/newview/llfloaterexperiences.h | 45 | ||||
-rw-r--r-- | indra/newview/llpanelexperiences.cpp | 254 | ||||
-rw-r--r-- | indra/newview/llpanelexperiences.h | 120 | ||||
-rwxr-xr-x | indra/newview/llstartup.cpp | 12 | ||||
-rwxr-xr-x | indra/newview/llstartup.h | 1 | ||||
-rw-r--r-- | indra/newview/llviewerfloaterreg.cpp | 4 | ||||
-rwxr-xr-x | indra/newview/llvoavatar.cpp | 4 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_experiences.xml | 29 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 8 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_experience_info.xml | 79 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_experiences.xml | 40 |
19 files changed, 1052 insertions, 4 deletions
@@ -70,3 +70,4 @@ glob:indra/newview/avatar_icons_cache.txt glob:indra/newview/avatar_lad.log glob:*.diff *.rej +indra/newview/stat diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index d98781e9e6..9974d103a2 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -38,6 +38,7 @@ set(llmessage_SOURCE_FILES llcurl.cpp lldatapacker.cpp lldispatcher.cpp + llexperiencecache.cpp llfiltersd2xmlrpc.cpp llhost.cpp llhttpassetstorage.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES lldbstrings.h lldispatcher.h lleventflags.h + llexperiencecache.h llfiltersd2xmlrpc.h llfollowcamparams.h llhost.h diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp new file mode 100644 index 0000000000..0d8f76c7e2 --- /dev/null +++ b/indra/llmessage/llexperiencecache.cpp @@ -0,0 +1,313 @@ +/** + * @file llexperiencecache.cpp + * @brief llexperiencecache and related class definitions + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llavatarname.h" +#include "llframetimer.h" +#include "llhttpclient.h" +#include "llsdserialize.h" +#include <set> +#include <map> + +#include "llexperiencecache.h" + + + +namespace LLExperienceCache +{ + bool sRunning = false; + std::string sLookupURL; + + typedef std::set<LLUUID> ask_queue_t; + ask_queue_t sAskQueue; + + typedef std::map<LLUUID, F64> pending_queue_t; + pending_queue_t sPendingQueue; + + + cache_t sCache; + + LLFrameTimer sRequestTimer; + + + + void processExperience( const LLUUID& agent_id, const LLExperienceData& experience, bool add_to_cache ) + { + if(add_to_cache) + { + sCache[agent_id]=experience; + + sPendingQueue.erase(agent_id); + + + //signal + } + } + + void initClass( bool running ) + { + sRunning = false; + } + + const cache_t& getCached() + { + return sCache; + } + + + + void importFile(std::istream& istr) + { + LLSD data; + S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); + if(parse_count < 1) return; + + LLSD agents = data["agents"]; + + LLUUID agent_id; + LLExperienceData experience; + LLSD::map_const_iterator it = agents.beginMap(); + for(; it != agents.endMap() ; ++it) + { + agent_id.set(it->first); + experience.fromLLSD( it->second); + sCache[agent_id]=experience; + } + + LL_INFOS("ExperienceCache") << "loaded " << sCache.size() << LL_ENDL; + } + + void exportFile(std::ostream& ostr) + { + LLSD agents; + + cache_t::const_iterator it =sCache.begin(); + for( ; it != sCache.end() ; ++it) + { + agents[it->first.asString()] = it->second.asLLSD(); + } + + LLSD data; + data["agents"] = agents; + + LLSDSerialize::toPrettyXML(data, ostr); + } + + class LLExperienceResponder : public LLHTTPClient::Responder + { + public: + LLExperienceResponder(const std::vector<LLUUID>& agent_ids) + :mAgentIds(agent_ids) + { + + } + + virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + mHeaders = content; + } + + virtual void result(const LLSD& content) + { + LLSD agents = content["agents"]; + LLSD::array_const_iterator it = agents.beginArray(); + for( /**/ ; it != agents.endArray(); ++it) + { + const LLSD& row = *it; + LLUUID agent_id = row["id"].asUUID(); + + LLExperienceData experience; + + if(experience.fromLLSD(row)) + { + LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "Received result for " << agent_id + << "display '" << experience.mDisplayName << "'" << LL_ENDL ; + + processExperience(agent_id, experience, true); + } + } + + LLSD unresolved_agents = content["bad_ids"]; + S32 num_unresolved = unresolved_agents.size(); + if(num_unresolved > 0) + { + LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "Ignoreing " << num_unresolved + << " bad ids" << LL_ENDL ; + } + + LL_DEBUGS("ExperienceCache") << __FUNCTION__ << sCache.size() << " cached experiences" << LL_ENDL; + } + + private: + std::vector<LLUUID> mAgentIds; + LLSD mHeaders; + }; + + void requestExperiences() + { + if(sAskQueue.empty()) + return; + + F64 now = LLFrameTimer::getTotalSeconds(); + + const U32 NAME_URL_MAX = 4096; + const U32 NAME_URL_SEND_THRESHOLD = 3000; + + std::string url; + url.reserve(NAME_URL_MAX); + + std::vector<LLUUID> agent_ids; + agent_ids.reserve(128); + + url += sLookupURL; + + std::string arg="?ids="; + + for(ask_queue_t::const_iterator it = sAskQueue.begin(); it != sAskQueue.end() ; ++it) + { + const LLUUID& agent_id = *it; + + url += arg; + url += agent_id.asString(); + agent_ids.push_back(agent_id); + + sPendingQueue[agent_id] = now; + + arg[0]='&'; + + if(url.size() > NAME_URL_SEND_THRESHOLD) + { + LLHTTPClient::get(url, new LLExperienceResponder(agent_ids)); + url = sLookupURL; + arg[0]='?'; + agent_ids.clear(); + } + } + + if(url.size() > sLookupURL.size()) + { + LLHTTPClient::get(url, new LLExperienceResponder(agent_ids)); + } + + sAskQueue.clear(); + } + + bool isRequestPending(const LLUUID& agent_id) + { + bool isPending = false; + const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; + + pending_queue_t::const_iterator it = sPendingQueue.find(agent_id); + + if(it != sPendingQueue.end()) + { + F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; + isPending = (it->second > expire_time); + } + + return isPending; + } + + + void setLookupURL( const std::string& lookup_url ) + { + sLookupURL = lookup_url; + } + + bool hasLookupURL() + { + return !sLookupURL.empty(); + } + + void idle() + { + sRunning = true; + + if(!sAskQueue.empty()) + { + requestExperiences(); + } + } + + void erase( const LLUUID& agent_id ) + { + sCache.erase(agent_id); + } + + void fetch( const LLUUID& agent_id ) + { + LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "queue request for agent" << agent_id << LL_ENDL ; + sAskQueue.insert(agent_id); + } + + void insert( const LLUUID& agent_id, const LLExperienceData& experience_data ) + { + sCache[agent_id]=experience_data; + } + + bool get( const LLUUID& agent_id, LLExperienceData* experience_data ) + { + if(sRunning) + { + + cache_t::const_iterator it = sCache.find(agent_id); + if (it != sCache.end()) + { + llassert(experience_data); + *experience_data = it->second; + return true; + } + } + + if(!isRequestPending(agent_id)) + { + fetch(agent_id); + } + + return false; + } + + +} + +bool LLExperienceData::fromLLSD( const LLSD& sd ) +{ + mDisplayName = sd["display_name"].asString(); + mDescription = sd["username"].asString(); + + if(mDisplayName.empty() || mDescription.empty()) return false; + + mDescription += " % Hey, this is a description!"; + return true; +} + +LLSD LLExperienceData::asLLSD() const +{ + LLSD sd; + sd["display_name"] = mDisplayName; + sd["username"] = mDescription.substr(0, llmin(mDescription.size(),mDescription.find(" %"))); + return sd; +} diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h new file mode 100644 index 0000000000..799cdea13a --- /dev/null +++ b/indra/llmessage/llexperiencecache.h @@ -0,0 +1,71 @@ +/** + * @file llexperiencecache.h + * @brief Caches information relating to experience keys + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + + +#ifndef LL_LLEXPERIENCECACHE_H +#define LL_LLEXPERIENCECACHE_H + +#include <string> + +class LLUUID; + + +class LLExperienceData +{ +public: + bool fromLLSD(const LLSD& sd); + LLSD asLLSD() const; + + + std::string mDisplayName; + std::string mDescription; +}; + + + +namespace LLExperienceCache +{ + void setLookupURL(const std::string& lookup_url); + bool hasLookupURL(); + + + void idle(); + void exportFile(std::ostream& ostr); + void importFile(std::istream& istr); + void initClass(bool running); + + void erase(const LLUUID& agent_id); + void fetch(const LLUUID& agent_id); + void insert(const LLUUID& agent_id, const LLExperienceData& experience_data); + bool get(const LLUUID& agent_id, LLExperienceData* experience_data); + + typedef std::map<LLUUID, LLExperienceData> cache_t; + + const cache_t& getCached(); +}; + +#endif // LL_LLEXPERIENCECACHE_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7eea9ece5a..ccb18df1e0 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -202,6 +202,7 @@ set(viewer_SOURCE_FILES llfloatereditwater.cpp llfloaterenvironmentsettings.cpp llfloaterevent.cpp + llfloaterexperiences.cpp llfloaterfonttest.cpp llfloatergesture.cpp llfloatergodtools.cpp @@ -370,6 +371,7 @@ set(viewer_SOURCE_FILES llpanelclassified.cpp llpanelcontents.cpp llpaneleditwearable.cpp + llpanelexperiences.cpp llpanelface.cpp llpanelgenerictip.cpp llpanelgroup.cpp @@ -779,6 +781,7 @@ set(viewer_HEADER_FILES llfloatereditwater.h llfloaterenvironmentsettings.h llfloaterevent.h + llfloaterexperiences.h llfloaterfonttest.h llfloatergesture.h llfloatergodtools.h @@ -941,6 +944,7 @@ set(viewer_HEADER_FILES llpanelclassified.h llpanelcontents.h llpaneleditwearable.h + llpanelexperiences.h llpanelface.h llpanelgenerictip.h llpanelgroup.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 438194c715..7855d77c9c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -100,6 +100,7 @@ // Linden library includes #include "llavatarnamecache.h" #include "lldiriterator.h" +#include "llexperiencecache.h" #include "llimagej2c.h" #include "llmemory.h" #include "llprimitive.h" @@ -4149,7 +4150,7 @@ void LLAppViewer::loadNameCache() } void LLAppViewer::saveNameCache() - { +{ // display names cache std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); @@ -4157,7 +4158,7 @@ void LLAppViewer::saveNameCache() if(name_cache_stream.is_open()) { LLAvatarNameCache::exportFile(name_cache_stream); -} + } if (!gCacheName) return; @@ -4170,6 +4171,32 @@ void LLAppViewer::saveNameCache() } } + +void LLAppViewer::saveExperienceCache() +{ + std::string filename = + gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL; + llofstream cache_stream(filename); + if(cache_stream.is_open()) + { + LLExperienceCache::exportFile(cache_stream); + } +} + +void LLAppViewer::loadExperienceCache() +{ + std::string filename = + gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL; + llifstream cache_stream(filename); + if(cache_stream.is_open()) + { + LLExperienceCache::importFile(cache_stream); + } +} + + /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -4372,7 +4399,7 @@ void LLAppViewer::idle() // floating throughout the various object lists. // idleNameCache(); - + idleExperienceCache(); idleNetwork(); @@ -4786,6 +4813,22 @@ void LLAppViewer::idleNameCache() LLAvatarNameCache::idle(); } +void LLAppViewer::idleExperienceCache() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; + + std::string lookup_url=region->getCapability("GetDisplayNames"); // use GetDisplayNames for testing round trip + if(!lookup_url.empty() && lookup_url.back() != '/') + { + lookup_url += '/'; + } + + LLExperienceCache::setLookupURL(lookup_url); + + LLExperienceCache::idle(); +} + // // Handle messages, and all message related stuff // @@ -4949,6 +4992,7 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); + saveExperienceCache(); // close inventory interface, close all windows LLFloaterInventory::cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 7a474f9122..4bf6bec0e8 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -114,6 +114,10 @@ public: void loadNameCache(); void saveNameCache(); + void loadExperienceCache(); + void saveExperienceCache(); + + void removeMarkerFile(bool leave_logout_marker = false); // LLAppViewer testing helpers. @@ -218,6 +222,7 @@ private: void idle(); void idleShutdown(); // update avatar SLID and display name caches + void idleExperienceCache(); void idleNameCache(); void idleNetwork(); diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp new file mode 100644 index 0000000000..b862b41bba --- /dev/null +++ b/indra/newview/llfloaterexperiences.cpp @@ -0,0 +1,14 @@ +#include "llviewerprecompiledheaders.h" + +#include "llpanelexperiences.h" +#include "llfloaterexperiences.h" + +LLFloaterExperiences::LLFloaterExperiences(const LLSD& data) + :LLFloater(data) +{ +} + +BOOL LLFloaterExperiences::postBuild() +{ + return TRUE; +} diff --git a/indra/newview/llfloaterexperiences.h b/indra/newview/llfloaterexperiences.h new file mode 100644 index 0000000000..1e5f216f8d --- /dev/null +++ b/indra/newview/llfloaterexperiences.h @@ -0,0 +1,45 @@ +/** + * @file llfloaterexperiences.h + * @brief LLFloaterExperiences class definition + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATEREXPERIENCES_H +#define LL_LLFLOATEREXPERIENCES_H + +#include "llfloater.h" + +class LLFloaterExperiences : + public LLFloater +{ +public: + LLFloaterExperiences(const LLSD& data); + +protected: + /*virtual*/ BOOL postBuild(); + +private: + +}; + +#endif //LL_LLFLOATEREXPERIENCES_H diff --git a/indra/newview/llpanelexperiences.cpp b/indra/newview/llpanelexperiences.cpp new file mode 100644 index 0000000000..bc9d3cc0ee --- /dev/null +++ b/indra/newview/llpanelexperiences.cpp @@ -0,0 +1,254 @@ +#include "llviewerprecompiledheaders.h" + + +#include "llpanelprofile.h" +#include "lluictrlfactory.h" +#include "llexperiencecache.h" + +#include "llpanelexperiences.h" + + +static LLRegisterPanelClassWrapper<LLPanelExperiences> register_experiences_panel("experiences_panel"); + + +LLPanelExperiences::LLPanelExperiences( ) + : mExperiencesList(NULL), + mExperiencesAccTab(NULL), + mProfilePanel(NULL), + mPanelExperienceInfo(NULL), + mNoExperiences(false) +{ + +} + +void* LLPanelExperiences::create( void* data ) +{ + return new LLPanelExperiences(); +} + + +BOOL LLPanelExperiences::postBuild( void ) +{ + mExperiencesList = getChild<LLFlatListView>("experiences_list"); + if(hasString("no_experiences")) + { + mExperiencesList->setNoItemsCommentText(getString("no_experiences")); + } + + const LLExperienceCache::cache_t& experiences = LLExperienceCache::getCached(); + + LLExperienceCache::cache_t::const_iterator it = experiences.begin(); + for( ; it != experiences.end() && mExperiencesList->getChildCount() < 10 ; ++it) + { + LLExperienceItem* item = new LLExperienceItem(); + item->setExperienceName(it->second.mDisplayName); + item->setExperienceDescription(it->second.mDescription); + mExperiencesList->addItem(item); + } + + mExperiencesAccTab = getChild<LLAccordionCtrlTab>("tab_experiences"); + mExperiencesAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelExperiences::onAccordionStateChanged, this, mExperiencesAccTab)); + mExperiencesAccTab->setDisplayChildren(true); + + return TRUE; +} + +void LLPanelExperiences::onOpen( const LLSD& key ) +{ + LLPanel::onOpen(key); +} + +void LLPanelExperiences::onClosePanel() +{ + if (mPanelExperienceInfo) + { + onPanelExperienceClose(mPanelExperienceInfo); + } +} + +void LLPanelExperiences::updateData() +{ + if(isDirty()) + { + mNoExperiences = false; + + /* + mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); + mNoItemsLabel->setVisible(TRUE); + + mPicksList->clear(); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); + + mClassifiedsList->clear(); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); + */ + } +} + +LLExperienceItem* LLPanelExperiences::getSelectedExperienceItem() +{ + LLPanel* selected_item = mExperiencesList->getSelectedItem(); + if (!selected_item) return NULL; + + return dynamic_cast<LLExperienceItem*>(selected_item); +} + +void LLPanelExperiences::setProfilePanel( LLPanelProfile* profile_panel ) +{ + mProfilePanel = profile_panel; +} + +void LLPanelExperiences::onListCommit( const LLFlatListView* f_list ) +{ + if(f_list == mExperiencesList) + { + mExperiencesList->resetSelection(true); + } + else + { + llwarns << "Unknown list" << llendl; + } + + //updateButtons(); +} + +void LLPanelExperiences::onAccordionStateChanged( const LLAccordionCtrlTab* acc_tab ) +{ + if(!mExperiencesAccTab->getDisplayChildren()) + { + mExperiencesList->resetSelection(true); + } + +} + +void LLPanelExperiences::openExperienceInfo() +{ + LLSD selected_value = mExperiencesList->getSelectedValue(); + if(selected_value.isUndefined()) + { + return; + } + + LLExperienceItem* experience = (LLExperienceItem*)mExperiencesList->getSelectedItem(); + + createExperienceInfoPanel(); + + LLSD params; + params["experience_name"] = experience->getExperienceName(); + params["experience_desc"] = experience->getExperienceDescription(); + + getProfilePanel()->openPanel(mPanelExperienceInfo, params); + +} + + +void LLPanelExperiences::createExperienceInfoPanel() +{ + if(!mPanelExperienceInfo) + { + mPanelExperienceInfo = LLPanelExperienceInfo::create(); + mPanelExperienceInfo->setExitCallback(boost::bind(&LLPanelExperiences::onPanelExperienceClose, this, mPanelExperienceInfo)); + mPanelExperienceInfo->setVisible(FALSE); + } +} + +void LLPanelExperiences::onPanelExperienceClose( LLPanel* panel ) +{ + getProfilePanel()->closePanel(panel); +} + +LLPanelProfile* LLPanelExperiences::getProfilePanel() +{ + llassert_always(NULL != mProfilePanel); + + return mProfilePanel; +} + + + + + + + + + + + +LLExperienceItem::LLExperienceItem() +{ + buildFromFile("panel_experience_info.xml"); +} + +void LLExperienceItem::init( LLExperienceData* experience_data ) +{ + setExperienceDescription(experience_data->mDescription); + setExperienceName(experience_data->mDisplayName); +} + +void LLExperienceItem::setExperienceDescription( const std::string& val ) +{ + mExperienceDescription = val; + getChild<LLUICtrl>("experience_desc")->setValue(val); +} + +void LLExperienceItem::setExperienceName( const std::string& val ) +{ + mExperienceName = val; + getChild<LLUICtrl>("experience_name")->setValue(val); +} + +BOOL LLExperienceItem::postBuild() +{ + return TRUE; +} + +void LLExperienceItem::update() +{ + +} + +void LLExperienceItem::processProperties( void* data, EAvatarProcessorType type ) +{ + +} + +LLExperienceItem::~LLExperienceItem() +{ + +} + + +void LLPanelExperienceInfo::setExperienceName( const std::string& name ) +{ + getChild<LLUICtrl>("experience_name")->setValue(name); +} + +void LLPanelExperienceInfo::setExperienceDesc( const std::string& desc ) +{ + getChild<LLUICtrl>("experience_desc")->setValue(desc); +} + +void LLPanelExperienceInfo::onOpen( const LLSD& key ) +{ + setExperienceName(key["experience_name"]); + setExperienceDesc(key["experience_desc"]); + + /* + LLAvatarPropertiesProcessor::getInstance()->addObserver( + getAvatarId(), this); + LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest( + getAvatarId(), getPickId()); + */ +} + +LLPanelExperienceInfo* LLPanelExperienceInfo::create() +{ + LLPanelExperienceInfo* panel = new LLPanelExperienceInfo(); + panel->buildFromFile("panel_experience_info.xml"); + return panel; +} + +void LLPanelExperienceInfo::setExitCallback( const commit_callback_t& cb ) +{ + getChild<LLButton>("back_btn")->setClickedCallback(cb); +} diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h new file mode 100644 index 0000000000..33bb0f944a --- /dev/null +++ b/indra/newview/llpanelexperiences.h @@ -0,0 +1,120 @@ +/** + * @file llpanelpicks.h + * @brief LLPanelPicks and related class definitions + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELEXPERIENCES_H +#define LL_LLPANELEXPERIENCES_H + +#include "llaccordionctrltab.h" +#include "llflatlistview.h" +#include "llpanelavatar.h" + +class LLExperienceData; +class LLExperienceItem; +class LLPanelProfile; + +class LLPanelExperienceInfo + : public LLPanel +{ +public: + static LLPanelExperienceInfo* create(); + + void onOpen(const LLSD& key); + void setExperienceName( const std::string& name ); + void setExperienceDesc( const std::string& desc ); + + + virtual void setExitCallback(const commit_callback_t& cb); +}; + + +class LLPanelExperiences + : public LLPanel /*LLPanelProfileTab*/ +{ +public: + LLPanelExperiences(); + + static void* create(void* data); + + /*virtual*/ BOOL postBuild(void); + + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ void onClosePanel(); + + void updateData(); + + LLExperienceItem* getSelectedExperienceItem(); + + void setProfilePanel(LLPanelProfile* profile_panel); + +protected: + + void onListCommit(const LLFlatListView* f_list); + void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); + + + void openExperienceInfo(); + void createExperienceInfoPanel(); + void onPanelExperienceClose(LLPanel* panel); + LLPanelProfile* getProfilePanel(); +private: + LLFlatListView* mExperiencesList; + LLAccordionCtrlTab* mExperiencesAccTab; + LLPanelProfile* mProfilePanel; + LLPanelExperienceInfo* mPanelExperienceInfo; + bool mNoExperiences; +}; + + +class LLExperienceItem + : public LLPanel + //, public LLAvatarPropertiesObserver +{ +public: + LLExperienceItem(); + ~LLExperienceItem(); + + void init(LLExperienceData* experience_data); + /*virtual*/ BOOL postBuild(); + void update(); + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + + void setCreatorID(const LLUUID& val) { mCreatorID = val; } + void setExperienceDescription(const std::string& val); + void setExperienceName(const std::string& val); + + const LLUUID& getCreatorID() const { return mCreatorID; } + const std::string& getExperienceName() const { return mExperienceName; } + const std::string& getExperienceDescription() const { return mExperienceDescription; } + +protected: + LLUUID mCreatorID; + + std::string mExperienceName; + std::string mExperienceDescription; +}; +#endif // LL_LLPANELEXPERIENCES_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3d1fd74ba6..ec8415b28e 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -47,6 +47,7 @@ #include "llares.h" #include "llavatarnamecache.h" +#include "llexperiencecache.h" #include "lllandmark.h" #include "llcachename.h" #include "lldir.h" @@ -1398,6 +1399,9 @@ bool idle_startup() LLStartUp::initNameCache(); display_startup(); + LLStartUp::initExperienceCache(); + display_startup(); + // update the voice settings *after* gCacheName initialization // so that we can construct voice UI that relies on the name cache LLVoiceClient::getInstance()->updateSettings(); @@ -2809,6 +2813,13 @@ void LLStartUp::initNameCache() LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); } + +void LLStartUp::initExperienceCache() +{ + LLAppViewer::instance()->loadExperienceCache(); + LLExperienceCache::initClass(false); +} + void LLStartUp::cleanupNameCache() { LLAvatarNameCache::cleanupClass(); @@ -3504,3 +3515,4 @@ void transition_back_to_login_panel(const std::string& emsg) reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); gSavedSettings.setBOOL("AutoLogin", FALSE); } + diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 760e38890b..00e03bcda6 100755 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -91,6 +91,7 @@ public: static void fontInit(); static void initNameCache(); + static void initExperienceCache(); static void cleanupNameCache(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1f7cf0cdd4..5582d256f8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -56,6 +56,7 @@ #include "llfloatereditsky.h" #include "llfloatereditwater.h" #include "llfloaterenvironmentsettings.h" +#include "llfloaterexperiences.h" #include "llfloaterevent.h" #include "llfloaterdestinations.h" #include "llfloaterfonttest.h" @@ -204,7 +205,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("env_edit_day_cycle", "floater_edit_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditDayCycle>); LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>); - + LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>); + LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>); LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 627238b0f5..4635138fa3 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -48,6 +48,7 @@ #include "llanimationstates.h" #include "llavatarnamecache.h" #include "llavatarpropertiesprocessor.h" +#include "llexperiencecache.h" #include "llphysicsmotion.h" #include "llviewercontrol.h" #include "llcallingcard.h" // IDEVO for LLAvatarTracker @@ -2516,6 +2517,9 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) idleUpdateBelowWater(); // wind effect uses this idleUpdateWindEffect(); } + + LLExperienceData ed; + LLExperienceCache::get(getID(), &ed); idleUpdateNameTag( root_pos_last ); idleUpdateRenderCost(); diff --git a/indra/newview/skins/default/xui/en/floater_experiences.xml b/indra/newview/skins/default/xui/en/floater_experiences.xml new file mode 100644 index 0000000000..57541c8b35 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_experiences.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> + +<floater + positioning="cascading" + can_close="true" + can_resize="true" + height="400" + help_topic="sidebar_experiences" + min_height="300" + min_width="300" + layout="topleft" + name="floater_experiences" + save_rect="false" + single_instance="true" + reuse_instance="false" + title="EXPERIENCES" + width="400"> + <panel + top="3" + left="3" + layout="topleft" + right="-3" + follows="all" + height="300" + class="experiences_panel" + filename="panel_experiences.xml" + > + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1aa55acf2d..36b1cea701 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -53,6 +53,14 @@ parameter="" /> </menu_item_call> <menu_item_call + label="Experiences..." + name="Experiences" + shortcut="control|E"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="experiences"/> + </menu_item_call> + <menu_item_call label="Places..." name="Places"> <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/panel_experience_info.xml b/indra/newview/skins/default/xui/en/panel_experience_info.xml new file mode 100644 index 0000000000..47f366d857 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_experience_info.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bg_opaque_color="DkGray2" + background_visible="true" + background_opaque="true" + fit_parent="true" + follows="all" + height="120" + label="Experiences" + layout="topleft" + left="0" + name="panel_experience_info" + top_pad="0"> + <text + follows="top|left|right" + font="SansSerifHugeBold" + height="26" + layout="topleft" + left_pad="4" + name="title" + text_color="White" + top="2" + value="Experience Info" + use_ellipses="true" + right="-3"/> + <text + follows="top|left|right" + font="SansSerifBig" + height="20" + layout="topleft" + left_pad="4" + name="name_label" + text_color="White" + left="8" + top_delta="28" + value="Name" + use_ellipses="true" + right="-3" /> + <text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="8" + name="experience_name" + text_color="White" + left="16" + top_delta="22" + value="[loading...]" + use_ellipses="true" + right="-3" /> + <text + follows="top|left|right" + font="SansSerifBig" + height="20" + left="8" + layout="topleft" + left_pad="4" + name="desc_label" + text_color="White" + top_delta="22" + value="Description" + use_ellipses="true" + right="-3" /> + <expandable_text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="8" + name="experience_desc" + text_color="White" + left="16" + top_delta="22" + value="[loading...]" + use_ellipses="true" + right="-3" + word_wrap="true" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_experiences.xml b/indra/newview/skins/default/xui/en/panel_experiences.xml new file mode 100644 index 0000000000..47a3005aae --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_experiences.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<panel + layout="topleft" + top="3" + left="3" + right="-3" + bottom="-3" + label="Experiences" + follows="all"> + <string + name="no_experiences" + value="No experiences."/> + + <accordion + fit_parent="true" + layout="topleft" + top="0" + left="3" + right="-3" + bottom="-3" + single_expansion="true" + follows="all"> + <accordion_tab + name="tab_experiences" + layout="topleft" + top="0" + left="0" + right="-3" + title="Experiences" + follows="all"> + <flat_list_view + name="experiences_list" + layout="topleft" + top="0" + left="0" + follows="all"/> + </accordion_tab> + </accordion> +</panel> |