diff options
Diffstat (limited to 'indra/newview')
180 files changed, 8354 insertions, 3054 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dce0ea73cd..ac5e12c392 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -13,7 +13,6 @@ include(DragDrop) include(EXPAT) include(FMODEX) include(GLOD) -include(GooglePerfTools) include(Hunspell) include(JsonCpp) include(LLAppearance) @@ -263,6 +262,7 @@ set(viewer_SOURCE_FILES llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaternotificationstabbed.cpp + llfloateroutfitsnapshot.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp llfloaterpathfindingcharacters.cpp @@ -403,6 +403,7 @@ set(viewer_SOURCE_FILES llnotificationscripthandler.cpp llnotificationstorage.cpp llnotificationtiphandler.cpp + lloutfitgallery.cpp lloutfitslist.cpp lloutfitobserver.cpp lloutputmonitorctrl.cpp @@ -879,6 +880,7 @@ set(viewer_HEADER_FILES llfloaternamedesc.h llfloaternotificationsconsole.h llfloaternotificationstabbed.h + llfloateroutfitsnapshot.h llfloaterobjectweights.h llfloateropenobject.h llfloaterpathfindingcharacters.h @@ -1009,6 +1011,7 @@ set(viewer_HEADER_FILES llnotificationlistview.h llnotificationmanager.h llnotificationstorage.h + lloutfitgallery.h lloutfitslist.h lloutfitobserver.h lloutputmonitorctrl.h @@ -1140,6 +1143,7 @@ set(viewer_HEADER_FILES llsky.h llslurl.h llsnapshotlivepreview.h + llsnapshotmodel.h llspatialpartition.h llspeakers.h llspeakingindicatormanager.h @@ -1675,7 +1679,7 @@ if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES # *TODO -reenable this once we get server usage sorted out - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS} /LARGEADDRESSAWARE" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE" LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE" ) @@ -1695,20 +1699,8 @@ if (WINDOWS) # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py # and have the build deps get tracked *please* tell me about it. - if(USE_TCMALLOC) - # Configure a var for tcmalloc location, if used. - # Note the need to specify multiple names explicitly. - set(GOOGLE_PERF_TOOLS_SOURCE - ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll - ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll - ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll - ) - endif(USE_TCMALLOC) - - set(COPY_INPUT_DEPENDENCIES # The following commented dependencies are determined at variably at build time. Can't do this here. - #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll @@ -1750,6 +1742,7 @@ if (WINDOWS) SLPlugin media_plugin_quicktime media_plugin_cef + media_plugin_libvlc winmm_shim windows-crash-logger ) @@ -1949,7 +1942,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLLOGIN_LIBRARIES} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} - ${TCMALLOC_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} ) @@ -1965,6 +1957,7 @@ if (LINUX) linux-crash-logger SLPlugin media_plugin_gstreamer010 + media_plugin_libvlc llcommon ) @@ -2072,7 +2065,7 @@ if (DARWIN) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger) add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger) if (ENABLE_SIGNING) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index a2cec7aff4..de197cc337 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -4.0.8 +4.1.3 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6ccf89eabe..e12b8cfecd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -137,6 +137,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>AdvanceOutfitSnapshot</key> + <map> + <key>Comment</key> + <string>Display advanced parameter settings in outfit snaphot interface</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>AgentPause</key> <map> <key>Comment</key> @@ -4504,28 +4515,6 @@ <key>Value</key> <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> - <key>WebProfileURL</key> - <map> - <key>Comment</key> - <string>URL for Web Profiles</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>https://my.secondlife.com/[AGENT_NAME]</string> - </map> - <key>WebProfileNonProductionURL</key> - <map> - <key>Comment</key> - <string>URL for Web Profiles on Non-Production grids</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>https://my-demo.secondlife.com/[AGENT_NAME]</string> - </map> <key>HighResSnapshot</key> <map> <key>Comment</key> @@ -4870,7 +4859,7 @@ <key>InventoryTrashMaxCapacity</key> <map> <key>Comment</key> - <string>Maximum capacity of the Trash folder. User will ve offered to clean it up when exceeded.</string> + <string>Maximum capacity of the Trash folder. User will be offered to clean it up when exceeded.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6343,17 +6332,6 @@ <key>Value</key> <integer>512</integer> </map> - <key>MemProfiling</key> - <map> - <key>Comment</key> - <string>You want to use tcmalloc's memory profiling options.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>MenuAccessKeyTime</key> <map> <key>Comment</key> @@ -7940,6 +7918,17 @@ <key>Value</key> <integer>100000</integer> </map> + <key>PrimTextMaxDrawDistance</key> + <map> + <key>Comment</key> + <string>Maximum draw distance beyond which PRIM_TEXT won't be rendered</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>64.0</real> + </map> <key>ProbeHardwareOnStartup</key> <map> <key>Comment</key> @@ -10024,28 +10013,28 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderUseFarClip</key> - <map> - <key>Comment</key> - <string>If false, frustum culling will ignore far clip plane.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>RenderUseImpostors</key> - <map> - <key>Comment</key> + <key>RenderUseFarClip</key> + <map> + <key>Comment</key> + <string>If false, frustum culling will ignore far clip plane.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>RenderUseImpostors</key> + <map> + <key>Comment</key> <string>OBSOLETE and UNUSED. See RenderAvatarMaxNonImpostors and RenderAvatarMaxComplexity.</string> - <key>Persist</key> + <key>Persist</key> <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> <integer>0</integer> - </map> + </map> <key>RenderAutoMuteByteLimit</key> <map> <key>Comment</key> @@ -10092,6 +10081,17 @@ <key>Value</key> <integer>10</integer> </map> + <key>ComplexityChangesPopUpDelay</key> + <map> + <key>Comment</key> + <string>Delay before viewer will show avatar complexity notice again</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>300</integer> + </map> <key>RenderAvatarMaxComplexity</key> <map> <key>Comment</key> @@ -10104,6 +10104,50 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderHUDObjectsWarning</key> + <map> + <key>Comment</key> + <string>Viewer will warn user about HUD containing to many objects if objects count is above this value</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1000</integer> + </map> + <key>RenderHUDTexturesWarning</key> + <map> + <key>Comment</key> + <string>Viewer will warn user about HUD containing to many textures if texture count is above this value</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>200</integer> + </map> + <key>RenderHUDOversizedTexturesWarning</key> + <map> + <key>Comment</key> + <string>How many textures with size 1024 * 1024 or bigger HUD can contain before notifying user</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>6</integer> + </map> + <key>RenderHUDTexturesMemoryWarning</key> + <map> + <key>Comment</key> + <string>Viewer will warn user about HUD textures using memory above this value (in bytes)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>32000000</integer> + </map> <key>RenderAutoMuteSurfaceAreaLimit</key> <map> <key>Comment</key> @@ -12792,6 +12836,17 @@ <key>Value</key> <real>1.0</real> </map> + <key>LastSystemUIScaleFactor</key> + <map> + <key>Comment</key> + <string>Size of system UI during last run. On Windows 100% (96 DPI) system setting is 1.0 UI size</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> <key>UIScrollbarSize</key> <map> <key>Comment</key> @@ -13287,6 +13342,17 @@ <key>Value</key> <string>1</string> </map> + <key>UpdaterShowReleaseNotes</key> + <map> + <key>Comment</key> + <string>Enables displaying of the Release notes in a web floater after update.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UploadBakedTexOld</key> <map> <key>Comment</key> @@ -14625,6 +14691,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>OutfitGallerySortByName</key> + <map> + <key>Comment</key> + <string>Always sort outfits by name in Outfit Gallery</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>OutfitOperationsTimeout</key> <map> <key>Comment</key> diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 92a5413adb..1dddf52961 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -31,6 +31,8 @@ #include "llcoros.h" #include "lleventcoro.h" #include "llcorehttputil.h" +#include "llexception.h" +#include "stringize.h" #include <algorithm> #include <iterator> @@ -154,13 +156,11 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, } while (false); } - catch (std::exception e) - { - LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL; - } catch (...) { - LL_WARNS() << "Caught unknown exception." << LL_ENDL; + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName() + << "('" << url << "')")); + throw; } mPendingObjectQuota.clear(); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d933537d2e..d8b0787852 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3895,11 +3895,17 @@ void LLAgent::handleTeleportFinished() mIsMaturityRatingChangingDuringTeleport = false; } - // Init SLM Marketplace connection so we know which UI should be used for the user as a merchant - // Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all. - // Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport. - // *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp) - check_merchant_status(); + if (mRegionp) + { + if (mRegionp->capabilitiesReceived()) + { + onCapabilitiesReceivedAfterTeleport(); + } + else + { + mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport)); + } + } } void LLAgent::handleTeleportFailed() @@ -3931,6 +3937,14 @@ void LLAgent::handleTeleportFailed() } } +/*static*/ +void LLAgent::onCapabilitiesReceivedAfterTeleport() +{ + + check_merchant_status(); +} + + void LLAgent::teleportRequest( const U64& region_handle, const LLVector3& pos_local, diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 3a533c2cba..d82ff7a67f 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -676,6 +676,8 @@ private: void handleTeleportFinished(); void handleTeleportFailed(); + static void onCapabilitiesReceivedAfterTeleport(); + //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index b76a66ab39..170e4063a1 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -62,23 +62,37 @@ using namespace LLAvatarAppearanceDefines; /////////////////////////////////////////////////////////////////////////////// -// Callback to wear and start editing an item that has just been created. -void wear_and_edit_cb(const LLUUID& inv_item) +void set_default_permissions(LLViewerInventoryItem* item) { - if (inv_item.isNull()) return; - - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (!item) return; - - LLPermissions perm = item->getPermissions(); + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskNextOwner() != LLFloaterPerms::getNextOwnerPerms("Wearables") + || perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Wearables") + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Wearables")) + { perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); + item->setPermissions(perm); item->updateServer(FALSE); - gInventory.updateItem(item); - gInventory.notifyObservers(); + } +} + +// Callback to wear and start editing an item that has just been created. +void wear_and_edit_cb(const LLUUID& inv_item) +{ + if (inv_item.isNull()) return; + + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (!item) return; + + set_default_permissions(item); + + // item was just created, update even if permissions did not changed + gInventory.updateItem(item); + gInventory.notifyObservers(); // Request editing the item after it gets worn. gAgentWearables.requestEditingWearable(inv_item); @@ -94,13 +108,8 @@ void wear_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); - item->setPermissions(perm); + set_default_permissions(item); - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -253,6 +262,7 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i { LLAppearanceMgr::instance().addCOFItemLink(inv_item, new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription); + editWearable(inv_item); } } @@ -423,7 +433,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, // old_wearable may still be referred to by other inventory items. Revert // unsaved changes so other inventory items aren't affected by the changes // that were just saved. - old_wearable->revertValues(); + old_wearable->revertValuesWithoutUpdate(); } void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) @@ -1364,6 +1374,30 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array // LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL; } +std::vector<LLViewerObject*> LLAgentWearables::getTempAttachments() +{ + llvo_vec_t temp_attachs; + if (isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *objectp = (*attachment_iter); + if (objectp && objectp->isTempAttachment()) + { + temp_attachs.push_back(objectp); + } + } + } + } + return temp_attachs; +} + void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove) { if (!isAgentAvatarValid()) return; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 1004482020..b27698fd8f 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -185,6 +185,8 @@ public: static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); + static llvo_vec_t getTempAttachments(); + //-------------------------------------------------------------------- // Signals //-------------------------------------------------------------------- diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 49291ea564..c1f898284a 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -30,6 +30,8 @@ #include "llappviewer.h" #include "llviewercontrol.h" +#include "llexception.h" +#include "stringize.h" #include <openssl/x509_vfy.h> #include <openssl/ssl.h> @@ -534,7 +536,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, // somewhat clumsy, as we may run into errors that do not map directly to curl // error codes. Should be refactored with login refactoring, perhaps. result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT); - result.setMessage(cert_exception.getMessage()); + result.setMessage(cert_exception.what()); LLPointer<LLCertificate> cert = cert_exception.getCert(); cert->ref(); // adding an extra ref here result.setErrorData(cert.get()); @@ -544,13 +546,14 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, catch (LLCertException &cert_exception) { result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE); - result.setMessage(cert_exception.getMessage()); + result.setMessage(cert_exception.what()); LLPointer<LLCertificate> cert = cert_exception.getCert(); cert->ref(); // adding an extra ref here result.setErrorData(cert.get()); } catch (...) { + LOG_UNHANDLED_EXCEPTION(STRINGIZE("('" << url << "')")); // any other odd error, we just handle as a connect error. result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR); } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 549df80fa1..be8877328d 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -48,16 +48,19 @@ - (void) applicationDidFinishLaunching:(NSNotification *)notification { frameTimer = nil; - + [self languageUpdated]; - + if (initViewer()) { - frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; + // Set up recurring calls to oneFrame (repeating timer with timeout 0) + // until applicationShouldTerminate. + frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self + selector:@selector(oneFrame) userInfo:nil repeats:YES]; } else { handleQuit(); } - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; // [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; @@ -96,22 +99,29 @@ - (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender { - if (!runMainLoop()) + // run one frame to assess state + if (!pumpMainLoop()) { + // pumpMainLoop() returns true when done, false if it wants to be + // called again. Since it returned false, do not yet cancel + // frameTimer. handleQuit(); return NSTerminateCancel; } else { + // pumpMainLoop() returned true: it's done. Okay, done with frameTimer. [frameTimer release]; cleanupViewer(); return NSTerminateNow; } } -- (void) mainLoop +- (void) oneFrame { - bool appExiting = runMainLoop(); + bool appExiting = pumpMainLoop(); if (appExiting) { + // Once pumpMainLoop() reports that we're done, cancel frameTimer: + // stop the repetitive calls. [frameTimer release]; [[NSApplication sharedApplication] terminate:self]; } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a1d9786321..92e3cd0279 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include <boost/lexical_cast.hpp> +#include <boost/foreach.hpp> #include "llaccordionctrltab.h" #include "llagent.h" #include "llagentcamera.h" @@ -1517,6 +1518,26 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit) wearInventoryCategory(cat, false, false); } +// Remove existing photo link from outfit folder. +void LLAppearanceMgr::removeOutfitPhoto(const LLUUID& outfit_id) +{ + LLInventoryModel::cat_array_t sub_cat_array; + LLInventoryModel::item_array_t outfit_item_array; + gInventory.collectDescendents( + outfit_id, + sub_cat_array, + outfit_item_array, + LLInventoryModel::EXCLUDE_TRASH); + BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array) + { + LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem(); + if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) + { + gInventory.removeItem(outfit_item->getUUID()); + } + } +} + // Open outfit renaming dialog. void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id) { @@ -1854,15 +1875,15 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return false; } - // Check whether the outfit contains any wearables we aren't wearing already (STORM-702). + // Check whether the outfit contains any wearables LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); + LLFindWearables is_wearable; gInventory.collectDescendentsIf(outfit_cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, - is_worn); + is_wearable); return items.size() > 0; } @@ -2945,6 +2966,16 @@ void LLAppearanceMgr::updateIsDirty() gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items, LLInventoryModel::EXCLUDE_TRASH, collector); + for (U32 i = 0; i < outfit_items.size(); ++i) + { + LLViewerInventoryItem* linked_item = outfit_items.at(i)->getLinkedItem(); + if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) + { + outfit_items.erase(outfit_items.begin() + i); + break; + } + } + if(outfit_items.size() != cof_items.size()) { LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL; @@ -3092,6 +3123,14 @@ void appearance_mgr_update_dirty_state() { if (LLAppearanceMgr::instanceExists()) { + LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); + LLUUID image_id = app_mgr.getOutfitImage(); + if(image_id.notNull()) + { + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_object(app_mgr.getBaseOutfitUUID(), image_id, cb); + } + LLAppearanceMgr::getInstance()->updateIsDirty(); LLAppearanceMgr::getInstance()->setOutfitLocked(false); gAgentWearables.notifyLoadingFinished(); @@ -3101,7 +3140,21 @@ void appearance_mgr_update_dirty_state() void update_base_outfit_after_ordering() { LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); - + LLInventoryModel::cat_array_t sub_cat_array; + LLInventoryModel::item_array_t outfit_item_array; + gInventory.collectDescendents(app_mgr.getBaseOutfitUUID(), + sub_cat_array, + outfit_item_array, + LLInventoryModel::EXCLUDE_TRASH); + BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array) + { + LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem(); + if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) + { + app_mgr.setOutfitImage(linked_item->getLinkedUUID()); + } + } + LLPointer<LLInventoryCallback> dirty_state_updater = new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); @@ -3424,13 +3477,13 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd } else { - if (cofVersion < lastRcv) + if (cofVersion <= lastRcv) { LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv << " but requesting for " << cofVersion << LL_ENDL; return; } - if (lastReq > cofVersion) + if (lastReq >= cofVersion) { LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq << " but requesting for " << cofVersion << LL_ENDL; @@ -3450,7 +3503,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd LL_WARNS("Avatar") << "Forcing version failure on COF Baking" << LL_ENDL; } - LL_INFOS() << "Requesting bake for COF version " << cofVersion << LL_ENDL; + LL_INFOS("Avatar") << "Requesting bake for COF version " << cofVersion << LL_ENDL; LLSD postData; if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate")) @@ -3916,6 +3969,10 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << LL_ENDL; mAttachmentInvLinkEnabled = val; } +boost::signals2::connection LLAppearanceMgr::setAttachmentsChangedCallback(attachments_changed_callback_t cb) +{ + return mAttachmentsChangeSignal.connect(cb); +} void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg) { @@ -3942,6 +3999,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); LLAttachmentsMgr::instance().onAttachmentArrived(item_id); + + mAttachmentsChangeSignal(); } void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) @@ -3962,6 +4021,8 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; } + + mAttachmentsChangeSignal(); } BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 7069da7352..f0d3f80f59 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -61,6 +61,7 @@ public: void changeOutfit(bool proceed, const LLUUID& category, bool append); void replaceCurrentOutfit(const LLUUID& new_outfit); void renameOutfit(const LLUUID& outfit_id); + void removeOutfitPhoto(const LLUUID& outfit_id); void takeOffOutfit(const LLUUID& cat_id); void addCategoryToCurrentOutfit(const LLUUID& cat_id); S32 findExcessOrDuplicateItems(const LLUUID& cat_id, @@ -184,6 +185,9 @@ public: void wearBaseOutfit(); + void setOutfitImage(const LLUUID& image_id) {mCOFImageID = image_id;} + LLUUID getOutfitImage() {return mCOFImageID;} + // Overrides the base outfit with the content from COF // @return false if there is no base outfit bool updateBaseOutfit(); @@ -225,6 +229,10 @@ public: void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } std::string getAppearanceServiceURL() const; + typedef boost::function<void ()> attachments_changed_callback_t; + typedef boost::signals2::signal<void ()> attachments_changed_signal_t; + boost::signals2::connection setAttachmentsChangedCallback(attachments_changed_callback_t cb); + private: @@ -268,6 +276,10 @@ private: LLTimer mInFlightTimer; static bool mActive; + attachments_changed_signal_t mAttachmentsChangeSignal; + + LLUUID mCOFImageID; + std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; // Set of temp attachment UUIDs that should be removed diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6bc1f67e32..0813f2c359 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -122,15 +122,20 @@ #include "llleap.h" #include "stringize.h" #include "llcoros.h" +#include "llexception.h" #if !LL_LINUX #include "cef/llceflib.h" -#endif +#if LL_WINDOWS +#include "vlc/libvlc_version.h" +#endif // LL_WINDOWS +#endif // LL_LINUX // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string.hpp> #include <boost/regex.hpp> +#include <boost/throw_exception.hpp> #if LL_WINDOWS # include <share.h> // For _SH_DENYWR in processMarkerFiles @@ -201,6 +206,7 @@ #include "llcommandlineparser.h" #include "llfloatermemleak.h" #include "llfloaterreg.h" +#include "llfloateroutfitsnapshot.h" #include "llfloatersnapshot.h" #include "llfloaterinventory.h" @@ -231,7 +237,6 @@ #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" - // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -696,7 +701,8 @@ LLAppViewer::LLAppViewer() mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), mFastTimerLogThread(NULL), mUpdater(new LLUpdaterService()), - mSettingsLocationList(NULL) + mSettingsLocationList(NULL), + mIsFirstRun(false) { if(NULL != sInstance) { @@ -769,9 +775,6 @@ bool LLAppViewer::init() // // Start of the application // -#ifdef LL_DARWIN - mMainLoopInitialized = false; -#endif // initialize LLWearableType translation bridge. // Memory will be cleaned up in ::cleanupClass() @@ -925,7 +928,7 @@ bool LLAppViewer::init() // Provide the text fields with callbacks for opening Urls LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null)); - LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null)); + LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false)); LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null)); LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); @@ -1122,17 +1125,23 @@ bool LLAppViewer::init() #if LL_WINDOWS if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) { + std::string url; if (gGLManager.mIsIntel) { - LLNotificationsUtil::add("IntelOldDriver"); + url = LLTrans::getString("IntelDriverPage"); } else if (gGLManager.mIsNVIDIA) { - LLNotificationsUtil::add("NVIDIAOldDriver"); + url = LLTrans::getString("NvidiaDriverPage"); } else if (gGLManager.mIsATI) { - LLNotificationsUtil::add("AMDOldDriver"); + url = LLTrans::getString("AMDDriverPage"); + } + + if (!url.empty()) + { + LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url)); } } #endif @@ -1220,6 +1229,25 @@ bool LLAppViewer::init() boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + showReleaseNotesIfRequired(); + + /*----------------------------------------------------------------------*/ + // nat 2016-06-29 moved the following here from the former mainLoop(). + mMainloopTimeout = new LLWatchdogTimeout(); + + // Create IO Pump to use for HTTP Requests. + gServicePump = new LLPumpIO(gAPRPoolp); + + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. + + LLVoiceChannel::initClass(); + LLVoiceClient::getInstance()->init(gServicePump); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); + + joystick = LLViewerJoystick::getInstance(); + joystick->setNeedsReset(true); + /*----------------------------------------------------------------------*/ + return true; } @@ -1294,299 +1322,266 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update"); // externally visible timers LLTrace::BlockTimerStatHandle FTM_FRAME("Frame"); -bool LLAppViewer::mainLoop() +bool LLAppViewer::frame() { -#ifdef LL_DARWIN - if (!mMainLoopInitialized) -#endif - { - LL_INFOS() << "Entering main_loop" << LL_ENDL; - mMainloopTimeout = new LLWatchdogTimeout(); - - //------------------------------------------- - // Run main loop until time to quit - //------------------------------------------- - - // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO(gAPRPoolp); - - // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. - - LLVoiceChannel::initClass(); - LLVoiceClient::getInstance()->init(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); - - joystick = LLViewerJoystick::getInstance(); - joystick->setNeedsReset(true); - -#ifdef LL_DARWIN - // Ensure that this section of code never gets called again on OS X. - mMainLoopInitialized = true; -#endif - } - // As we do not (yet) send data on the mainloop LLEventPump that varies - // with each frame, no need to instantiate a new LLSD event object each - // time. Obviously, if that changes, just instantiate the LLSD at the - // point of posting. - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - - LLSD newFrame; - + LLSD newFrame; + LLTimer frameTimer,idleTimer; LLTimer debugTime; - + //LLPrivateMemoryPoolTester::getInstance()->run(false) ; //LLPrivateMemoryPoolTester::getInstance()->run(true) ; //LLPrivateMemoryPoolTester::destroy() ; - // Handle messages -#ifdef LL_DARWIN - if (!LLApp::isExiting()) -#else - while (!LLApp::isExiting()) -#endif + LL_RECORD_BLOCK_TIME(FTM_FRAME); + LLTrace::BlockTimer::processTimes(); + LLTrace::get_frame_recording().nextPeriod(); + LLTrace::BlockTimer::logStats(); + + LLTrace::get_thread_recorder()->pullFromChildren(); + + //clear call stack records + LL_CLEAR_CALLSTACKS(); + + //check memory availability information + checkMemory() ; + + try { - LL_RECORD_BLOCK_TIME(FTM_FRAME); - LLTrace::BlockTimer::processTimes(); - LLTrace::get_frame_recording().nextPeriod(); - LLTrace::BlockTimer::logStats(); + pingMainloopTimeout("Main:MiscNativeWindowEvents"); + + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + gViewerWindow->getWindow()->processMiscNativeEvents(); + } - LLTrace::get_thread_recorder()->pullFromChildren(); + pingMainloopTimeout("Main:GatherInput"); - //clear call stack records - LL_CLEAR_CALLSTACKS(); + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + if (!restoreErrorTrap()) + { + LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; + } - //check memory availability information - checkMemory() ; + gViewerWindow->getWindow()->gatherInput(); + } + +#if 1 && !LL_RELEASE_FOR_DOWNLOAD + // once per second debug info + if (debugTime.getElapsedTimeF32() > 1.f) + { + debugTime.reset(); + } - try +#endif + //memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - pingMainloopTimeout("Main:MiscNativeWindowEvents"); + mem_leak_instance->idle() ; + } - if (gViewerWindow) + // canonical per-frame event + mainloop.post(newFrame); + + if (!LLApp::isExiting()) + { + pingMainloopTimeout("Main:JoystickKeyboard"); + + // Scan keyboard for movement keys. Command keys and typing + // are handled by windows callbacks. Don't do this until we're + // done initializing. JC + if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) + && gViewerWindow->getActive() + && !gViewerWindow->getWindow()->getMinimized() + && LLStartUp::getStartupState() == STATE_STARTED + && (gHeadlessClient || !gViewerWindow->getShowProgress()) + && !gFocusMgr.focusLocked()) { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - gViewerWindow->getWindow()->processMiscNativeEvents(); + joystick->scanJoystick(); + gKeyboard->scanKeyboard(); } - - pingMainloopTimeout("Main:GatherInput"); - - if (gViewerWindow) + + // Update state based on messages, user input, object idle. { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - if (!restoreErrorTrap()) - { - LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; - } + pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! + + LL_RECORD_BLOCK_TIME(FTM_IDLE); + idle(); - gViewerWindow->getWindow()->gatherInput(); + resumeMainloopTimeout(); } -#if 1 && !LL_RELEASE_FOR_DOWNLOAD - // once per second debug info - if (debugTime.getElapsedTimeF32() > 1.f) + if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) { - debugTime.reset(); + pauseMainloopTimeout(); + saveFinalSnapshot(); + disconnectViewer(); + resumeMainloopTimeout(); } - -#endif - //memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if(mem_leak_instance) - { - mem_leak_instance->idle() ; - } - // canonical per-frame event - mainloop.post(newFrame); - - if (!LLApp::isExiting()) + // Render scene. + // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 + if (!LLApp::isExiting() && !gHeadlessClient) { - pingMainloopTimeout("Main:JoystickKeyboard"); - - // Scan keyboard for movement keys. Command keys and typing - // are handled by windows callbacks. Don't do this until we're - // done initializing. JC - if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) - && gViewerWindow->getActive() - && !gViewerWindow->getWindow()->getMinimized() - && LLStartUp::getStartupState() == STATE_STARTED - && (gHeadlessClient || !gViewerWindow->getShowProgress()) - && !gFocusMgr.focusLocked()) - { - joystick->scanJoystick(); - gKeyboard->scanKeyboard(); - } + pingMainloopTimeout("Main:Display"); + gGLActive = TRUE; + display(); + pingMainloopTimeout("Main:Snapshot"); + LLFloaterSnapshot::update(); // take snapshots + LLFloaterOutfitSnapshot::update(); + gGLActive = FALSE; + } + } - // Update state based on messages, user input, object idle. - { - pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - - LL_RECORD_BLOCK_TIME(FTM_IDLE); - idle(); + pingMainloopTimeout("Main:Sleep"); - resumeMainloopTimeout(); - } - - if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) - { - pauseMainloopTimeout(); - saveFinalSnapshot(); - disconnectViewer(); - resumeMainloopTimeout(); - } + pauseMainloopTimeout(); + + // Sleep and run background threads + { + LL_RECORD_BLOCK_TIME(FTM_SLEEP); + + // yield some time to the os based on command line option + if(mYieldTime >= 0) + { + LL_RECORD_BLOCK_TIME(FTM_YIELD); + ms_sleep(mYieldTime); + } - // Render scene. - // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 - if (!LLApp::isExiting() && !gHeadlessClient) + // yield cooperatively when not running as foreground window + if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) + || !gFocusMgr.getAppHasFocus()) + { + // Sleep if we're not rendering, or the window is minimized. + S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); + // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads + // of equal priority on Windows + if (milliseconds_to_sleep > 0) { - pingMainloopTimeout("Main:Display"); - gGLActive = TRUE; - display(); - pingMainloopTimeout("Main:Snapshot"); - LLFloaterSnapshot::update(); // take snapshots - gGLActive = FALSE; + ms_sleep(milliseconds_to_sleep); + // also pause worker threads during this wait period + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); } } - - pingMainloopTimeout("Main:Sleep"); - pauseMainloopTimeout(); + if (mRandomizeFramerate) + { + ms_sleep(rand() % 200); + } - // Sleep and run background threads + if (mPeriodicSlowFrame + && (gFrameCount % 10 == 0)) { - LL_RECORD_BLOCK_TIME(FTM_SLEEP); - - // yield some time to the os based on command line option - if(mYieldTime >= 0) - { - LL_RECORD_BLOCK_TIME(FTM_YIELD); - ms_sleep(mYieldTime); - } + LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; + ms_sleep(500); + } + + const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second + idleTimer.reset(); + S32 total_work_pending = 0; + S32 total_io_pending = 0; + while(1) + { + S32 work_pending = 0; + S32 io_pending = 0; + F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); + + work_pending += updateTextureThreads(max_time); - // yield cooperatively when not running as foreground window - if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus()) { - // Sleep if we're not rendering, or the window is minimized. - S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); - // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads - // of equal priority on Windows - if (milliseconds_to_sleep > 0) - { - ms_sleep(milliseconds_to_sleep); - // also pause worker threads during this wait period - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); - } + LL_RECORD_BLOCK_TIME(FTM_VFS); + io_pending += LLVFSThread::updateClass(1); } - - if (mRandomizeFramerate) { - ms_sleep(rand() % 200); + LL_RECORD_BLOCK_TIME(FTM_LFS); + io_pending += LLLFSThread::updateClass(1); } - if (mPeriodicSlowFrame - && (gFrameCount % 10 == 0)) + if (io_pending > 1000) { - LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; - ms_sleep(500); + ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up } - const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second - idleTimer.reset(); - S32 total_work_pending = 0; - S32 total_io_pending = 0; - while(1) - { - S32 work_pending = 0; - S32 io_pending = 0; - F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); - - work_pending += updateTextureThreads(max_time); - - { - LL_RECORD_BLOCK_TIME(FTM_VFS); - io_pending += LLVFSThread::updateClass(1); - } - { - LL_RECORD_BLOCK_TIME(FTM_LFS); - io_pending += LLLFSThread::updateClass(1); - } - - if (io_pending > 1000) - { - ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up - } - - total_work_pending += work_pending ; - total_io_pending += io_pending ; - - if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) - { - break; - } - } - gMeshRepo.update() ; + total_work_pending += work_pending ; + total_io_pending += io_pending ; - if(!total_work_pending) //pause texture fetching threads if nothing to process. + if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) { - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); - LLAppViewer::getTextureFetch()->pause(); + break; } - if(!total_io_pending) //pause file threads if nothing to process. - { - LLVFSThread::sLocal->pause(); - LLLFSThread::sLocal->pause(); - } + } + gMeshRepo.update() ; + + if(!total_work_pending) //pause texture fetching threads if nothing to process. + { + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); + LLAppViewer::getTextureFetch()->pause(); + } + if(!total_io_pending) //pause file threads if nothing to process. + { + LLVFSThread::sLocal->pause(); + LLLFSThread::sLocal->pause(); + } - //texture fetching debugger - if(LLTextureFetchDebugger::isEnabled()) + //texture fetching debugger + if(LLTextureFetchDebugger::isEnabled()) + { + LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = + LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); + if(tex_fetch_debugger_instance) { - LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = - LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); - if(tex_fetch_debugger_instance) - { - tex_fetch_debugger_instance->idle() ; - } + tex_fetch_debugger_instance->idle() ; } + } - if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && - (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) - { - gFrameStalls++; - } - frameTimer.reset(); + if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && + (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) + { + gFrameStalls++; + } + frameTimer.reset(); - resumeMainloopTimeout(); - - pingMainloopTimeout("Main:End"); - } + resumeMainloopTimeout(); + + pingMainloopTimeout("Main:End"); } - catch(std::bad_alloc) - { - LLMemory::logMemoryInfo(TRUE) ; + } + catch (const LLContinueError&) + { + LOG_UNHANDLED_EXCEPTION(""); + } + catch(std::bad_alloc) + { + LLMemory::logMemoryInfo(TRUE) ; - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if(mem_leak_instance) - { - mem_leak_instance->stop() ; - LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; - } - else - { - //output possible call stacks to log file. - LLError::LLCallStacks::print() ; + //stop memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) + { + mem_leak_instance->stop() ; + LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; + } + else + { + //output possible call stacks to log file. + LLError::LLCallStacks::print() ; - LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; - } + LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; } } + catch (...) + { + CRASH_ON_UNHANDLED_EXCEPTION(""); + } if (LLApp::isExiting()) { @@ -1600,7 +1595,7 @@ bool LLAppViewer::mainLoop() catch(std::bad_alloc) { LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ; - + //stop memory leaking simulation LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); @@ -1609,16 +1604,20 @@ bool LLAppViewer::mainLoop() mem_leak_instance->stop() ; } } + catch (...) + { + CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()"); + } } - + delete gServicePump; - + destroyMainloopTimeout(); - + LL_INFOS() << "Exiting main_loop" << LL_ENDL; } - return LLApp::isExiting(); + return ! LLApp::isRunning(); } S32 LLAppViewer::updateTextureThreads(F32 max_time) @@ -2483,7 +2482,10 @@ bool LLAppViewer::initConfiguration() if (gSavedSettings.getBOOL("FirstRunThisInstall")) { - // Note that the "FirstRunThisInstall" settings is currently unused. + // Set firstrun flag to indicate that some further init actiona should be taken + // like determining screen DPI value and so on + mIsFirstRun = true; + gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); } @@ -3140,7 +3142,8 @@ bool LLAppViewer::initWindow() .min_width(gSavedSettings.getU32("MinWindowWidth")) .min_height(gSavedSettings.getU32("MinWindowHeight")) .fullscreen(gSavedSettings.getBOOL("FullScreen")) - .ignore_pixel_depth(ignorePixelDepth); + .ignore_pixel_depth(ignorePixelDepth) + .first_run(mIsFirstRun); gViewerWindow = new LLViewerWindow(window_params); @@ -3277,6 +3280,7 @@ LLSD LLAppViewer::getViewerInfo() const if (build_config != "Release") { info["BUILD_CONFIG"] = build_config; + info["ADDRESS_SIZE"] = ADDRESS_SIZE; } // return a URL to the release notes for this viewer, such as: @@ -3342,6 +3346,19 @@ LLSD LLAppViewer::getViewerInfo() const info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION; #else info["LLCEFLIB_VERSION"] = "Undefined"; + +#endif + +#if LL_WINDOWS + std::ostringstream ver_codec; + ver_codec << LIBVLC_VERSION_MAJOR; + ver_codec << "."; + ver_codec << LIBVLC_VERSION_MINOR; + ver_codec << "."; + ver_codec << LIBVLC_VERSION_REVISION; + info["LIBVLC_VERSION"] = ver_codec.str(); +#else + info["LIBVLC_VERSION"] = "Undefined"; #endif S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); @@ -5546,8 +5563,7 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; - // *FIX: Any way to insure it won't be handled? - throw; + LLTHROW(LLException("User selected Force Software Exception")); } void LLAppViewer::forceErrorDriverCrash() @@ -5799,6 +5815,20 @@ void LLAppViewer::launchUpdater() // LLAppViewer::instance()->forceQuit(); } +/** +* Check if user is running a new version of the viewer. +* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. +*/ +void LLAppViewer::showReleaseNotesIfRequired() +{ + if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion + && gSavedSettings.getBOOL("UpdaterShowReleaseNotes") + && !gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + LLSD info(getViewerInfo()); + LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); + } +} //virtual void LLAppViewer::setMasterSystemAudioMute(bool mute) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b5e674bd7b..948d316009 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -79,7 +79,7 @@ public: // virtual bool init(); // Override to do application initialization virtual bool cleanup(); // Override to do application cleanup - virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. + virtual bool frame(); // Override for application body logic // Application control void flushVFSIO(); // waits for vfs transfers to complete @@ -254,6 +254,8 @@ private: void sendLogoutRequest(); void disconnectViewer(); + + void showReleaseNotesIfRequired(); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. @@ -283,7 +285,6 @@ private: std::string mSerialNumber; bool mPurgeCache; bool mPurgeOnExit; - bool mMainLoopInitialized; LLViewerJoystick* joystick; bool mSavedFinalSnapshot; @@ -316,6 +317,7 @@ private: // llcorehttp library init/shutdown helper LLAppCoreHttp mAppCoreHttp; + bool mIsFirstRun; //--------------------------------------------- //*NOTE: Mani - legacy updater stuff // Still useable? diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index f5742b29cf..6f32aab851 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -95,10 +95,8 @@ int main( int argc, char **argv ) } // Run the application main loop - if(!LLApp::isQuitting()) - { - viewer_app_ptr->mainLoop(); - } + while (! viewer_app_ptr->frame()) + {} if (!LLApp::isError()) { diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index ca219fda59..4fe1e31668 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -117,12 +117,17 @@ void handleQuit() LLAppViewer::instance()->userQuit(); } -bool runMainLoop() +// This function is called pumpMainLoop() rather than runMainLoop() because +// it passes control to the viewer's main-loop logic for a single frame. Like +// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it +// expects to be called again by the timer in LLAppDelegate +// (llappdelegate-objc.mm). +bool pumpMainLoop() { bool ret = LLApp::isQuitting(); if (!ret && gViewerAppPtr != NULL) { - ret = gViewerAppPtr->mainLoop(); + ret = gViewerAppPtr->frame(); } else { ret = true; } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4786f83bfd..5107030476 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -231,6 +231,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, DWORD heap_enable_lfh_error[MAX_HEAPS]; S32 num_heaps = 0; + LLWindowWin32::setDPIAwareness(); + #if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit #elif 0 @@ -317,10 +319,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } // Run the application main loop - if(!LLApp::isQuitting()) - { - viewer_app_ptr->mainLoop(); - } + while (! viewer_app_ptr->frame()) + {} if (!LLApp::isError()) { @@ -330,33 +330,33 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, // app cleanup if there was a problem. // #if WINDOWS_CRT_MEM_CHECKS - LL_INFOS() << "CRT Checking memory:" << LL_ENDL; - if (!_CrtCheckMemory()) - { - LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL; - } - else - { - LL_INFOS() << " No corruption detected." << LL_ENDL; - } + LL_INFOS() << "CRT Checking memory:" << LL_ENDL; + if (!_CrtCheckMemory()) + { + LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL; + } + else + { + LL_INFOS() << " No corruption detected." << LL_ENDL; + } #endif - - gGLActive = TRUE; - viewer_app_ptr->cleanup(); - + gGLActive = TRUE; + + viewer_app_ptr->cleanup(); + #if WINDOWS_CRT_MEM_CHECKS - LL_INFOS() << "CRT Checking memory:" << LL_ENDL; - if (!_CrtCheckMemory()) - { - LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL; - } - else - { - LL_INFOS() << " No corruption detected." << LL_ENDL; - } + LL_INFOS() << "CRT Checking memory:" << LL_ENDL; + if (!_CrtCheckMemory()) + { + LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL; + } + else + { + LL_INFOS() << " No corruption detected." << LL_ENDL; + } #endif - + } delete viewer_app_ptr; viewer_app_ptr = NULL; @@ -569,7 +569,7 @@ bool LLAppViewerWin32::initHardwareTest() // Do driver verification and initialization based on DirectX // hardware polling and driver versions // - if (FALSE == gSavedSettings.getBOOL("NoHardwareProbe")) + if (TRUE == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && FALSE == gSavedSettings.getBOOL("NoHardwareProbe")) { // per DEV-11631 - disable hardware probing for everything // but vram. diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index a6e745448a..7b8c630837 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -950,15 +950,22 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); if (inventory_selected.empty()) return false; // nothing selected + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); bool can_share = true; std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end(); for (; it != it_end; ++it) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); - // any category can be offered. + LLUUID cat_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID(); + LLViewerInventoryCategory* inv_cat = gInventory.getCategory(cat_id); + // any category can be offered if it's not in trash. if (inv_cat) { + if ((cat_id == trash_id) || gInventory.isObjectDescendentOf(cat_id, trash_id)) + { + can_share = false; + break; + } continue; } diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp index 24934fdb73..94584a623b 100644 --- a/indra/newview/llavatarrendernotifier.cpp +++ b/indra/newview/llavatarrendernotifier.cpp @@ -38,6 +38,7 @@ #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnotificationtemplate.h" +#include "llslurl.h" #include "lltimer.h" #include "llvoavatarself.h" #include "llviewercontrol.h" @@ -51,6 +52,11 @@ static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1; // wait seconds before processing over limit updates after last complexity change static const U32 OVER_LIMIT_UPDATE_DELAY = 70; +static const U32 WARN_HUD_OBJECTS_LIMIT = 1000; +static const U32 WARN_HUD_TEXTURES_LIMIT = 200; +static const U32 WARN_HUD_OVERSIZED_TEXTURES_LIMIT = 6; +static const U32 WARN_HUD_TEXTURE_MEMORY_LIMIT = 32000000; // in bytes + LLAvatarRenderNotifier::LLAvatarRenderNotifier() : mAgentsCount(0), @@ -264,3 +270,220 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity) } } +// LLHUDRenderNotifier + +static const char* e_hud_messages[] = +{ + "hud_render_textures_warning", + "hud_render_cramped_warning", + "hud_render_heavy_textures_warning", + "hud_render_cost_warning", + "hud_render_memory_warning", +}; + +LLHUDRenderNotifier::LLHUDRenderNotifier() : +mReportedHUDWarning(WARN_NONE) +{ +} + +LLHUDRenderNotifier::~LLHUDRenderNotifier() +{ +} + +void LLHUDRenderNotifier::updateNotificationHUD(hud_complexity_list_t complexity) +{ + if (!isAgentAvatarValid() || !gAgentWearables.areWearablesLoaded()) + { + // data not ready. + return; + } + + // TODO: + // Find a way to show message with list of issues, but without making it too large + // and intrusive. + + LLHUDComplexity new_total_complexity; + LLHUDComplexity report_complexity; + + hud_complexity_list_t::iterator iter = complexity.begin(); + hud_complexity_list_t::iterator end = complexity.end(); + EWarnLevel warning_level = WARN_NONE; + for (; iter != end; ++iter) + { + LLHUDComplexity object_complexity = *iter; + EWarnLevel object_level = getWarningType(object_complexity, report_complexity); + if (object_level >= 0) + { + warning_level = object_level; + report_complexity = object_complexity; + } + new_total_complexity.objectsCost += object_complexity.objectsCost; + new_total_complexity.objectsCount += object_complexity.objectsCount; + new_total_complexity.texturesCost += object_complexity.texturesCost; + new_total_complexity.texturesCount += object_complexity.texturesCount; + new_total_complexity.largeTexturesCount += object_complexity.largeTexturesCount; + new_total_complexity.texturesMemoryTotal += object_complexity.texturesMemoryTotal; + } + + if (mHUDPopUpDelayTimer.hasExpired() || isNotificationVisible()) + { + if (warning_level >= 0) + { + // Display info about most complex HUD object + // make sure it shown only once unless object's complexity or object itself changed + if (mReportedHUDComplexity.objectId != report_complexity.objectId + || mReportedHUDWarning != warning_level) + { + displayHUDNotification(warning_level, report_complexity.objectId, report_complexity.objectName, report_complexity.jointName); + mReportedHUDComplexity = report_complexity; + mReportedHUDWarning = warning_level; + } + } + else + { + // Check if total complexity is above threshold and above previous warning + // Show warning with highest importance (5m delay between warnings by default) + if (!mReportedHUDComplexity.objectId.isNull()) + { + mReportedHUDComplexity.reset(); + mReportedHUDWarning = WARN_NONE; + } + + warning_level = getWarningType(new_total_complexity, mReportedHUDComplexity); + if (warning_level >= 0 && mReportedHUDWarning != warning_level) + { + displayHUDNotification(warning_level); + } + mReportedHUDComplexity = new_total_complexity; + mReportedHUDWarning = warning_level; + } + } + else if (warning_level >= 0) + { + LL_DEBUGS("HUDdetail") << "HUD individual warning postponed" << LL_ENDL; + } + + if (mLatestHUDComplexity.objectsCost != new_total_complexity.objectsCost + || mLatestHUDComplexity.objectsCount != new_total_complexity.objectsCount + || mLatestHUDComplexity.texturesCost != new_total_complexity.texturesCost + || mLatestHUDComplexity.texturesCount != new_total_complexity.texturesCount + || mLatestHUDComplexity.largeTexturesCount != new_total_complexity.largeTexturesCount + || mLatestHUDComplexity.texturesMemoryTotal != new_total_complexity.texturesMemoryTotal) + { + LL_INFOS("HUDdetail") << "HUD textures count: " << new_total_complexity.texturesCount + << " HUD textures cost: " << new_total_complexity.texturesCost + << " Large textures: " << new_total_complexity.largeTexturesCount + << " HUD objects cost: " << new_total_complexity.objectsCost + << " HUD objects count: " << new_total_complexity.objectsCount << LL_ENDL; + + mLatestHUDComplexity = new_total_complexity; + } +} + +bool LLHUDRenderNotifier::isNotificationVisible() +{ + return mHUDNotificationPtr != NULL && mHUDNotificationPtr->isActive(); +} + +// private static +LLHUDRenderNotifier::EWarnLevel LLHUDRenderNotifier::getWarningType(LLHUDComplexity object_complexity, LLHUDComplexity cmp_complexity) +{ + static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); // ties max HUD cost to avatar cost + static LLCachedControl<U32> max_objects_count(gSavedSettings, "RenderHUDObjectsWarning", WARN_HUD_OBJECTS_LIMIT); + static LLCachedControl<U32> max_textures_count(gSavedSettings, "RenderHUDTexturesWarning", WARN_HUD_TEXTURES_LIMIT); + static LLCachedControl<U32> max_oversized_count(gSavedSettings, "RenderHUDOversizedTexturesWarning", WARN_HUD_OVERSIZED_TEXTURES_LIMIT); + static LLCachedControl<U32> max_texture_memory(gSavedSettings, "RenderHUDTexturesMemoryWarning", WARN_HUD_TEXTURE_MEMORY_LIMIT); + + if (cmp_complexity.texturesMemoryTotal < object_complexity.texturesMemoryTotal + && object_complexity.texturesMemoryTotal > (F64Bytes)max_texture_memory) + { + // Note: Memory might not be accurate since texture is still loading or discard level changes + + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " memory usage over limit, " + << " was " << cmp_complexity.texturesMemoryTotal + << " is " << object_complexity.texturesMemoryTotal << LL_ENDL; + + return WARN_MEMORY; + } + else if ((cmp_complexity.objectsCost < object_complexity.objectsCost + || cmp_complexity.texturesCost < object_complexity.texturesCost) + && max_render_cost > 0 + && object_complexity.objectsCost + object_complexity.texturesCost > max_render_cost) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " complexity over limit," + << " HUD textures cost: " << object_complexity.texturesCost + << " HUD objects cost: " << object_complexity.objectsCost << LL_ENDL; + + return WARN_COST; + } + else if (cmp_complexity.largeTexturesCount < object_complexity.largeTexturesCount + && object_complexity.largeTexturesCount > max_oversized_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains to many large textures: " + << object_complexity.largeTexturesCount << LL_ENDL; + + return WARN_HEAVY; + } + else if (cmp_complexity.texturesCount < object_complexity.texturesCount + && object_complexity.texturesCount > max_textures_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many textures: " + << object_complexity.texturesCount << LL_ENDL; + + return WARN_CRAMPED; + } + else if (cmp_complexity.objectsCount < object_complexity.objectsCount + && object_complexity.objectsCount > max_objects_count) + { + LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many objects: " + << object_complexity.objectsCount << LL_ENDL; + + return WARN_TEXTURES; + } + return WARN_NONE; +} + +void LLHUDRenderNotifier::displayHUDNotification(EWarnLevel warn_type, LLUUID obj_id, std::string obj_name, std::string joint_name) +{ + static LLCachedControl<U32> pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300); + static LLCachedControl<U32> expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20); + LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay); + + // Since we need working "ignoretext" there is no other way but to + // use single notification while constructing it from multiple pieces + LLSD reason_args; + if (obj_id.isNull()) + { + reason_args["HUD_DETAILS"] = LLTrans::getString("hud_description_total"); + } + else + { + if (obj_name.empty()) + { + LL_WARNS("HUDdetail") << "Object name not assigned" << LL_ENDL; + } + if (joint_name.empty()) + { + std::string verb = "select?name=" + LLURI::escape(obj_name); + reason_args["HUD_DETAILS"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString(); + } + else + { + LLSD object_args; + std::string verb = "select?name=" + LLURI::escape(obj_name); + object_args["OBJ_NAME"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString(); + object_args["JNT_NAME"] = LLTrans::getString(joint_name); + reason_args["HUD_DETAILS"] = LLTrans::getString("hud_name_with_joint", object_args); + } + } + + LLSD msg_args; + msg_args["HUD_REASON"] = LLTrans::getString(e_hud_messages[warn_type], reason_args); + + mHUDNotificationPtr = LLNotifications::instance().add(LLNotification::Params() + .name("HUDComplexityWarning") + .expiry(expire_date) + .substitutions(msg_args)); + mHUDPopUpDelayTimer.resetWithExpiry(pop_up_delay); +} + diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index 2a2704de28..a169baef40 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -33,6 +33,36 @@ class LLViewerRegion; +struct LLHUDComplexity +{ + LLHUDComplexity() + { + reset(); + } + void reset() + { + objectId = LLUUID::null; + objectName = ""; + objectsCost = 0; + objectsCount = 0; + texturesCost = 0; + texturesCount = 0; + largeTexturesCount = 0; + texturesMemoryTotal = (F64Bytes)0; + } + LLUUID objectId; + std::string objectName; + std::string jointName; + U32 objectsCost; + U32 objectsCount; + U32 texturesCost; + U32 texturesCount; + U32 largeTexturesCount; + F64Bytes texturesMemoryTotal; +}; + +typedef std::list<LLHUDComplexity> hud_complexity_list_t; + // Class to notify user about drastic changes in agent's render weights or if other agents // reported that user's agent is too 'heavy' for their settings class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier> @@ -81,4 +111,36 @@ private: S32 mLastOutfitRezStatus; }; +// Class to notify user about heavy set of HUD +class LLHUDRenderNotifier : public LLSingleton<LLHUDRenderNotifier> +{ +public: + LLHUDRenderNotifier(); + ~LLHUDRenderNotifier(); + + void updateNotificationHUD(hud_complexity_list_t complexity); + bool isNotificationVisible(); + +private: + enum EWarnLevel + { + WARN_NONE = -1, + WARN_TEXTURES = 0, // least important + WARN_CRAMPED, + WARN_HEAVY, + WARN_COST, + WARN_MEMORY, //most important + }; + + LLNotificationPtr mHUDNotificationPtr; + + static EWarnLevel getWarningType(LLHUDComplexity object_complexity, LLHUDComplexity cmp_complexity); + void displayHUDNotification(EWarnLevel warn_type, LLUUID obj_id = LLUUID::null, std::string object_name = "", std::string joint_name = ""); + + LLHUDComplexity mReportedHUDComplexity; + EWarnLevel mReportedHUDWarning; + LLHUDComplexity mLatestHUDComplexity; + LLFrameTimer mHUDPopUpDelayTimer; +}; + #endif /* ! defined(LL_llavatarrendernotifier_H) */ diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 00fa6dd979..54c6c985d6 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -311,7 +311,8 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) } else if (mesg[0] == '/' && mesg[1] - && LLStringOps::isDigit(mesg[1])) + && (LLStringOps::isDigit(mesg[1]) + || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2])))) { // This a special "/20" speak on a channel S32 pos = 0; @@ -325,7 +326,7 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) channel_string.push_back(c); pos++; } - while(c && pos < 64 && LLStringOps::isDigit(c)); + while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos == 1 && c == '-'))); // Move the pointer forward to the first non-whitespace char // Check isspace before looping, so we can handle "/33foo" diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 1819fc74ee..90a5483dc9 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llcommandlineparser.h" +#include "llexception.h" // *NOTE: The boost::lexical_cast generates // the warning C4701(local used with out assignment) in VC7.1. @@ -50,6 +51,7 @@ #include "llsdserialize.h" #include "llerror.h" #include "stringize.h" +#include "llexception.h" #include <string> #include <set> #include <iostream> @@ -98,14 +100,14 @@ namespace bool gPastLastOption = false; } -class LLCLPError : public std::logic_error { +class LLCLPError : public LLException { public: - LLCLPError(const std::string& what) : std::logic_error(what) {} + LLCLPError(const std::string& what) : LLException(what) {} }; -class LLCLPLastOption : public std::logic_error { +class LLCLPLastOption : public LLException { public: - LLCLPLastOption(const std::string& what) : std::logic_error(what) {} + LLCLPLastOption(const std::string& what) : LLException(what) {} }; class LLCLPValue : public po::value_semantic_codecvt_helper<char> @@ -202,17 +204,17 @@ protected: { if(gPastLastOption) { - throw(LLCLPLastOption("Don't parse no more!")); + LLTHROW(LLCLPLastOption("Don't parse no more!")); } // Error checks. Needed? if (!value_store.empty() && !is_composing()) { - throw(LLCLPError("Non composing value with multiple occurences.")); + LLTHROW(LLCLPError("Non composing value with multiple occurences.")); } if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens()) { - throw(LLCLPError("Illegal number of tokens specified.")); + LLTHROW(LLCLPError("Illegal number of tokens specified.")); } if(value_store.empty()) @@ -466,7 +468,7 @@ onevalue(const std::string& option, { // What does it mean when the user specifies a command-line switch // that requires a value, but omits the value? Complain. - throw LLCLPError(STRINGIZE("No value specified for --" << option << "!")); + LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!"))); } else if (value.size() > 1) { @@ -484,9 +486,9 @@ void badvalue(const std::string& option, // If the user passes an unusable value for a command-line switch, it // seems like a really bad idea to just ignore it, even with a log // warning. - throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option - << "' for variable '" << varname << "' of type " << type - << ": '" << value << "'")); + LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option + << "' for variable '" << varname << "' of type " << type + << ": '" << value << "'"))); } template <typename T> diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 7721e67290..76e16f5a1f 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -67,7 +67,9 @@ namespace const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue"); - + // ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged + // callback mechanism and the LLEventPump coroutine architecture allowing the + // coroutine to wait for the inventory event. class ObjectInventoryFetcher: public LLVOInventoryListener { public: @@ -144,7 +146,7 @@ public: queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM); } - return LLSD().with("success", LLSD::Boolean(true)); + return LLSDMap("success", LLSD::Boolean(true)); } @@ -254,7 +256,6 @@ LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key) setTitle(LLTrans::getString("CompileQueueTitle")); setStartString(LLTrans::getString("CompileQueueStart")); -// mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID())); } LLFloaterCompileQueue::~LLFloaterCompileQueue() @@ -267,7 +268,6 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content ) { mExperienceIds.insert(it->asUUID()); } -// nextObject(); } BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const @@ -277,11 +277,6 @@ BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const // //Attempt to record this asset ID. If it can not be inserted into the set // //then it has already been processed so return false. -// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId) -// { -// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId); -// return result.second; -// } void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult) { @@ -331,8 +326,10 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren queue->experienceIdsReceived(result["experience_ids"]); + // getDerived handle gets a handle that can be resolved to a parent class of the derived object. LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>()); + // note subtle difference here: getDerivedHandle in this case is for an LLFloaterCompileQueue fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript, queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3); @@ -345,37 +342,35 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren } +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { LLSD result; - LLFloaterCompileQueue *that = hfloater.get(); - bool monocompile = that->mMono; + LLCheckedHandle<LLFloaterCompileQueue> floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + bool monocompile = floater->mMono; F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); - if (!that) - return false; // Initial test to see if we can (or should) attempt to compile the script. LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory); - { - if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) || - !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) - { - std::string buffer = "Skipping: " + item->getName() + "(Permissions)"; - that->addStringMessage(buffer); - return true; - } + if (!item) + { + LL_WARNS("SCRIPTQ") << "item retrieved is not an LLInventoryItem." << LL_ENDL; + return true; + } -// if (!that->checkAssetId(item->getAssetUUID())) -// { -// std::string buffer = "Skipping: " + item->getName() + "(Repeat)"; -// that->addStringMessage(buffer); -// return true; -// } + if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) || + !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + { + std::string buffer = "Skipping: " + item->getName() + "(Permissions)"; + floater->addStringMessage(buffer); + return true; } - that = NULL; // Attempt to retrieve the experience LLUUID experienceId; @@ -384,37 +379,30 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1)); result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, - LLSD().with("timeout", LLSD::Boolean(true))); + LLSDMap("timeout", LLSD::Boolean(true))); - that = hfloater.get(); - if (!that) - { - return false; - } - - if (result.has("timeout") && result["timeout"].asBoolean()) - { + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. LLStringUtil::format_map_t args; args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = that->getString("Timeout", args); - that->addStringMessage(buffer); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); return true; } if (result.has(LLExperienceCache::EXPERIENCE_ID)) { experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID(); - if (!that->hasExperience(experienceId)) + if (!floater->hasExperience(experienceId)) { - that->addProcessingMessage("CompileNoExperiencePerm", LLSD() - .with("SCRIPT", inventory->getName()) - .with("EXPERIENCE", result[LLExperienceCache::NAME].asString())); + floater->addProcessingMessage("CompileNoExperiencePerm", + LLSDMap("SCRIPT", inventory->getName()) + ("EXPERIENCE", result[LLExperienceCache::NAME].asString())); return true; } } } - that = NULL; { HandleScriptUserData userData(pump.getName()); @@ -433,32 +421,23 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat &userData); result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, - LLSD().with("timeout", LLSD::Boolean(true))); - } - - that = hfloater.get(); - if (!that) - { - return false; + LLSDMap("timeout", LLSD::Boolean(true))); } if (result.has("timeout")) - { - if (result.has("timeout") && result["timeout"].asBoolean()) - { - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = that->getString("Timeout", args); - that->addStringMessage(buffer); - return true; - } + { // A timeout filed in the result will always be true if present. + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); + return true; } if (result.has("error")) { LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL; std::string buffer = result["message"].asString() + " " + inventory->getName(); - that->addStringMessage(buffer); + floater->addStringMessage(buffer); if (result.has("alert")) { @@ -470,12 +449,9 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat } LLUUID assetId = result["asset_id"]; - that = NULL; - std::string url = object->getRegion()->getCapability("UpdateScriptTask"); - { LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(), inventory->getUUID(), @@ -490,24 +466,15 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); } - result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true))); - - that = hfloater.get(); - if (!that) - { - return false; - } + result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true))); if (result.has("timeout")) - { - if (result.has("timeout") && result["timeout"].asBoolean()) - { - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = that->getString("Timeout", args); - that->addStringMessage(buffer); - return true; - } + { // A timeout filed in the result will always be true if present. + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); + return true; } // Bytecode save completed @@ -515,21 +482,21 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat { std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded"); - that->addStringMessage(buffer); + floater->addStringMessage(buffer); LL_INFOS() << buffer << LL_ENDL; } else { LLSD compile_errors = result["errors"]; std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:"); - that->addStringMessage(buffer); + floater->addStringMessage(buffer); for (LLSD::array_const_iterator line = compile_errors.beginArray(); line < compile_errors.endArray(); line++) { std::string str = line->asString(); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); - that->addStringMessage(str); + floater->addStringMessage(str); } LL_INFOS() << result["errors"] << LL_ENDL; } @@ -576,16 +543,18 @@ LLFloaterResetQueue::~LLFloaterResetQueue() { } -bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { - LLFloaterScriptQueue *that = hfloater.get(); - if (that) - { - std::string buffer; - buffer = that->getString("Resetting") + (": ") + inventory->getName(); - that->addStringMessage(buffer); - } + LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("Resetting") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); @@ -602,6 +571,8 @@ bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hflo bool LLFloaterResetQueue::startQueue() { + // Bind the resetObjectScripts method into a QueueAction function and pass it + // into the object queue processing coroutine. fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts, getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3); @@ -629,16 +600,18 @@ LLFloaterRunQueue::~LLFloaterRunQueue() { } -bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { - LLFloaterScriptQueue *that = hfloater.get(); - if (that) - { - std::string buffer; - buffer = that->getString("Running") + (": ") + inventory->getName(); - that->addStringMessage(buffer); - } + LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("Running") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); @@ -684,16 +657,18 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue() { } +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { - LLFloaterScriptQueue *that = hfloater.get(); - if (that) - { - std::string buffer; - buffer = that->getString("NotRunning") + (": ") + inventory->getName(); - that->addStringMessage(buffer); - } + LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("NotRunning") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); @@ -732,7 +707,7 @@ void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object, mInventoryList.clear(); mInventoryList.assign(inventory->begin(), inventory->end()); - mPump.post(LLSD().with("changed", LLSD::Boolean(true))); + mPump.post(LLSDMap("changed", LLSD::Boolean(true))); } @@ -740,115 +715,97 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L object_data_list_t objectList, fnQueueAction_t func) { LLCoros::set_consuming(true); - LLFloaterScriptQueue * floater(NULL); + LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // This is expected if the dialog closes. LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true); F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); -// floater = hfloater.get(); -// floater->addProcessingMessage("Starting", -// LLSD() -// .with("[START]", action) -// .with("[COUNT]", LLSD::Integer(objectList.size()))); -// floater = NULL; - for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj) + try { - bool firstForObject = true; - LLUUID object_id = (*itObj).mObjectId; - LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL; - - LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id); - LLInventoryObject::object_list_t inventory; - if (obj) + for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj) { - ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL)); + bool firstForObject = true; + LLUUID object_id = (*itObj).mObjectId; + LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL; - fetcher->fetchInventory(); - - floater = hfloater.get(); - if (floater) + LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id); + LLInventoryObject::object_list_t inventory; + if (obj) { + ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL)); + + fetcher->fetchInventory(); + LLStringUtil::format_map_t args; args["[OBJECT_NAME]"] = (*itObj).mObjectName; floater->addStringMessage(floater->getString("LoadingObjInv", args)); - } - LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout, - LLSD().with("timeout", LLSD::Boolean(true))); + LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout, + LLSDMap("timeout", LLSD::Boolean(true))); - if (result.has("timeout") && result["timeout"].asBoolean()) - { - LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() << - ". Skipping to next object." << LL_ENDL; + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. + LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() << + ". Skipping to next object." << LL_ENDL; - // floater could have been closed - floater = hfloater.get(); - if (floater) - { LLStringUtil::format_map_t args; args["[OBJECT_NAME]"] = (*itObj).mObjectName; floater->addStringMessage(floater->getString("Timeout", args)); + + continue; } + inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end()); + } + else + { + LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id << + ". Skipping to next." << LL_ENDL; continue; } - inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end()); - } - else - { - LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id << - ". Skipping to next." << LL_ENDL; - continue; - } + // TODO: Get the name of the object we are looking at here so that we can display it below. + //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName(); + LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL; - // TODO: Get the name of the object we are looking at here so that we can display it below. - //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName(); - LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL; - - for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin(); - itInv != inventory.end(); ++itInv) - { - floater = hfloater.get(); - if (!floater) + for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin(); + itInv != inventory.end(); ++itInv) { - LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL; - break; - } + floater.check(); - // note, we have a smart pointer to the obj above... but if we didn't we'd check that - // it still exists here. + // note, we have a smart pointer to the obj above... but if we didn't we'd check that + // it still exists here. - if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT)) - { - LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL; - if (firstForObject) + if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT)) { - //floater->addStringMessage(objName + ":"); - firstForObject = false; + LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL; + if (firstForObject) + { + //floater->addStringMessage(objName + ":"); + firstForObject = false; + } + + if (!func(obj, (*itInv), maildrop)) + { + continue; + } } - if (!func(obj, (*itInv), maildrop)) - { - continue; - } + // no other explicit suspension point in this loop. func(...) MIGHT suspend + // but offers no guarantee of doing so. + llcoro::suspend(); } - - llcoro::suspend(); - } - // Just test to be sure the floater is still present before calling the func - if (!hfloater.get()) - { - LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL; - break; } - } - - floater = hfloater.get(); - if (floater) - { floater->addStringMessage("Done"); floater->getChildView("close")->setEnabled(TRUE); } + catch (LLCheckedHandleBase::Stale &) + { + // This is expected. It means that floater has been closed before + // processing was completed. + LL_DEBUGS("SCRIPTQ") << "LLExeceptionStaleHandle caught! Floater has most likely been closed." << LL_ENDL; + } } diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 05c7e6caa5..4e69896b69 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -448,7 +448,12 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s std::string LLConversationLog::getFileName() { std::string filename = "conversation"; - return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename) + ".log"; + std::string log_address = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + if (!log_address.empty()) + { + log_address += ".log"; + } + return log_address; } bool LLConversationLog::saveToFile(const std::string& filename) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index de349a03d4..481c66aaf5 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2132,7 +2132,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a src; U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; + vec[0] = vec[1] = vec[2] = vec[3] = color.asRGBA(); src.loadua((F32*) vec); @@ -2168,7 +2168,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLColor4U glow4u = LLColor4U(0,0,0,glow); - U32 glow32 = glow4u.mAll; + U32 glow32 = glow4u.asRGBA(); U32 vec[4]; vec[0] = vec[1] = vec[2] = vec[3] = glow32; diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index bababca652..c2d0d9f06b 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -108,6 +108,7 @@ private: static const std::string sCheckUpdateListenerName; static void startFetchServerReleaseNotes(); + static void fetchServerReleaseNotesCoro(const std::string& cap_url); static void handleServerReleaseNotes(LLSD results); }; @@ -224,35 +225,62 @@ void LLFloaterAbout::startFetchServerReleaseNotes() // an URL suitable for external browsers in the "Location:" HTTP header. std::string cap_url = region->getCapability("ServerReleaseNotes"); - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url, - &LLFloaterAbout::handleServerReleaseNotes, &LLFloaterAbout::handleServerReleaseNotes); + LLCoros::instance().launch("fetchServerReleaseNotesCoro", boost::bind(&LLFloaterAbout::fetchServerReleaseNotesCoro, cap_url)); } /*static*/ +void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url) +{ + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("fetchServerReleaseNotesCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + httpOpts->setWantHeaders(true); + httpOpts->setFollowRedirects(false); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + handleServerReleaseNotes(httpResults); + } + else + { + handleServerReleaseNotes(result); + } +} + +/*static*/ void LLFloaterAbout::handleServerReleaseNotes(LLSD results) { -// LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about"); -// if (floater_about) -// { - LLSD http_headers; - if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS)) - { - LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; - } - else - { - http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; - } - - std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString(); - if (location.empty()) - { - location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); - } - LLAppViewer::instance()->setServerReleaseNotesURL(location); -// } + LLSD http_headers; + if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS)) + { + LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + } + else + { + http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + } + + std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString(); + if (location.empty()) + { + location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL"); + } + LLAppViewer::instance()->setServerReleaseNotesURL(location); + + LLFloaterAbout* floater_about = LLFloaterReg::findTypedInstance<LLFloaterAbout>("sl_about"); + if (floater_about) + { + floater_about->setSupportText(location); + } } class LLFloaterAboutListener: public LLEventAPI diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 72892b47a4..aa7bfbfdb7 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -55,6 +55,8 @@ //#include "llsdserialize.h" +static const U32 AVATAR_PICKER_SEARCH_TIMEOUT = 180U; + //put it back as a member once the legacy path is out? static std::map<LLUUID, LLAvatarName> sAvatarNameMap; @@ -463,10 +465,13 @@ void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::strin LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL; - LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + httpOpts->setTimeout(AVATAR_PICKER_SEARCH_TIMEOUT); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index e21a8594bc..91436e52fe 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -280,7 +280,7 @@ void LLFloaterBuyCurrencyUI::onClickCancel() void LLFloaterBuyCurrencyUI::onClickErrorWeb() { - LLWeb::loadURLExternal(mManager.errorURI()); + LLWeb::loadURL(mManager.errorURI()); closeFloater(); // Update L$ balance LLStatusBar::sendMoneyBalanceRequest(); diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index da85d378b2..b1d6d8be82 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -87,7 +87,7 @@ S32 compute_jpeg_quality(S32 width, S32 height) { F32 target_compression_ratio = (F32)(width * height * 3) / (F32)(TARGET_DATA_SIZE); S32 quality = (S32)(110.0f - (2.0f * target_compression_ratio)); - return llclamp(quality,MIN_QUALITY,MAX_QUALITY); + return llclamp(quality, MIN_QUALITY, MAX_QUALITY); } /////////////////////////// @@ -95,52 +95,52 @@ S32 compute_jpeg_quality(S32 width, S32 height) /////////////////////////// LLFacebookStatusPanel::LLFacebookStatusPanel() : - mMessageTextEditor(NULL), - mPostButton(NULL), + mMessageTextEditor(NULL), + mPostButton(NULL), mCancelButton(NULL), - mAccountCaptionLabel(NULL), - mAccountNameLabel(NULL), - mPanelButtons(NULL), - mConnectButton(NULL), - mDisconnectButton(NULL) + mAccountCaptionLabel(NULL), + mAccountNameLabel(NULL), + mPanelButtons(NULL), + mConnectButton(NULL), + mDisconnectButton(NULL) { - mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); - mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this)); + mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this)); - setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2)); - mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this)); } BOOL LLFacebookStatusPanel::postBuild() { - mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); - mAccountNameLabel = getChild<LLTextBox>("account_name_label"); - mPanelButtons = getChild<LLUICtrl>("panel_buttons"); - mConnectButton = getChild<LLUICtrl>("connect_btn"); - mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); + mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label"); + mAccountNameLabel = getChild<LLTextBox>("account_name_label"); + mPanelButtons = getChild<LLUICtrl>("panel_buttons"); + mConnectButton = getChild<LLUICtrl>("connect_btn"); + mDisconnectButton = getChild<LLUICtrl>("disconnect_btn"); - mMessageTextEditor = getChild<LLUICtrl>("status_message"); - mPostButton = getChild<LLUICtrl>("post_status_btn"); - mCancelButton = getChild<LLUICtrl>("cancel_status_btn"); + mMessageTextEditor = getChild<LLUICtrl>("status_message"); + mPostButton = getChild<LLUICtrl>("post_status_btn"); + mCancelButton = getChild<LLUICtrl>("cancel_status_btn"); - return LLPanel::postBuild(); + return LLPanel::postBuild(); } void LLFacebookStatusPanel::draw() { - LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); + LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); - //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress - bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; - mDisconnectButton->setEnabled(!disconnecting); + //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress + bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING; + mDisconnectButton->setEnabled(!disconnecting); - //Disable the 'connect' button when a connection is in progress - bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; - mConnectButton->setEnabled(!connecting); + //Disable the 'connect' button when a connection is in progress + bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS; + mConnectButton->setEnabled(!connecting); if (mMessageTextEditor && mPostButton && mCancelButton) - { + { bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); std::string message = mMessageTextEditor->getValue().asString(); mMessageTextEditor->setEnabled(no_ongoing_connection); @@ -148,175 +148,175 @@ void LLFacebookStatusPanel::draw() mPostButton->setEnabled(no_ongoing_connection && !message.empty()); } - LLPanel::draw(); + LLPanel::draw(); } void LLFacebookStatusPanel::onSend() { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendStatus(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1)); + + // Connect to Facebook if necessary and then post + if (LLFacebookConnect::instance().isConnected()) + { + sendStatus(); + } + else + { + LLFacebookConnect::instance().checkConnectionToFacebook(true); + } } bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data) { - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendStatus(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); - clearAndClose(); - break; - } - - return false; + switch (data.get("enum").asInteger()) + { + case LLFacebookConnect::FB_CONNECTED: + sendStatus(); + break; + + case LLFacebookConnect::FB_POSTED: + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); + clearAndClose(); + break; + } + + return false; } bool LLFacebookStatusPanel::onFacebookConnectAccountStateChange(const LLSD& data) { - if(LLFacebookConnect::instance().isConnected()) - { - //In process of disconnecting so leave the layout as is - if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) - { - showConnectedLayout(); - } - } - else - { - showDisconnectedLayout(); - } - - return false; + if (LLFacebookConnect::instance().isConnected()) + { + //In process of disconnecting so leave the layout as is + if (data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING) + { + showConnectedLayout(); + } + } + else + { + showDisconnectedLayout(); + } + + return false; } void LLFacebookStatusPanel::sendStatus() { - std::string message = mMessageTextEditor->getValue().asString(); - if (!message.empty()) - { - LLFacebookConnect::instance().updateStatus(message); - } + std::string message = mMessageTextEditor->getValue().asString(); + if (!message.empty()) + { + LLFacebookConnect::instance().updateStatus(message); + } } void LLFacebookStatusPanel::onVisibilityChange(BOOL visible) { - if(visible) - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1)); - - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); - - //Connected - if(LLFacebookConnect::instance().isConnected()) - { - showConnectedLayout(); - } - //Check if connected (show disconnected layout in meantime) - else - { - showDisconnectedLayout(); - } + if (visible) + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1)); + + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this)); + + //Connected + if (LLFacebookConnect::instance().isConnected()) + { + showConnectedLayout(); + } + //Check if connected (show disconnected layout in meantime) + else + { + showDisconnectedLayout(); + } if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) { LLFacebookConnect::instance().checkConnectionToFacebook(); } - } - else - { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); - LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); - } + } + else + { + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel"); + LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel"); + } } bool LLFacebookStatusPanel::onFacebookConnectInfoChange() { - LLSD info = LLFacebookConnect::instance().getInfo(); - std::string clickable_name; + LLSD info = LLFacebookConnect::instance().getInfo(); + std::string clickable_name; - //Strings of format [http://www.somewebsite.com Click Me] become clickable text - if(info.has("link") && info.has("name")) - { - clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; - } + //Strings of format [http://www.somewebsite.com Click Me] become clickable text + if (info.has("link") && info.has("name")) + { + clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]"; + } - mAccountNameLabel->setText(clickable_name); + mAccountNameLabel->setText(clickable_name); - return false; + return false; } void LLFacebookStatusPanel::showConnectButton() { - if(!mConnectButton->getVisible()) - { - mConnectButton->setVisible(TRUE); - mDisconnectButton->setVisible(FALSE); - } + if (!mConnectButton->getVisible()) + { + mConnectButton->setVisible(TRUE); + mDisconnectButton->setVisible(FALSE); + } } void LLFacebookStatusPanel::hideConnectButton() { - if(mConnectButton->getVisible()) - { - mConnectButton->setVisible(FALSE); - mDisconnectButton->setVisible(TRUE); - } + if (mConnectButton->getVisible()) + { + mConnectButton->setVisible(FALSE); + mDisconnectButton->setVisible(TRUE); + } } void LLFacebookStatusPanel::showDisconnectedLayout() { - mAccountCaptionLabel->setText(getString("facebook_disconnected")); - mAccountNameLabel->setText(std::string("")); - showConnectButton(); + mAccountCaptionLabel->setText(getString("facebook_disconnected")); + mAccountNameLabel->setText(std::string("")); + showConnectButton(); } void LLFacebookStatusPanel::showConnectedLayout() { - LLFacebookConnect::instance().loadFacebookInfo(); + LLFacebookConnect::instance().loadFacebookInfo(); - mAccountCaptionLabel->setText(getString("facebook_connected")); - hideConnectButton(); + mAccountCaptionLabel->setText(getString("facebook_connected")); + hideConnectButton(); } void LLFacebookStatusPanel::onConnect() { - LLFacebookConnect::instance().checkConnectionToFacebook(true); + LLFacebookConnect::instance().checkConnectionToFacebook(true); - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); + //Clear only the facebook browser cookies so that the facebook login screen appears + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::onDisconnect() { - LLFacebookConnect::instance().disconnectFromFacebook(); + LLFacebookConnect::instance().disconnectFromFacebook(); - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); + LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::clearAndClose() { - mMessageTextEditor->setValue(""); + mMessageTextEditor->setValue(""); - LLFloater* floater = getParentByType<LLFloater>(); - if (floater) - { - floater->closeFloater(); - } + LLFloater* floater = getParentByType<LLFloater>(); + if (floater) + { + floater->closeFloater(); + } } /////////////////////////// @@ -324,89 +324,89 @@ void LLFacebookStatusPanel::clearAndClose() /////////////////////////// LLFacebookPhotoPanel::LLFacebookPhotoPanel() : -mResolutionComboBox(NULL), -mRefreshBtn(NULL), -mBtnPreview(NULL), -mWorkingLabel(NULL), -mThumbnailPlaceholder(NULL), -mCaptionTextBox(NULL), -mPostButton(NULL), -mBigPreviewFloater(NULL), -mQuality(MAX_QUALITY) + mResolutionComboBox(NULL), + mRefreshBtn(NULL), + mBtnPreview(NULL), + mWorkingLabel(NULL), + mThumbnailPlaceholder(NULL), + mCaptionTextBox(NULL), + mPostButton(NULL), + mBigPreviewFloater(NULL), + mQuality(MAX_QUALITY) { - mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); - mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); - mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this)); + mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this)); + mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this)); } LLFacebookPhotoPanel::~LLFacebookPhotoPanel() { - if(mPreviewHandle.get()) - { - mPreviewHandle.get()->die(); - } + if (mPreviewHandle.get()) + { + mPreviewHandle.get()->die(); + } } BOOL LLFacebookPhotoPanel::postBuild() { - setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); - - mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); - mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! - mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); - mFilterComboBox = getChild<LLUICtrl>("filters_combobox"); - mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); - mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); - mBtnPreview = getChild<LLButton>("big_preview_btn"); + setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2)); + + mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox"); + mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw! + mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); + mFilterComboBox = getChild<LLUICtrl>("filters_combobox"); + mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE)); + mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); + mBtnPreview = getChild<LLButton>("big_preview_btn"); mWorkingLabel = getChild<LLUICtrl>("working_lbl"); - mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); - mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); - mPostButton = getChild<LLUICtrl>("post_photo_btn"); - mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); - mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview")); + mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); + mCaptionTextBox = getChild<LLUICtrl>("photo_caption"); + mPostButton = getChild<LLUICtrl>("post_photo_btn"); + mCancelButton = getChild<LLUICtrl>("cancel_photo_btn"); + mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview")); - // Update filter list + // Update filter list std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); + LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); for (U32 i = 0; i < filter_list.size(); i++) - { + { filterbox->add(filter_list[i]); } - return LLPanel::postBuild(); + return LLPanel::postBuild(); } // virtual S32 LLFacebookPhotoPanel::notify(const LLSD& info) { - if (info.has("snapshot-updating")) - { + if (info.has("snapshot-updating")) + { // Disable the Post button and whatever else while the snapshot is not updated // updateControls(); - return 1; - } - - if (info.has("snapshot-updated")) - { + return 1; + } + + if (info.has("snapshot-updated")) + { // Enable the send/post/save buttons. updateControls(); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. after snapshot is taken - LLUICtrl * refresh_button = getRefreshBtn(); - if (!refresh_button->getVisible()) - { - refresh_button->setVisible(true); - } - return 1; - } - - return 0; + + // The refresh button is initially hidden. We show it after the first update, + // i.e. after snapshot is taken + LLUICtrl * refresh_button = getRefreshBtn(); + if (!refresh_button->getVisible()) + { + refresh_button->setVisible(true); + } + return 1; + } + + return 0; } void LLFacebookPhotoPanel::draw() -{ - LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); +{ + LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts) bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing()); @@ -416,98 +416,98 @@ void LLFacebookPhotoPanel::draw() mFilterComboBox->setEnabled(no_ongoing_connection); mRefreshBtn->setEnabled(no_ongoing_connection); mBtnPreview->setEnabled(no_ongoing_connection); - + // Reassign the preview floater if we have the focus and the preview exists if (hasFocus() && isPreviewVisible()) { attachPreview(); } - + // Toggle the button state as appropriate bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>())); - mBtnPreview->setToggleState(preview_active); - + mBtnPreview->setToggleState(preview_active); + // Display the thumbnail if one is available - if (previewp && previewp->getThumbnailImage()) - { - const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); - const S32 thumbnail_w = previewp->getThumbnailWidth(); - const S32 thumbnail_h = previewp->getThumbnailHeight(); - - // calc preview offset within the preview rect - const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ; - const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ; - S32 offset_x = thumbnail_rect.mLeft + local_offset_x; - S32 offset_y = thumbnail_rect.mBottom + local_offset_y; - - gGL.matrixMode(LLRender::MM_MODELVIEW); - // Apply floater transparency to the texture unless the floater is focused. - F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - LLColor4 color = LLColor4::white; - gl_draw_scaled_image(offset_x, offset_y, - thumbnail_w, thumbnail_h, - previewp->getThumbnailImage(), color % alpha); - } + if (previewp && previewp->getThumbnailImage()) + { + const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect(); + const S32 thumbnail_w = previewp->getThumbnailWidth(); + const S32 thumbnail_h = previewp->getThumbnailHeight(); + + // calc preview offset within the preview rect + const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2; + const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2; + S32 offset_x = thumbnail_rect.mLeft + local_offset_x; + S32 offset_y = thumbnail_rect.mBottom + local_offset_y; + + gGL.matrixMode(LLRender::MM_MODELVIEW); + // Apply floater transparency to the texture unless the floater is focused. + F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + LLColor4 color = LLColor4::white; + gl_draw_scaled_image(offset_x, offset_y, + thumbnail_w, thumbnail_h, + previewp->getThumbnailImage(), color % alpha); + } // Update the visibility of the working (computing preview) label mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate())); - + // Enable Post if we have a preview to send and no on going connection being processed mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate())); - + // Draw the rest of the panel on top of it - LLPanel::draw(); + LLPanel::draw(); } LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView() { - LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); - return previewp; + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); + return previewp; } void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible) { - if (visible) - { - if (mPreviewHandle.get()) - { - LLSnapshotLivePreview* preview = getPreviewView(); - if(preview) - { - LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; - preview->updateSnapshot(TRUE); - } - } - else - { - LLRect full_screen_rect = getRootView()->getRect(); - LLSnapshotLivePreview::Params p; - p.rect(full_screen_rect); - LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); - mPreviewHandle = previewp->getHandle(); + if (visible) + { + if (mPreviewHandle.get()) + { + LLSnapshotLivePreview* preview = getPreviewView(); + if (preview) + { + LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; + preview->updateSnapshot(TRUE); + } + } + else + { + LLRect full_screen_rect = getRootView()->getRect(); + LLSnapshotLivePreview::Params p; + p.rect(full_screen_rect); + LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); + mPreviewHandle = previewp->getHandle(); mQuality = MAX_QUALITY; previewp->setContainer(this); - previewp->setSnapshotType(previewp->SNAPSHOT_WEB); - previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); - previewp->setSnapshotQuality(mQuality, false); + previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); + previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG); + previewp->setSnapshotQuality(mQuality, false); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode - previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); + previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect()); - updateControls(); - } - } + updateControls(); + } + } } void LLFacebookPhotoPanel::onClickNewSnapshot() { - LLSnapshotLivePreview* previewp = getPreviewView(); - if (previewp) - { - previewp->updateSnapshot(TRUE); - } + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + previewp->updateSnapshot(TRUE); + } } void LLFacebookPhotoPanel::onClickBigPreview() @@ -541,167 +541,167 @@ void LLFacebookPhotoPanel::attachPreview() void LLFacebookPhotoPanel::onSend() { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendPhoto(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1)); + + // Connect to Facebook if necessary and then post + if (LLFacebookConnect::instance().isConnected()) + { + sendPhoto(); + } + else + { + LLFacebookConnect::instance().checkConnectionToFacebook(true); + } } bool LLFacebookPhotoPanel::onFacebookConnectStateChange(const LLSD& data) { - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendPhoto(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); - clearAndClose(); - break; - } - - return false; + switch (data.get("enum").asInteger()) + { + case LLFacebookConnect::FB_CONNECTED: + sendPhoto(); + break; + + case LLFacebookConnect::FB_POSTED: + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); + clearAndClose(); + break; + } + + return false; } void LLFacebookPhotoPanel::sendPhoto() { - // Get the caption - std::string caption = mCaptionTextBox->getValue().asString(); + // Get the caption + std::string caption = mCaptionTextBox->getValue().asString(); - // Get the image - LLSnapshotLivePreview* previewp = getPreviewView(); - - // Post to Facebook - LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); + // Get the image + LLSnapshotLivePreview* previewp = getPreviewView(); - updateControls(); + // Post to Facebook + LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption); + + updateControls(); } void LLFacebookPhotoPanel::clearAndClose() { - mCaptionTextBox->setValue(""); + mCaptionTextBox->setValue(""); - LLFloater* floater = getParentByType<LLFloater>(); - if (floater) - { - floater->closeFloater(); + LLFloater* floater = getParentByType<LLFloater>(); + if (floater) + { + floater->closeFloater(); if (mBigPreviewFloater) { mBigPreviewFloater->closeOnFloaterOwnerClosing(floater); } - } + } } void LLFacebookPhotoPanel::updateControls() { - LLSnapshotLivePreview* previewp = getPreviewView(); - BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); - - // *TODO: Separate maximum size for Web images from postcards - LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; - - updateResolution(FALSE); + LLSnapshotLivePreview* previewp = getPreviewView(); + BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + + // *TODO: Separate maximum size for Web images from postcards + LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; + + updateResolution(FALSE); } void LLFacebookPhotoPanel::updateResolution(BOOL do_update) { - LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); - LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); + LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox); + LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox); - std::string sdstring = combobox->getSelectedValue(); - LLSD sdres; - std::stringstream sstream(sdstring); - LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + std::string sdstring = combobox->getSelectedValue(); + LLSD sdres; + std::stringstream sstream(sdstring); + LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); - S32 width = sdres[0]; - S32 height = sdres[1]; + S32 width = sdres[0]; + S32 height = sdres[1]; // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); - LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); - if (previewp && combobox->getCurrentIndex() >= 0) - { - S32 original_width = 0 , original_height = 0 ; - previewp->getSize(original_width, original_height) ; - - if (width == 0 || height == 0) - { - // take resolution from current window size - LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; - previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); - } - else - { - // use the resolution from the selected pre-canned drop-down choice - LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; - previewp->setSize(width, height); - } - - checkAspectRatio(width); - - previewp->getSize(width, height); - + LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); + if (previewp && combobox->getCurrentIndex() >= 0) + { + S32 original_width = 0, original_height = 0; + previewp->getSize(original_width, original_height); + + if (width == 0 || height == 0) + { + // take resolution from current window size + LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL; + previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); + } + else + { + // use the resolution from the selected pre-canned drop-down choice + LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; + previewp->setSize(width, height); + } + + checkAspectRatio(width); + + previewp->getSize(width, height); + // Recompute quality setting mQuality = compute_jpeg_quality(width, height); previewp->setSnapshotQuality(mQuality, false); - - if (original_width != width || original_height != height) - { - previewp->setSize(width, height); - if (do_update) - { + + if (original_width != width || original_height != height) + { + previewp->setSize(width, height); + if (do_update) + { previewp->updateSnapshot(TRUE); - updateControls(); - } - } + updateControls(); + } + } // Get the old filter, compare to the current one "filter_name" and set if changed std::string original_filter = previewp->getFilter(); - if (original_filter != filter_name) - { + if (original_filter != filter_name) + { previewp->setFilter(filter_name); - if (do_update) - { + if (do_update) + { previewp->updateSnapshot(FALSE, TRUE); - updateControls(); - } - } - } + updateControls(); + } + } + } } void LLFacebookPhotoPanel::checkAspectRatio(S32 index) { - LLSnapshotLivePreview *previewp = getPreviewView() ; - - BOOL keep_aspect = FALSE; - - if (0 == index) // current window size - { - keep_aspect = TRUE; - } - else // predefined resolution - { - keep_aspect = FALSE; - } - - if (previewp) - { - previewp->mKeepAspectRatio = keep_aspect; - } + LLSnapshotLivePreview *previewp = getPreviewView(); + + BOOL keep_aspect = FALSE; + + if (0 == index) // current window size + { + keep_aspect = TRUE; + } + else // predefined resolution + { + keep_aspect = FALSE; + } + + if (previewp) + { + previewp->mKeepAspectRatio = keep_aspect; + } } LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn() { - return mRefreshBtn; + return mRefreshBtn; } //////////////////////// @@ -712,21 +712,21 @@ LLFacebookCheckinPanel::LLFacebookCheckinPanel() : mMapUrl(""), mReloadingMapTexture(false) { - mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this)); + mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this)); } BOOL LLFacebookCheckinPanel::postBuild() { // Keep pointers to widgets so we don't traverse the UI hierarchy too often - mPostButton = getChild<LLUICtrl>("post_place_btn"); - mCancelButton = getChild<LLUICtrl>("cancel_place_btn"); - mMessageTextEditor = getChild<LLUICtrl>("place_caption"); + mPostButton = getChild<LLUICtrl>("post_place_btn"); + mCancelButton = getChild<LLUICtrl>("cancel_place_btn"); + mMessageTextEditor = getChild<LLUICtrl>("place_caption"); mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator"); mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder"); mMapDefault = getChild<LLIconCtrl>("map_default"); mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb"); - - return LLPanel::postBuild(); + + return LLPanel::postBuild(); } void LLFacebookCheckinPanel::draw() @@ -767,101 +767,101 @@ void LLFacebookCheckinPanel::draw() // This will hide/show the loading indicator and/or tile underneath mMapDefault->setVisible(!(mMapCheckBox->get())); - LLPanel::draw(); + LLPanel::draw(); } void LLFacebookCheckinPanel::onSend() { - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1)); - - // Connect to Facebook if necessary and then post - if (LLFacebookConnect::instance().isConnected()) - { - sendCheckin(); - } - else - { - LLFacebookConnect::instance().checkConnectionToFacebook(true); - } + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1)); + + // Connect to Facebook if necessary and then post + if (LLFacebookConnect::instance().isConnected()) + { + sendCheckin(); + } + else + { + LLFacebookConnect::instance().checkConnectionToFacebook(true); + } } bool LLFacebookCheckinPanel::onFacebookConnectStateChange(const LLSD& data) { - switch (data.get("enum").asInteger()) - { - case LLFacebookConnect::FB_CONNECTED: - sendCheckin(); - break; - - case LLFacebookConnect::FB_POSTED: - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); - clearAndClose(); - break; - } - - return false; + switch (data.get("enum").asInteger()) + { + case LLFacebookConnect::FB_CONNECTED: + sendCheckin(); + break; + + case LLFacebookConnect::FB_POSTED: + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); + clearAndClose(); + break; + } + + return false; } void LLFacebookCheckinPanel::sendCheckin() { - // Get the location SLURL - LLSLURL slurl; - LLAgentUI::buildSLURL(slurl); - std::string slurl_string = slurl.getSLURLString(); - - // Use a valid http:// URL if the scheme is secondlife:// - LLURI slurl_uri(slurl_string); - if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) - { - slurl_string = DEFAULT_CHECKIN_LOCATION_URL; - } - - // Add query parameters so Google Analytics can track incoming clicks! - slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; - - // Get the region name - std::string region_name(""); + // Get the location SLURL + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + std::string slurl_string = slurl.getSLURLString(); + + // Use a valid http:// URL if the scheme is secondlife:// + LLURI slurl_uri(slurl_string); + if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) + { + slurl_string = DEFAULT_CHECKIN_LOCATION_URL; + } + + // Add query parameters so Google Analytics can track incoming clicks! + slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS; + + // Get the region name + std::string region_name(""); LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { region_name = regionp->getName(); } - - // Get the region description - std::string description; - LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent()); - - // Optionally add the region map view - bool add_map_view = mMapCheckBox->getValue().asBoolean(); + + // Get the region description + std::string description; + LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent()); + + // Optionally add the region map view + bool add_map_view = mMapCheckBox->getValue().asBoolean(); std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL); - - // Get the caption - std::string caption = mMessageTextEditor->getValue().asString(); - // Post to Facebook - LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption); + // Get the caption + std::string caption = mMessageTextEditor->getValue().asString(); + + // Post to Facebook + LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption); } void LLFacebookCheckinPanel::clearAndClose() { - mMessageTextEditor->setValue(""); + mMessageTextEditor->setValue(""); - LLFloater* floater = getParentByType<LLFloater>(); - if (floater) - { - floater->closeFloater(); - } + LLFloater* floater = getParentByType<LLFloater>(); + if (floater) + { + floater->closeFloater(); + } } /////////////////////////// //LLFacebookFriendsPanel////// /////////////////////////// -LLFacebookFriendsPanel::LLFacebookFriendsPanel() : -mFriendsStatusCaption(NULL), -mSecondLifeFriends(NULL), -mSuggestedFriends(NULL) +LLFacebookFriendsPanel::LLFacebookFriendsPanel() : + mFriendsStatusCaption(NULL), + mSecondLifeFriends(NULL), + mSuggestedFriends(NULL) { } @@ -872,55 +872,55 @@ LLFacebookFriendsPanel::~LLFacebookFriendsPanel() BOOL LLFacebookFriendsPanel::postBuild() { - mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status"); + mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status"); + + mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends"); + mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); - mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends"); - mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu); - - mSuggestedFriends = getChild<LLAvatarList>("suggested_friends"); - mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu); - - setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2)); + mSuggestedFriends = getChild<LLAvatarList>("suggested_friends"); + mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu); + + setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2)); LLAvatarTracker::instance().addObserver(this); - - return LLPanel::postBuild(); + + return LLPanel::postBuild(); } bool LLFacebookFriendsPanel::updateSuggestedFriendList() { - const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); - uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs(); - second_life_friends.clear(); - uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); - suggested_friends.clear(); - - //Add suggested friends - LLSD friends = LLFacebookConnect::instance().getContent(); - for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) - { - LLUUID agent_id = (*i).asUUID(); - if (agent_id.notNull()) - { - bool second_life_buddy = av_tracker.isBuddy(agent_id); - if (second_life_buddy) - { - second_life_friends.push_back(agent_id); - } - else - { - //FB+SL but not SL friend - suggested_friends.push_back(agent_id); - } - } - } - - //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) - mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches()); - mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); - showFriendsAccordionsIfNeeded(); - - return false; + const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); + uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs(); + second_life_friends.clear(); + uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs(); + suggested_friends.clear(); + + //Add suggested friends + LLSD friends = LLFacebookConnect::instance().getContent(); + for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i) + { + LLUUID agent_id = (*i).asUUID(); + if (agent_id.notNull()) + { + bool second_life_buddy = av_tracker.isBuddy(agent_id); + if (second_life_buddy) + { + second_life_friends.push_back(agent_id); + } + else + { + //FB+SL but not SL friend + suggested_friends.push_back(agent_id); + } + } + } + + //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display) + mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches()); + mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches()); + showFriendsAccordionsIfNeeded(); + + return false; } void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded() @@ -949,15 +949,15 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded() { // We have something in the lists, hide the explanatory text mFriendsStatusCaption->setVisible(false); - + // Show the lists LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion"); accordion->setVisible(true); - + // Expand and show accordions if needed, else - hide them getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches()); getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches()); - + // Rearrange accordions accordion->arrange(); } @@ -965,56 +965,56 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded() void LLFacebookFriendsPanel::changed(U32 mask) { - if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) - { + if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) + { LLFacebookConnect::instance().loadFacebookFriends(); - updateFacebookList(true); - } + updateFacebookList(true); + } } void LLFacebookFriendsPanel::updateFacebookList(bool visible) { - if (visible) - { + if (visible) + { // We want this to be called to fetch the friends list once a connection is established - LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel"); - LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1)); - + LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel"); + LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1)); + // We then want this to be called to update the displayed lists once the list of friends is received - LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening - LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this)); - - // Try to connect to Facebook + LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening + LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this)); + + // Try to connect to Facebook if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) || (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED)) { LLFacebookConnect::instance().checkConnectionToFacebook(); } - // Loads FB friends - if (LLFacebookConnect::instance().isConnected()) - { - LLFacebookConnect::instance().loadFacebookFriends(); - } + // Loads FB friends + if (LLFacebookConnect::instance().isConnected()) + { + LLFacebookConnect::instance().loadFacebookFriends(); + } // Sort the FB friends and update the lists - updateSuggestedFriendList(); - } + updateSuggestedFriendList(); + } } bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data) { - LLSD::Integer connection_state = data.get("enum").asInteger(); - - if (connection_state == LLFacebookConnect::FB_CONNECTED) - { - LLFacebookConnect::instance().loadFacebookFriends(); - } - else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED) - { - updateSuggestedFriendList(); - } - - return false; + LLSD::Integer connection_state = data.get("enum").asInteger(); + + if (connection_state == LLFacebookConnect::FB_CONNECTED) + { + LLFacebookConnect::instance().loadFacebookFriends(); + } + else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED) + { + updateSuggestedFriendList(); + } + + return false; } //////////////////////// @@ -1027,7 +1027,7 @@ LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key), mStatusLoadingText(NULL), mStatusLoadingIndicator(NULL) { - mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this)); + mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this)); } void LLFloaterFacebook::onClose(bool app_quitting) @@ -1037,7 +1037,7 @@ void LLFloaterFacebook::onClose(bool app_quitting) { big_preview_floater->closeOnFloaterOwnerClosing(this); } - LLFloater::onClose(app_quitting); + LLFloater::onClose(app_quitting); } void LLFloaterFacebook::onCancel() @@ -1053,24 +1053,24 @@ void LLFloaterFacebook::onCancel() BOOL LLFloaterFacebook::postBuild() { // Keep tab of the Photo Panel - mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo")); + mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo")); // Connection status widgets mStatusErrorText = getChild<LLTextBox>("connection_error_text"); mStatusLoadingText = getChild<LLTextBox>("connection_loading_text"); mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator"); - return LLFloater::postBuild(); + return LLFloater::postBuild(); } void LLFloaterFacebook::showPhotoPanel() { - LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent()); - if (!parent) - { - LL_WARNS() << "Cannot find panel container" << LL_ENDL; - return; - } - - parent->selectTabPanel(mFacebookPhotoPanel); + LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent()); + if (!parent) + { + LL_WARNS() << "Cannot find panel container" << LL_ENDL; + return; + } + + parent->selectTabPanel(mFacebookPhotoPanel); } void LLFloaterFacebook::draw() @@ -1082,7 +1082,7 @@ void LLFloaterFacebook::draw() mStatusLoadingIndicator->setVisible(false); LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState(); std::string status_text; - + switch (connection_state) { case LLFacebookConnect::FB_NOT_CONNECTED: @@ -1105,7 +1105,7 @@ void LLFloaterFacebook::draw() status_text = LLTrans::getString("SocialFacebookPosting"); mStatusLoadingText->setValue(status_text); mStatusLoadingIndicator->setVisible(true); - break; + break; case LLFacebookConnect::FB_CONNECTION_FAILED: // Error connecting to the service mStatusErrorText->setVisible(true); @@ -1118,21 +1118,21 @@ void LLFloaterFacebook::draw() status_text = LLTrans::getString("SocialFacebookErrorPosting"); mStatusErrorText->setValue(status_text); break; - case LLFacebookConnect::FB_DISCONNECTING: - // Disconnecting loading indicator - mStatusLoadingText->setVisible(true); - status_text = LLTrans::getString("SocialFacebookDisconnecting"); - mStatusLoadingText->setValue(status_text); - mStatusLoadingIndicator->setVisible(true); - break; - case LLFacebookConnect::FB_DISCONNECT_FAILED: - // Error disconnecting from the service - mStatusErrorText->setVisible(true); - status_text = LLTrans::getString("SocialFacebookErrorDisconnecting"); - mStatusErrorText->setValue(status_text); - break; + case LLFacebookConnect::FB_DISCONNECTING: + // Disconnecting loading indicator + mStatusLoadingText->setVisible(true); + status_text = LLTrans::getString("SocialFacebookDisconnecting"); + mStatusLoadingText->setValue(status_text); + mStatusLoadingIndicator->setVisible(true); + break; + case LLFacebookConnect::FB_DISCONNECT_FAILED: + // Error disconnecting from the service + mStatusErrorText->setVisible(true); + status_text = LLTrans::getString("SocialFacebookErrorDisconnecting"); + mStatusErrorText->setValue(status_text); + break; } } - LLFloater::draw(); + LLFloater::draw(); } diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index cd132b843d..15b7c7fafa 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -238,8 +238,8 @@ void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible) mPreviewHandle = previewp->getHandle(); previewp->setContainer(this); - previewp->setSnapshotType(previewp->SNAPSHOT_WEB); - previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG); + previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); + previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_PNG); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index d842106146..b840d37c4d 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -328,7 +328,7 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur element["columns"][0]["font"]["name"] = "SANSSERIF"; element["columns"][0]["font"]["style"] = font_style; - std::string key_string = LLKeyboard::stringFromKey(gesture->mKey); + std::string key_string; std::string buffer; if (gesture->mKey == KEY_NONE) @@ -338,6 +338,7 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur } else { + key_string = LLKeyboard::stringFromKey(gesture->mKey); buffer = LLKeyboard::stringFromAccelerator(gesture->mMask, gesture->mKey); } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7a989806a1..257b39a7dd 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -798,7 +798,8 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* } else if (mesg[0] == '/' && mesg[1] - && LLStringOps::isDigit(mesg[1])) + && (LLStringOps::isDigit(mesg[1]) + || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2])))) { // This a special "/20" speak on a channel S32 pos = 0; @@ -812,7 +813,7 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel_string.push_back(c); pos++; } - while(c && pos < 64 && LLStringOps::isDigit(c)); + while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos==1 && c =='-'))); // Move the pointer forward to the first non-whitespace char // Check isspace before looping, so we can handle "/33foo" @@ -837,19 +838,36 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* 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(); - - add(LLStatViewer::CHAT_COUNT, 1); + LLMessageSystem* msg = gMessageSystem; + + if (channel >= 0) + { + 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); + + } + else + { + // Hack: ChatFromViewer doesn't allow negative channels + msg->newMessage("ScriptDialogReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + msg->nextBlock("Data"); + msg->addUUID("ObjectID", gAgentID); + msg->addS32("ChatChannel", channel); + msg->addS32("ButtonIndex", 0); + msg->addString("ButtonLabel", utf8_out_text); + } + + gAgent.sendReliableMessage(); + add(LLStatViewer::CHAT_COUNT, 1); } class LLChatCommandHandler : public LLCommandHandler diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp new file mode 100644 index 0000000000..d80793f9e4 --- /dev/null +++ b/indra/newview/llfloateroutfitsnapshot.cpp @@ -0,0 +1,377 @@ +/** + * @file llfloateroutfitsnapshot.cpp + * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2016, 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 "llfloatersnapshot.h" +#include "llfloateroutfitsnapshot.h" + +#include "llagent.h" +#include "llfacebookconnect.h" +#include "llfloaterreg.h" +#include "llfloaterfacebook.h" +#include "llfloaterflickr.h" +#include "llfloatertwitter.h" +#include "llimagefiltersmanager.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llpostcard.h" +#include "llresmgr.h" // LLLocale +#include "llsdserialize.h" +#include "llsidetraypanelcontainer.h" +#include "llspinctrl.h" +#include "llviewercontrol.h" +#include "lltoolfocus.h" +#include "lltoolmgr.h" +#include "llwebprofile.h" + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- +LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL; + +const S32 OUTFIT_SNAPSHOT_WIDTH = 256; +const S32 OUTFIT_SNAPSHOT_HEIGHT = 256; + +static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view"); + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +// virtual +LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found) +{ + LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); + LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel); + if (!ok_if_not_found) + { + llassert_always(active_panel != NULL); + } + return active_panel; +} + +// virtual +LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater) +{ + return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; +} + +// virtual +LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater) +{ + return LLSnapshotModel::SNAPSHOT_TYPE_COLOR; +} + +// This is the main function that keeps all the GUI controls in sync with the saved settings. +// It should be called anytime a setting is changed that could affect the controls. +// No other methods should be changing any of the controls directly except for helpers called by this method. +// The basic pattern for programmatically changing the GUI settings is to first set the +// appropriate saved settings and then call this method to sync the GUI with them. +// FIXME: The above comment seems obsolete now. +// virtual +void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater) +{ + LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater); + LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); + LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater); + + LLSnapshotLivePreview* previewp = getPreviewView(); + BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + + // *TODO: Separate maximum size for Web images from postcards + LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; + + LLLocale locale(LLLocale::USER_LOCALE); + std::string bytes_string; + if (got_snap) + { + LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10); + } + + // Update displayed image resolution. + LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text"); + image_res_tb->setVisible(got_snap); + if (got_snap) + { + image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth())); + image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight())); + } + + floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); + floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor")); + + updateResolution(floater); + + if (previewp) + { + previewp->setSnapshotType(shot_type); + previewp->setSnapshotFormat(shot_format); + previewp->setSnapshotBufferType(layer_type); + } + + LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); + if (current_panel) + { + LLSD info; + info["have-snapshot"] = got_snap; + current_panel->updateControls(info); + } + LL_DEBUGS() << "finished updating controls" << LL_ENDL; +} + +// virtual +std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix() +{ + return "panel_outfit_snapshot_"; +} + +// Show/hide upload status message. +// virtual +void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg) +{ + mFloater->setSuccessLabelPanelVisible(finished && ok); + mFloater->setFailureLabelPanelVisible(finished && !ok); + + if (finished) + { + LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); + std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); + finished_lbl->setValue(result_text); + + LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); + snapshot_panel->onOpen(LLSD()); + } +} + +void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data) +{ + LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data; + + if (!view) + { + llassert(view); + return; + } + + S32 width = OUTFIT_SNAPSHOT_WIDTH; + S32 height = OUTFIT_SNAPSHOT_HEIGHT; + + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + S32 original_width = 0, original_height = 0; + previewp->getSize(original_width, original_height); + + if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { //clamp snapshot resolution to window size when showing UI or HUD in snapshot + width = llmin(width, gViewerWindow->getWindowWidthRaw()); + height = llmin(height, gViewerWindow->getWindowHeightRaw()); + } + + + llassert(width > 0 && height > 0); + + // use the resolution from the selected pre-canned drop-down choice + LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; + previewp->setSize(width, height); + + if (original_width != width || original_height != height) + { + // hide old preview as the aspect ratio could be wrong + checkAutoSnapshot(previewp, FALSE); + LL_DEBUGS() << "updating thumbnail" << LL_ENDL; + previewp->updateSnapshot(TRUE); + } + } +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot +///---------------------------------------------------------------------------- + +// Default constructor +LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key) +: LLFloaterSnapshotBase(key), +mOutfitGallery(NULL) +{ + impl = new Impl(this); +} + +LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot() +{ +} + +// virtual +BOOL LLFloaterOutfitSnapshot::postBuild() +{ + mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); + childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this); + mRefreshLabel = getChild<LLUICtrl>("refresh_lbl"); + mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel"); + mFailureLblPanel = getChild<LLUICtrl>("failed_panel"); + + childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this); + getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); + + childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this); + getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); + + getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); + childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this); + + getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); + childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this); + + getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this)); + getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this)); + + // Filters + LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox"); + std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this); + + mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); + + // create preview window + LLRect full_screen_rect = getRootView()->getRect(); + LLSnapshotLivePreview::Params p; + p.rect(full_screen_rect); + LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); + LLView* parent_view = gSnapshotFloaterView->getParent(); + + parent_view->removeChild(gSnapshotFloaterView); + // make sure preview is below snapshot floater + parent_view->addChild(previewp); + parent_view->addChild(gSnapshotFloaterView); + + //move snapshot floater to special purpose snapshotfloaterview + gFloaterView->removeChild(this); + gSnapshotFloaterView->addChild(this); + + impl->mPreviewHandle = previewp->getHandle(); + previewp->setContainer(this); + impl->updateControls(this); + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); + impl->updateLayout(this); + + previewp->mKeepAspectRatio = FALSE; + previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); + + return TRUE; +} + +// virtual +void LLFloaterOutfitSnapshot::onOpen(const LLSD& key) +{ + LLSnapshotLivePreview* preview = getPreviewView(); + if (preview) + { + LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; + preview->updateSnapshot(TRUE); + } + focusFirstItem(FALSE); + gSnapshotFloaterView->setEnabled(TRUE); + gSnapshotFloaterView->setVisible(TRUE); + gSnapshotFloaterView->adjustToFitScreen(this, FALSE); + + impl->updateControls(this); + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); + impl->updateLayout(this); + + LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory"); + snapshot_panel->onOpen(LLSD()); + postPanelSwitch(); + +} + +void LLFloaterOutfitSnapshot::onExtendFloater() +{ + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); +} + +// static +void LLFloaterOutfitSnapshot::update() +{ + LLFloaterOutfitSnapshot* inst = findInstance(); + if (inst != NULL) + { + inst->impl->updateLivePreview(); + } +} + + +// static +LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance() +{ + return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); +} + +// static +LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); +} + +// virtual +void LLFloaterOutfitSnapshot::saveTexture() +{ + LL_DEBUGS() << "saveTexture" << LL_ENDL; + + LLSnapshotLivePreview* previewp = getPreviewView(); + if (!previewp) + { + llassert(previewp != NULL); + return; + } + + if (mOutfitGallery) + { + mOutfitGallery->onBeforeOutfitSnapshotSave(); + } + previewp->saveTexture(TRUE, getOutfitID().asString()); + if (mOutfitGallery) + { + mOutfitGallery->onAfterOutfitSnapshotSave(); + } + closeFloater(); +} + +///---------------------------------------------------------------------------- +/// Class LLOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p) +{ +} + +LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView() +{ +} diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h new file mode 100644 index 0000000000..bee386ec63 --- /dev/null +++ b/indra/newview/llfloateroutfitsnapshot.h @@ -0,0 +1,123 @@ +/** + * @file llfloateroutfitsnapshot.h + * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2016, 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_LLFLOATEROUTFITSNAPSHOT_H +#define LL_LLFLOATEROUTFITSNAPSHOT_H + +#include "llfloater.h" +#include "llfloatersnapshot.h" +#include "lloutfitgallery.h" +#include "llsnapshotlivepreview.h" + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot +///---------------------------------------------------------------------------- + +class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase +{ + LOG_CLASS(LLFloaterOutfitSnapshot); + +public: + + LLFloaterOutfitSnapshot(const LLSD& key); + /*virtual*/ ~LLFloaterOutfitSnapshot(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + static void update(); + + void onExtendFloater(); + + static LLFloaterOutfitSnapshot* getInstance(); + static LLFloaterOutfitSnapshot* findInstance(); + /*virtual*/ void saveTexture(); + + const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } + + void setOutfitID(LLUUID id) { mOutfitID = id; } + LLUUID getOutfitID() { return mOutfitID; } + void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; } + + class Impl; + friend class Impl; +private: + + LLUUID mOutfitID; + LLOutfitGallery* mOutfitGallery; +}; + +///---------------------------------------------------------------------------- +/// Class LLFloaterOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase +{ + LOG_CLASS(LLFloaterOutfitSnapshot::Impl); +public: + Impl(LLFloaterSnapshotBase* floater) + : LLFloaterSnapshotBase::ImplBase(floater) + {} + ~Impl() + {} + void updateResolution(void* data); + + static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); + + /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true); + /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); + /*virtual*/ std::string getSnapshotPanelPrefix(); + + /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater); + +private: + /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); + /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); +}; + +///---------------------------------------------------------------------------- +/// Class LLOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +class LLOutfitSnapshotFloaterView : public LLFloaterView +{ +public: + struct Params + : public LLInitParam::Block<Params, LLFloaterView::Params> + { + }; + +protected: + LLOutfitSnapshotFloaterView(const Params& p); + friend class LLUICtrlFactory; + +public: + virtual ~LLOutfitSnapshotFloaterView(); +}; + +extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView; + +#endif // LL_LLFLOATEROUTFITSNAPSHOT_H diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index 31245db344..dfe462c8d1 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -72,6 +72,8 @@ struct LLGiveMoneyInfo mFloater(floater), mAmount(amount){} }; +typedef boost::shared_ptr<LLGiveMoneyInfo> give_money_ptr; + ///---------------------------------------------------------------------------- /// Class LLFloaterPay ///---------------------------------------------------------------------------- @@ -94,18 +96,18 @@ public: bool is_group); static bool payConfirmationCallback(const LLSD& notification, const LLSD& response, - LLGiveMoneyInfo* info); + give_money_ptr info); private: static void onCancel(void* data); static void onKeystroke(LLLineEditor* editor, void* data); - static void onGive(void* data); + static void onGive(give_money_ptr info); void give(S32 amount); static void processPayPriceReply(LLMessageSystem* msg, void **userdata); void finishPayUI(const LLUUID& target_id, BOOL is_group); protected: - std::vector<LLGiveMoneyInfo*> mCallbackData; + std::vector<give_money_ptr> mCallbackData; money_callback mCallback; LLTextBox* mObjectNameText; LLUUID mTargetUUID; @@ -113,7 +115,7 @@ protected: BOOL mHaveName; LLButton* mQuickPayButton[MAX_PAY_BUTTONS]; - LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS]; + give_money_ptr mQuickPayInfo[MAX_PAY_BUTTONS]; LLSafeHandle<LLObjectSelection> mObjectSelection; }; @@ -136,7 +138,11 @@ LLFloaterPay::LLFloaterPay(const LLSD& key) // Destroys the object LLFloaterPay::~LLFloaterPay() { - std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer()); + std::vector<give_money_ptr>::iterator iter; + for (iter = mCallbackData.begin(); iter != mCallbackData.end(); ++iter) + { + (*iter)->mFloater = NULL; + } mCallbackData.clear(); // Name callbacks will be automatically disconnected since LLFloater is trackable @@ -148,40 +154,40 @@ BOOL LLFloaterPay::postBuild() { S32 i = 0; - LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0); + give_money_ptr info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0)); mCallbackData.push_back(info); - childSetAction("fastpay 1",&LLFloaterPay::onGive,info); + childSetAction("fastpay 1", boost::bind(LLFloaterPay::onGive, info)); getChildView("fastpay 1")->setVisible(FALSE); mQuickPayButton[i] = getChild<LLButton>("fastpay 1"); mQuickPayInfo[i] = info; ++i; - info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1); + info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1)); mCallbackData.push_back(info); - childSetAction("fastpay 5",&LLFloaterPay::onGive,info); + childSetAction("fastpay 5", boost::bind(LLFloaterPay::onGive, info)); getChildView("fastpay 5")->setVisible(FALSE); mQuickPayButton[i] = getChild<LLButton>("fastpay 5"); mQuickPayInfo[i] = info; ++i; - info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2); + info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2)); mCallbackData.push_back(info); - childSetAction("fastpay 10",&LLFloaterPay::onGive,info); + childSetAction("fastpay 10", boost::bind(LLFloaterPay::onGive, info)); getChildView("fastpay 10")->setVisible(FALSE); mQuickPayButton[i] = getChild<LLButton>("fastpay 10"); mQuickPayInfo[i] = info; ++i; - info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3); + info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3)); mCallbackData.push_back(info); - childSetAction("fastpay 20",&LLFloaterPay::onGive,info); + childSetAction("fastpay 20", boost::bind(LLFloaterPay::onGive, info)); getChildView("fastpay 20")->setVisible(FALSE); mQuickPayButton[i] = getChild<LLButton>("fastpay 20"); @@ -195,10 +201,10 @@ BOOL LLFloaterPay::postBuild() getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this); getChild<LLLineEditor>("amount")->setPrevalidate(LLTextValidate::validateNonNegativeS32); - info = new LLGiveMoneyInfo(this, 0); + info = give_money_ptr(new LLGiveMoneyInfo(this, 0)); mCallbackData.push_back(info); - childSetAction("pay btn",&LLFloaterPay::onGive,info); + childSetAction("pay btn", boost::bind(LLFloaterPay::onGive, info)); setDefaultBtn("pay btn"); getChildView("pay btn")->setVisible(FALSE); getChildView("pay btn")->setEnabled(FALSE); @@ -415,9 +421,9 @@ void LLFloaterPay::payDirectly(money_callback callback, floater->finishPayUI(target_id, is_group); } -bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, LLGiveMoneyInfo* info) +bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, give_money_ptr info) { - if (!info || !info->mFloater) + if (!info.get() || !info->mFloater) { return false; } @@ -479,54 +485,61 @@ void LLFloaterPay::onKeystroke(LLLineEditor*, void* data) } // static -void LLFloaterPay::onGive(void* data) +void LLFloaterPay::onGive(give_money_ptr info) { - LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data); - LLFloaterPay* floater = info->mFloater; - if(info && floater) - { - S32 amount = info->mAmount; - if(amount == 0) - { - amount = atoi(floater->getChild<LLUICtrl>("amount")->getValue().asString().c_str()); - } - if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount) - { - LLUUID payee_id = LLUUID::null; - BOOL is_group = false; - if (floater->mObjectSelection.notNull()) - { - LLSelectNode* node = floater->mObjectSelection->getFirstRootNode(); - if (node) - { - node->mPermissions->getOwnership(payee_id, is_group); - } - else - { - // object no longer exists - LLNotificationsUtil::add("PayObjectFailed"); - floater->closeFloater(); - return; - } - } - else - { - is_group = floater->mTargetIsGroup; - payee_id = floater->mTargetUUID; - } - - LLSD args; - args["TARGET"] = LLSLURL( is_group ? "group" : "agent", payee_id, "completename").getSLURLString(); - args["AMOUNT"] = amount; - - LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info)); - } - else - { - floater->give(amount); - floater->closeFloater(); - } - } + if (!info.get() || !info->mFloater) + { + return; + } + + LLFloaterPay* floater = info->mFloater; + S32 amount = info->mAmount; + if (amount == 0) + { + LLUICtrl* text_field = floater->getChild<LLUICtrl>("amount"); + if (!text_field) + { + return; + } + amount = atoi(text_field->getValue().asString().c_str()); + } + + if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount) + { + LLUUID payee_id = LLUUID::null; + BOOL is_group = false; + if (floater->mObjectSelection.notNull()) + { + LLSelectNode* node = floater->mObjectSelection->getFirstRootNode(); + if (node) + { + node->mPermissions->getOwnership(payee_id, is_group); + } + else + { + // object no longer exists + LLNotificationsUtil::add("PayObjectFailed"); + floater->closeFloater(); + return; + } + } + else + { + is_group = floater->mTargetIsGroup; + payee_id = floater->mTargetUUID; + } + + LLSD args; + args["TARGET"] = LLSLURL(is_group ? "group" : "agent", payee_id, "completename").getSLURLString(); + args["AMOUNT"] = amount; + + LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info)); + } + else + { + floater->give(amount); + floater->closeFloater(); + } } void LLFloaterPay::give(S32 amount) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 36bdcf4d89..75f5e87a2b 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1232,6 +1232,9 @@ void LLFloaterPreference::refreshEnabledState() (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); + + // Cannot have floater active until caps have been received + getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); } void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() @@ -1369,9 +1372,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() disableUnavailableSettings(); getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); - - // Cannot have floater active until caps have been received - getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); } // static @@ -1411,7 +1411,7 @@ void LLAvatarComplexityControls::setIndirectMaxArc() else { // This is the inverse of the calculation in updateMaxComplexity - indirect_max_arc = (U32)((log(max_arc) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE) + MIN_INDIRECT_ARC_LIMIT; + indirect_max_arc = (U32)ll_round(((log(F32(max_arc)) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE)) + MIN_INDIRECT_ARC_LIMIT; } gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc); } @@ -1930,7 +1930,7 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu { // if this is changed, the inverse calculation in setIndirectMaxArc // must be changed to match - max_arc = (U32)exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT))); + max_arc = (U32)ll_round(exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT)))); } gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index ed6f4ede9f..a6ce0ba678 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -192,7 +192,6 @@ BOOL LLFloaterReporter::postBuild() mOwnerName = LLStringUtil::null; getChild<LLUICtrl>("summary_edit")->setFocus(TRUE); - getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE); mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString(); @@ -246,8 +245,6 @@ LLFloaterReporter::~LLFloaterReporter() // virtual void LLFloaterReporter::draw() { - getChildView("screen_check")->setEnabled(TRUE ); - LLFloater::draw(); } @@ -255,7 +252,6 @@ void LLFloaterReporter::enableControls(BOOL enable) { getChildView("category_combo")->setEnabled(enable); getChildView("chat_check")->setEnabled(enable); - getChildView("screen_check")->setEnabled(enable); getChildView("screenshot")->setEnabled(FALSE); getChildView("pick_btn")->setEnabled(enable); getChildView("summary_edit")->setEnabled(enable); @@ -448,23 +444,15 @@ void LLFloaterReporter::onClickSend(void *userdata) if(!url.empty() || !sshot_url.empty()) { self->sendReportViaCaps(url, sshot_url, self->gatherReport()); + LLNotificationsUtil::add("HelpReportAbuseConfirm"); self->closeFloater(); } else { - if(self->getChild<LLUICtrl>("screen_check")->getValue()) - { - self->getChildView("send_btn")->setEnabled(FALSE); - self->getChildView("cancel_btn")->setEnabled(FALSE); - // the callback from uploading the image calls sendReportViaLegacy() - self->uploadImage(); - } - else - { - self->sendReportViaLegacy(self->gatherReport()); - LLUploadDialog::modalUploadFinished(); - self->closeFloater(); - } + self->getChildView("send_btn")->setEnabled(FALSE); + self->getChildView("cancel_btn")->setEnabled(FALSE); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); } } } @@ -713,10 +701,7 @@ LLSD LLFloaterReporter::gatherReport() // only send a screenshot ID if we're asked to and the email is // going to LL - Estate Owners cannot see the screenshot asset LLUUID screenshot_id = LLUUID::null; - if (getChild<LLUICtrl>("screen_check")->getValue()) - { - screenshot_id = getChild<LLUICtrl>("screenshot")->getValue(); - }; + screenshot_id = getChild<LLUICtrl>("screenshot")->getValue(); LLSD report = LLSD::emptyMap(); report["report-type"] = (U8) mReportType; @@ -770,7 +755,7 @@ void LLFloaterReporter::finishedARPost(const LLSD &) void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) { - if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty()) + if(!sshot_url.empty()) { // try to upload screenshot LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType)); @@ -885,6 +870,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, self->mScreenID = uuid; LL_INFOS() << "Got screen shot " << uuid << LL_ENDL; self->sendReportViaLegacy(self->gatherReport()); + LLNotificationsUtil::add("HelpReportAbuseConfirm"); self->closeFloater(); } } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 7b8fc5b35b..eae16b9f03 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -660,6 +660,8 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild() { return FALSE; } + list->setCommitCallback(boost::bind(&LLPanelScriptLimitsRegionMemory::checkButtonsEnabled, this)); + checkButtonsEnabled(); //set all columns to resizable mode even if some columns will be empty for(S32 column = 0; column < list->getNumColumns(); column++) @@ -750,6 +752,14 @@ void LLPanelScriptLimitsRegionMemory::clearList() getChild<LLUICtrl>("parcels_listed")->setValue(LLSD(msg_empty_string)); mObjectListItems.clear(); + checkButtonsEnabled(); +} + +void LLPanelScriptLimitsRegionMemory::checkButtonsEnabled() +{ + LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list"); + getChild<LLButton>("highlight_btn")->setEnabled(list->getNumSelected() > 0); + getChild<LLButton>("return_btn")->setEnabled(list->getNumSelected() > 0); } // static diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index e3cbbd185f..2ac3862b4f 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -113,6 +113,7 @@ public: void showBeacon(); void returnObjectsFromParcel(S32 local_id); void returnObjects(); + void checkButtonsEnabled(); private: void onNameCache(const LLUUID& id, diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 0cb37dabe7..b139e5daf5 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -257,7 +257,6 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) static std::string badgeOK("badge_ok.j2c"); static std::string badgeNote("badge_note.j2c"); static std::string badgeWarn("badge_warn.j2c"); - static std::string badgeError("badge_error.j2c"); std::string badgeName; switch (badge) @@ -266,7 +265,7 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) case BADGE_OK: badgeName = badgeOK; break; case BADGE_NOTE: badgeName = badgeNote; break; case BADGE_WARN: badgeName = badgeWarn; break; - case BADGE_ERROR: badgeName = badgeError; break; + case BADGE_ERROR: badgeName = badgeWarn; break; } getChild<LLUICtrl>(id)->setValue(badgeName); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index b906671c7f..b5ba64716d 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2016, 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 @@ -28,7 +28,6 @@ #include "llfloatersnapshot.h" -#include "llagent.h" #include "llfacebookconnect.h" #include "llfloaterreg.h" #include "llfloaterfacebook.h" @@ -51,7 +50,6 @@ ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL; LLSnapshotFloaterView* gSnapshotFloaterView = NULL; const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -61,92 +59,8 @@ const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view"); - -///---------------------------------------------------------------------------- -/// Class LLFloaterSnapshot::Impl -///---------------------------------------------------------------------------- - -class LLFloaterSnapshot::Impl -{ - LOG_CLASS(LLFloaterSnapshot::Impl); -public: - typedef enum e_status - { - STATUS_READY, - STATUS_WORKING, - STATUS_FINISHED - } EStatus; - - Impl() - : mAvatarPauseHandles(), - mLastToolset(NULL), - mAspectRatioCheckOff(false), - mNeedRefresh(false), - mStatus(STATUS_READY) - { - } - ~Impl() - { - //unpause avatars - mAvatarPauseHandles.clear(); - - } - static void onClickNewSnapshot(void* data); - static void onClickAutoSnap(LLUICtrl *ctrl, void* data); - static void onClickFilter(LLUICtrl *ctrl, void* data); - //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); - static void onClickUICheck(LLUICtrl *ctrl, void* data); - static void onClickHUDCheck(LLUICtrl *ctrl, void* data); - static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked); - static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); - static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); - static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); - static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val); - static void onImageFormatChange(LLFloaterSnapshot* view); - static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h); - static void onSnapshotUploadFinished(bool status); - static void onSendingPostcardFinished(bool status); - static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); - static void setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) ; - static void updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed); - - static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true); - static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater); - static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater); - static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater); - static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater); - static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable); - static void setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked); - - static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater); - static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname); - static void updateControls(LLFloaterSnapshot* floater); - static void updateLayout(LLFloaterSnapshot* floater); - static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); - EStatus getStatus() const { return mStatus; } - static void setNeedRefresh(LLFloaterSnapshot* floater, bool need); - -private: - static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater); - static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); - static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); - static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ; - static void setWorking(LLFloaterSnapshot* floater, bool working); - static void setFinished(LLFloaterSnapshot* floater, bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); - - -public: - std::vector<LLAnimPauseRequest> mAvatarPauseHandles; - - LLToolset* mLastToolset; - LLHandle<LLView> mPreviewHandle; - bool mAspectRatioCheckOff ; - bool mNeedRefresh; - EStatus mStatus; -}; - -// static -LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found) +// virtual +LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found) { LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel()); @@ -157,58 +71,40 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floa return active_panel; } -// static -LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotType LLFloaterSnapshotBase::ImplBase::getActiveSnapshotType(LLFloaterSnapshotBase* floater) { - LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB; - std::string name; LLPanelSnapshot* spanel = getActivePanel(floater); - if (spanel) - { - name = spanel->getName(); - } - - if (name == "panel_snapshot_postcard") - { - type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; - } - else if (name == "panel_snapshot_inventory") - { - type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; - } - else if (name == "panel_snapshot_local") - { - type = LLSnapshotLivePreview::SNAPSHOT_LOCAL; - } - - return type; + //return type; + if (spanel) + { + return spanel->getSnapshotType(); + } + return LLSnapshotModel::SNAPSHOT_WEB; } -// static -LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater) { LLPanelSnapshot* active_panel = getActivePanel(floater); // FIXME: if the default is not PNG, profile uploads may fail. - return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + return active_panel ? active_panel->getImageFormat() : LLSnapshotModel::SNAPSHOT_FORMAT_PNG; } -// static -LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater) +LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshotBase* floater) { LLPanelSnapshot* active_panel = getActivePanel(floater); return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width"); } -// static -LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater) +LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshotBase* floater) { LLPanelSnapshot* active_panel = getActivePanel(floater); return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height"); } -// static -void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable) +void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable) { LLPanelSnapshot* active_panel = getActivePanel(floater); if (active_panel) @@ -217,8 +113,7 @@ void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* float } } -// static -void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked) +void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked) { LLPanelSnapshot* active_panel = getActivePanel(floater); if (active_panel) @@ -227,40 +122,41 @@ void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* flo } } -// static -LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) +LLSnapshotLivePreview* LLFloaterSnapshotBase::getPreviewView() { - LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get(); + return impl->getPreviewView(); +} + +LLSnapshotLivePreview* LLFloaterSnapshotBase::ImplBase::getPreviewView() +{ + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get(); return previewp; } -// static -LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) +// virtual +LLSnapshotModel::ESnapshotLayerType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater) { - LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR; LLSD value = floater->getChild<LLUICtrl>("layer_types")->getValue(); const std::string id = value.asString(); if (id == "colors") - type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR; else if (id == "depth") - type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH; + type = LLSnapshotModel::SNAPSHOT_TYPE_DEPTH; return type; } -// static -void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname) +void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname) { LLComboBox* combo = floater->getChild<LLComboBox>(comboname); combo->setVisible(TRUE); updateResolution(combo, floater, FALSE); // to sync spinners with combo } -//static -void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) +//virtual +void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floaterp) { - LLSnapshotLivePreview* previewp = getPreviewView(floaterp); - - BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot"); + LLSnapshotLivePreview* previewp = getPreviewView(); //BD - Automatically calculate the size of our snapshot window to enlarge // the snapshot preview to its maximum size, this is especially helpfull @@ -277,16 +173,16 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) } S32 floater_width = 224.f; - if(advanced) + if(mAdvanced) { floater_width = floater_width + panel_width; } LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder"); - thumbnail_placeholder->setVisible(advanced); + thumbnail_placeholder->setVisible(mAdvanced); thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight()); - floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(advanced); - floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(advanced); + floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced); + floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced); if(!floaterp->isMinimized()) { floaterp->reshape(floater_width, floaterp->getRect().getHeight()); @@ -316,7 +212,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) iter != LLCharacter::sInstances.end(); ++iter) { avatarp = *iter; - floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause()); + floaterp->impl->mAvatarPauseHandles.push_back(avatarp->requestPause()); } // freeze everything else @@ -324,7 +220,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset) { - floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset(); + floaterp->impl->mLastToolset = LLToolMgr::getInstance()->getCurrentToolset(); LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset); } } @@ -340,15 +236,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) } //RN: thaw all avatars - floaterp->impl.mAvatarPauseHandles.clear(); + floaterp->impl->mAvatarPauseHandles.clear(); // thaw everything else gSavedSettings.setBOOL("FreezeTime", FALSE); // restore last tool (e.g. pie menu, etc) - if (floaterp->impl.mLastToolset) + if (floaterp->impl->mLastToolset) { - LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset); + LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl->mLastToolset); } } } @@ -359,15 +255,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // The basic pattern for programmatically changing the GUI settings is to first set the // appropriate saved settings and then call this method to sync the GUI with them. // FIXME: The above comment seems obsolete now. -// static -void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) +// virtual +void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater) { - LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater); - ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); - LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); + LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater); + LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); + LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater); floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); - floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); + floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotModel::SNAPSHOT_LOCAL); LLPanelSnapshot* active_panel = getActivePanel(floater); if (active_panel) @@ -381,7 +277,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) S32 w = gViewerWindow->getWindowWidthRaw(); LL_DEBUGS() << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << LL_ENDL; width_ctrl->setValue(w); - if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE) { width_ctrl->setIncrement(w >> 1); } @@ -391,7 +287,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) S32 h = gViewerWindow->getWindowHeightRaw(); LL_DEBUGS() << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << LL_ENDL; height_ctrl->setValue(h); - if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE) { height_ctrl->setIncrement(h >> 1); } @@ -423,7 +319,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) } } - LLSnapshotLivePreview* previewp = getPreviewView(floater); + LLSnapshotLivePreview* previewp = getPreviewView(); BOOL got_bytes = previewp && previewp->getDataSize() > 0; BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); @@ -448,35 +344,35 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); floater->getChild<LLUICtrl>("file_size_label")->setColor( - shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + shot_type == LLSnapshotModel::SNAPSHOT_POSTCARD && got_bytes && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); // Update the width and height spinners based on the corresponding resolution combos. (?) switch(shot_type) { - case LLSnapshotLivePreview::SNAPSHOT_WEB: - layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + case LLSnapshotModel::SNAPSHOT_WEB: + layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR; floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); setResolution(floater, "profile_size_combo"); break; - case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: - layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + case LLSnapshotModel::SNAPSHOT_POSTCARD: + layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR; floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); setResolution(floater, "postcard_size_combo"); break; - case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: - layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + case LLSnapshotModel::SNAPSHOT_TEXTURE: + layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR; floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); setResolution(floater, "texture_size_combo"); break; - case LLSnapshotLivePreview::SNAPSHOT_LOCAL: + case LLSnapshotModel::SNAPSHOT_LOCAL: setResolution(floater, "local_size_combo"); break; default: break; } - setAspectRatioCheckboxValue(floater, !floater->impl.mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot")); + setAspectRatioCheckboxValue(floater, !floater->impl->mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot")); if (previewp) { @@ -495,33 +391,32 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) LL_DEBUGS() << "finished updating controls" << LL_ENDL; } -// static -void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg) +//virtual +void LLFloaterSnapshotBase::ImplBase::setStatus(EStatus status, bool ok, const std::string& msg) { - LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); switch (status) { case STATUS_READY: - setWorking(floater, false); - setFinished(floater, false); + setWorking(false); + setFinished(false); break; case STATUS_WORKING: - setWorking(floater, true); - setFinished(floater, false); + setWorking(true); + setFinished(false); break; case STATUS_FINISHED: - setWorking(floater, false); - setFinished(floater, true, ok, msg); + setWorking(false); + setFinished(true, ok, msg); break; } - floater->impl.mStatus = status; + mStatus = status; } -// static -void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need) +// virtual +void LLFloaterSnapshotBase::ImplBase::setNeedRefresh(bool need) { - if (!floater) return; + if (!mFloater) return; // Don't display the "Refresh to save" message if we're in auto-refresh mode. if (gSavedSettings.getBOOL("AutoSnapshot")) @@ -529,12 +424,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne need = false; } - floater->mRefreshLabel->setVisible(need); - floater->impl.mNeedRefresh = need; + mFloater->setRefreshLabelVisible(need); + mNeedRefresh = need; } -// static -void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail) +// virtual +void LLFloaterSnapshotBase::ImplBase::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail) { if (previewp) { @@ -545,43 +440,43 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, } // static -void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) +void LLFloaterSnapshotBase::ImplBase::onClickNewSnapshot(void* data) { - LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (previewp && view) + LLFloaterSnapshotBase* floater = (LLFloaterSnapshotBase *)data; + LLSnapshotLivePreview* previewp = floater->getPreviewView(); + if (previewp) { - view->impl.setStatus(Impl::STATUS_READY); + floater->impl->setStatus(ImplBase::STATUS_READY); LL_DEBUGS() << "updating snapshot" << LL_ENDL; previewp->mForceUpdateSnapshot = TRUE; } } // static -void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickAutoSnap(LLUICtrl *ctrl, void* data) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; gSavedSettings.setBOOL( "AutoSnapshot", check->get() ); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data; if (view) { - checkAutoSnapshot(getPreviewView(view)); - updateControls(view); + view->impl->checkAutoSnapshot(view->getPreviewView()); + view->impl->updateControls(view); } } // static -void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data) { - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data; if (view) { - updateControls(view); - LLSnapshotLivePreview* previewp = getPreviewView(view); + view->impl->updateControls(view); + LLSnapshotLivePreview* previewp = view->getPreviewView(); if (previewp) { - checkAutoSnapshot(previewp); + view->impl->checkAutoSnapshot(previewp); // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox")); std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); @@ -592,7 +487,7 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) } // static -void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() ); @@ -600,17 +495,17 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = view->getPreviewView(); if(previewp) { previewp->updateSnapshot(TRUE, TRUE); } - updateControls(view); + view->impl->updateControls(view); } } // static -void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() ); @@ -618,17 +513,16 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = view->getPreviewView(); if(previewp) { previewp->updateSnapshot(TRUE, TRUE); } - updateControls(view); + view->impl->updateControls(view); } } -// static -void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked) +void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked) { gSavedSettings.setBOOL("KeepAspectForSnapshot", checked); @@ -641,7 +535,7 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index } - LLSnapshotLivePreview* previewp = getPreviewView(view) ; + LLSnapshotLivePreview* previewp = getPreviewView() ; if(previewp) { previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; @@ -659,11 +553,11 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL } // static -void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data; + LLSnapshotLivePreview* previewp = view->getPreviewView(); if (!view || !check_box || !previewp) { @@ -677,16 +571,15 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) previewp->prepareFreezeFrame(); } - updateLayout(view); + view->impl->updateLayout(view); } -// static -void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index) +void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshotBase *view, S32 index) { - LLSnapshotLivePreview *previewp = getPreviewView(view) ; + LLSnapshotLivePreview *previewp = getPreviewView() ; // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here - if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view)) + if (LLSnapshotModel::SNAPSHOT_TEXTURE == getActiveSnapshotType(view)) { previewp->mKeepAspectRatio = FALSE ; return ; @@ -710,7 +603,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde keep_aspect = FALSE; } - view->impl.mAspectRatioCheckOff = !enable_cb; + view->impl->mAspectRatioCheckOff = !enable_cb; if (previewp) { @@ -719,51 +612,55 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde } // Show/hide upload progress indicators. -// static -void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working) +void LLFloaterSnapshotBase::ImplBase::setWorking(bool working) { - LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl"); + LLUICtrl* working_lbl = mFloater->getChild<LLUICtrl>("working_lbl"); working_lbl->setVisible(working); - floater->getChild<LLUICtrl>("working_indicator")->setVisible(working); + mFloater->getChild<LLUICtrl>("working_indicator")->setVisible(working); if (working) { - const std::string panel_name = getActivePanel(floater, false)->getName(); - const std::string prefix = panel_name.substr(std::string("panel_snapshot_").size()); - std::string progress_text = floater->getString(prefix + "_" + "progress_str"); + const std::string panel_name = getActivePanel(mFloater, false)->getName(); + const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size()); + std::string progress_text = mFloater->getString(prefix + "_" + "progress_str"); working_lbl->setValue(progress_text); } // All controls should be disabled while posting. - floater->setCtrlsEnabled(!working); - LLPanelSnapshot* active_panel = getActivePanel(floater); + mFloater->setCtrlsEnabled(!working); + LLPanelSnapshot* active_panel = getActivePanel(mFloater); if (active_panel) { active_panel->enableControls(!working); } } +//virtual +std::string LLFloaterSnapshot::Impl::getSnapshotPanelPrefix() +{ + return "panel_snapshot_"; +} + // Show/hide upload status message. -// static -void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg) +// virtual +void LLFloaterSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg) { - floater->mSucceessLblPanel->setVisible(finished && ok); - floater->mFailureLblPanel->setVisible(finished && !ok); + mFloater->setSuccessLabelPanelVisible(finished && ok); + mFloater->setFailureLabelPanelVisible(finished && !ok); if (finished) { - LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); - std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); + LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); + std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); finished_lbl->setValue(result_text); - LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); + LLSideTrayPanelContainer* panel_container = mFloater->getChild<LLSideTrayPanelContainer>("panel_container"); panel_container->openPreviousPanel(); panel_container->getCurrentPanel()->onOpen(LLSD()); } } // Apply a new resolution selected from the given combobox. -// static void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update) { LLComboBox* combobox = (LLComboBox*)ctrl; @@ -783,7 +680,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL S32 width = sdres[0]; S32 height = sdres[1]; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && combobox->getCurrentIndex() >= 0) { S32 original_width = 0 , original_height = 0 ; @@ -813,7 +710,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL new_height = spanel->getTypedPreviewHeight(); // Limit custom size for inventory snapshots to 512x512 px. - if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE) { new_width = llmin(new_width, MAX_TEXTURE_SIZE); new_height = llmin(new_height, MAX_TEXTURE_SIZE); @@ -851,7 +748,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL { getWidthSpinner(view)->setValue(width); getHeightSpinner(view)->setValue(height); - if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE) { getWidthSpinner(view)->setIncrement(width >> 1); getHeightSpinner(view)->setIncrement(height >> 1); @@ -865,7 +762,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL // hide old preview as the aspect ratio could be wrong checkAutoSnapshot(previewp, FALSE); LL_DEBUGS() << "updating thumbnail" << LL_ENDL; - getPreviewView(view)->updateSnapshot(TRUE); + getPreviewView()->updateSnapshot(TRUE); if(do_update) { LL_DEBUGS() << "Will update controls" << LL_ENDL; @@ -884,40 +781,37 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data) if (view) { - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = view->getPreviewView(); if (previewp) { - previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex()); + previewp->setSnapshotBufferType((LLSnapshotModel::ESnapshotLayerType)combobox->getCurrentIndex()); } - checkAutoSnapshot(previewp, TRUE); + view->impl->checkAutoSnapshot(previewp, TRUE); } } -// static -void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val) +void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val) { - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { previewp->setSnapshotQuality(quality_val); } } -// static -void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view) +void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshotBase* view) { if (view) { gSavedSettings.setS32("SnapshotFormat", getImageFormat(view)); LL_DEBUGS() << "image format changed, updating snapshot" << LL_ENDL; - getPreviewView(view)->updateSnapshot(TRUE); + getPreviewView()->updateSnapshot(TRUE); updateControls(view); } } // Sets the named size combo to "custom" mode. -// static -void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname) +void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshotBase* floater, const std::string& comboname) { LLComboBox* combo = floater->getChild<LLComboBox>(comboname); combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index @@ -925,7 +819,6 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s } // Update supplied width and height according to the constrain proportions flag; limit them by max_val. -//static BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value) { S32 w = width ; @@ -970,20 +863,18 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3 return (w != width || h != height) ; } -//static -void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) +void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshotBase* view, S32 width, S32 height) { getWidthSpinner(view)->forceSetValue(width); getHeightSpinner(view)->forceSetValue(height); - if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE) { getWidthSpinner(view)->setIncrement(width >> 1); getHeightSpinner(view)->setIncrement(height >> 1); } } -// static -void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed) +void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed) { getWidthSpinner(view)->resetDirty(); getHeightSpinner(view)->resetDirty(); @@ -993,13 +884,12 @@ void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshot } } -// static -void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h) +void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h) { LL_DEBUGS() << "applyCustomResolution(" << w << ", " << h << ")" << LL_ENDL; if (!view) return; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { S32 curw,curh; @@ -1023,90 +913,104 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 } // static -void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status) +void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status) { - setStatus(STATUS_FINISHED, status, "profile"); + floater->impl->setStatus(STATUS_FINISHED, status, "profile"); } - // static -void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status) +void LLFloaterSnapshot::Impl::onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status) { - setStatus(STATUS_FINISHED, status, "postcard"); + floater->impl->setStatus(STATUS_FINISHED, status, "postcard"); } ///---------------------------------------------------------------------------- -/// Class LLFloaterSnapshot +/// Class LLFloaterSnapshotBase ///---------------------------------------------------------------------------- // Default constructor -LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) - : LLFloater(key), +LLFloaterSnapshotBase::LLFloaterSnapshotBase(const LLSD& key) + : LLFloater(key), mRefreshBtn(NULL), mRefreshLabel(NULL), mSucceessLblPanel(NULL), - mFailureLblPanel(NULL), - impl (*(new Impl)) + mFailureLblPanel(NULL) { } -// Destroys the object -LLFloaterSnapshot::~LLFloaterSnapshot() +LLFloaterSnapshotBase::~LLFloaterSnapshotBase() { - if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die(); + if (impl->mPreviewHandle.get()) impl->mPreviewHandle.get()->die(); //unfreeze everything else gSavedSettings.setBOOL("FreezeTime", FALSE); - if (impl.mLastToolset) + if (impl->mLastToolset) { - LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset); + LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset); } - delete &impl; + delete impl; } +///---------------------------------------------------------------------------- +/// Class LLFloaterSnapshot +///---------------------------------------------------------------------------- +// Default constructor +LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) + : LLFloaterSnapshotBase(key) +{ + impl = new Impl(this); +} + +LLFloaterSnapshot::~LLFloaterSnapshot() +{ +} + +// virtual BOOL LLFloaterSnapshot::postBuild() { mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); - childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); + childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this); mRefreshLabel = getChild<LLUICtrl>("refresh_lbl"); mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel"); mFailureLblPanel = getChild<LLUICtrl>("failed_panel"); - childSetCommitCallback("ui_check", Impl::onClickUICheck, this); + childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this); getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); - childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this); + childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this); getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); - impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot")); + ((Impl*)impl)->setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot")); childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this); getChild<LLUICtrl>("layer_types")->setValue("colors"); getChildView("layer_types")->setEnabled(FALSE); getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); - childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this); + childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this); getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); - childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); - + childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this); + + getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this)); + getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this)); // Filters LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox"); - std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - for (U32 i = 0; i < filter_list.size(); i++) - { - filterbox->add(filter_list[i]); - } - childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this); - LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); - LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); + LLWebProfile::setImageUploadResultCallback(boost::bind(&Impl::onSnapshotUploadFinished, this, _1)); + LLPostCard::setPostResultCallback(boost::bind(&Impl::onSendingPostcardFinished, this, _1)); - sThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); + mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); // create preview window LLRect full_screen_rect = getRootView()->getRect(); @@ -1131,10 +1035,11 @@ BOOL LLFloaterSnapshot::postBuild() getChild<LLComboBox>("local_size_combo")->selectNthItem(8); getChild<LLComboBox>("local_format_combo")->selectNthItem(0); - impl.mPreviewHandle = previewp->getHandle(); + impl->mPreviewHandle = previewp->getHandle(); previewp->setContainer(this); - impl.updateControls(this); - impl.updateLayout(this); + impl->updateControls(this); + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot")); + impl->updateLayout(this); previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); @@ -1142,9 +1047,10 @@ BOOL LLFloaterSnapshot::postBuild() return TRUE; } -void LLFloaterSnapshot::draw() +// virtual +void LLFloaterSnapshotBase::draw() { - LLSnapshotLivePreview* previewp = impl.getPreviewView(this); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock())) { @@ -1154,11 +1060,11 @@ void LLFloaterSnapshot::draw() LLFloater::draw(); - if (previewp && !isMinimized() && sThumbnailPlaceholder->getVisible()) + if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible()) { if(previewp->getThumbnailImage()) { - bool working = impl.getStatus() == Impl::STATUS_WORKING; + bool working = impl->getStatus() == ImplBase::STATUS_WORKING; const LLRect& thumbnail_rect = getThumbnailPlaceholderRect(); const S32 thumbnail_w = previewp->getThumbnailWidth(); const S32 thumbnail_h = previewp->getThumbnailHeight(); @@ -1183,16 +1089,17 @@ void LLFloaterSnapshot::draw() gGL.pushUIMatrix(); LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom); - sThumbnailPlaceholder->draw(); + mThumbnailPlaceholder->draw(); gGL.popUIMatrix(); } } - impl.updateLayout(this); + impl->updateLayout(this); } +//virtual void LLFloaterSnapshot::onOpen(const LLSD& key) { - LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(this); + LLSnapshotLivePreview* preview = getPreviewView(); if(preview) { LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; @@ -1203,19 +1110,26 @@ void LLFloaterSnapshot::onOpen(const LLSD& key) gSnapshotFloaterView->setVisible(TRUE); gSnapshotFloaterView->adjustToFitScreen(this, FALSE); - impl.updateControls(this); - impl.updateLayout(this); + impl->updateControls(this); + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot")); + impl->updateLayout(this); // Initialize default tab. getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD()); } -void LLFloaterSnapshot::onClose(bool app_quitting) +void LLFloaterSnapshot::onExtendFloater() +{ + impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot")); +} + +//virtual +void LLFloaterSnapshotBase::onClose(bool app_quitting) { getParent()->setMouseOpaque(FALSE); //unfreeze everything, hide fullscreen preview - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { previewp->setVisible(FALSE); @@ -1223,125 +1137,145 @@ void LLFloaterSnapshot::onClose(bool app_quitting) } gSavedSettings.setBOOL("FreezeTime", FALSE); - impl.mAvatarPauseHandles.clear(); + impl->mAvatarPauseHandles.clear(); - if (impl.mLastToolset) + if (impl->mLastToolset) { - LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset); + LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset); } } // virtual -S32 LLFloaterSnapshot::notify(const LLSD& info) +S32 LLFloaterSnapshotBase::notify(const LLSD& info) { - // A child panel wants to change snapshot resolution. - if (info.has("combo-res-change")) + if (info.has("set-ready")) { - std::string combo_name = info["combo-res-change"]["control-name"].asString(); - impl.updateResolution(getChild<LLUICtrl>(combo_name), this); + impl->setStatus(ImplBase::STATUS_READY); return 1; } - if (info.has("custom-res-change")) + if (info.has("set-working")) { - LLSD res = info["custom-res-change"]; - impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger()); + impl->setStatus(ImplBase::STATUS_WORKING); return 1; } - if (info.has("keep-aspect-change")) + if (info.has("set-finished")) { - impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean()); + LLSD data = info["set-finished"]; + impl->setStatus(ImplBase::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString()); return 1; } - if (info.has("image-quality-change")) + if (info.has("snapshot-updating")) { - impl.onImageQualityChange(this, info["image-quality-change"].asInteger()); + // Disable the send/post/save buttons until snapshot is ready. + impl->updateControls(this); return 1; } - if (info.has("image-format-change")) + if (info.has("snapshot-updated")) { - impl.onImageFormatChange(this); + // Enable the send/post/save buttons. + impl->updateControls(this); + // We've just done refresh. + impl->setNeedRefresh(false); + + // The refresh button is initially hidden. We show it after the first update, + // i.e. when preview appears. + if (!mRefreshBtn->getVisible()) + { + mRefreshBtn->setVisible(true); + } return 1; } - if (info.has("set-ready")) + return 0; +} + +// virtual +S32 LLFloaterSnapshot::notify(const LLSD& info) +{ + bool res = LLFloaterSnapshotBase::notify(info); + if (res) + return res; + // A child panel wants to change snapshot resolution. + if (info.has("combo-res-change")) { - impl.setStatus(Impl::STATUS_READY); + std::string combo_name = info["combo-res-change"]["control-name"].asString(); + ((Impl*)impl)->updateResolution(getChild<LLUICtrl>(combo_name), this); return 1; } - if (info.has("set-working")) + if (info.has("custom-res-change")) { - impl.setStatus(Impl::STATUS_WORKING); + LLSD res = info["custom-res-change"]; + ((Impl*)impl)->applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger()); return 1; } - if (info.has("set-finished")) + if (info.has("keep-aspect-change")) { - LLSD data = info["set-finished"]; - impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString()); + ((Impl*)impl)->applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean()); return 1; } - - if (info.has("snapshot-updating")) + + if (info.has("image-quality-change")) { - // Disable the send/post/save buttons until snapshot is ready. - impl.updateControls(this); + ((Impl*)impl)->onImageQualityChange(this, info["image-quality-change"].asInteger()); return 1; } - if (info.has("snapshot-updated")) + if (info.has("image-format-change")) { - // Enable the send/post/save buttons. - impl.updateControls(this); - // We've just done refresh. - impl.setNeedRefresh(this, false); - - // The refresh button is initially hidden. We show it after the first update, - // i.e. when preview appears. - if (!mRefreshBtn->getVisible()) - { - mRefreshBtn->setVisible(true); - } + ((Impl*)impl)->onImageFormatChange(this); return 1; - } + } return 0; } -//static -void LLFloaterSnapshot::update() +BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized) { - LLFloaterSnapshot* inst = findInstance(); - LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook"); - LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); - LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); + LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook"); + LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); + LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); + + if (!initialized && !floater_facebook && !floater_flickr && !floater_twitter) + return FALSE; - if (!inst && !floater_facebook && !floater_flickr && !floater_twitter) - return; - BOOL changed = FALSE; LL_DEBUGS() << "npreviews: " << LLSnapshotLivePreview::sList.size() << LL_ENDL; for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin(); - iter != LLSnapshotLivePreview::sList.end(); ++iter) + iter != LLSnapshotLivePreview::sList.end(); ++iter) { changed |= LLSnapshotLivePreview::onIdle(*iter); } - - if (inst && changed) + return changed; +} + + +void LLFloaterSnapshotBase::ImplBase::updateLivePreview() +{ + if (ImplBase::updatePreviewList(true) && mFloater) { LL_DEBUGS() << "changed" << LL_ENDL; - inst->impl.updateControls(inst); + updateControls(mFloater); } } -// static -LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +//static +void LLFloaterSnapshot::update() { - return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); + LLFloaterSnapshot* inst = findInstance(); + if (inst != NULL) + { + inst->impl->updateLivePreview(); + } + else + { + ImplBase::updatePreviewList(false); + } } // static @@ -1351,18 +1285,17 @@ LLFloaterSnapshot* LLFloaterSnapshot::findInstance() } // static +LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); +} + +// virtual void LLFloaterSnapshot::saveTexture() { LL_DEBUGS() << "saveTexture" << LL_ENDL; - // FIXME: duplicated code - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return; - } - LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + LLSnapshotLivePreview* previewp = getPreviewView(); if (!previewp) { llassert(previewp != NULL); @@ -1372,18 +1305,10 @@ void LLFloaterSnapshot::saveTexture() previewp->saveTexture(); } -// static BOOL LLFloaterSnapshot::saveLocal() { LL_DEBUGS() << "saveLocal" << LL_ENDL; - // FIXME: duplicated code - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return FALSE; - } - LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + LLSnapshotLivePreview* previewp = getPreviewView(); if (!previewp) { llassert(previewp != NULL); @@ -1393,57 +1318,32 @@ BOOL LLFloaterSnapshot::saveLocal() return previewp->saveLocal(); } -// static -void LLFloaterSnapshot::postSave() +void LLFloaterSnapshotBase::postSave() { - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return; - } - - instance->impl.updateControls(instance); - instance->impl.setStatus(Impl::STATUS_WORKING); + impl->updateControls(this); + impl->setStatus(ImplBase::STATUS_WORKING); } -// static -void LLFloaterSnapshot::postPanelSwitch() +// virtual +void LLFloaterSnapshotBase::postPanelSwitch() { - LLFloaterSnapshot* instance = getInstance(); - instance->impl.updateControls(instance); + impl->updateControls(this); // Remove the success/failure indicator whenever user presses a snapshot option button. - instance->impl.setStatus(Impl::STATUS_READY); + impl->setStatus(ImplBase::STATUS_READY); } -// static -void LLFloaterSnapshot::inventorySaveFailed() +void LLFloaterSnapshotBase::inventorySaveFailed() { - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return; - } - - instance->impl.updateControls(instance); - instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory"); + impl->updateControls(this); + impl->setStatus(ImplBase::STATUS_FINISHED, false, "inventory"); } -// static -LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() +LLPointer<LLImageFormatted> LLFloaterSnapshotBase::getImageData() { // FIXME: May not work for textures. - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return NULL; - } - - LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + LLSnapshotLivePreview* previewp = getPreviewView(); if (!previewp) { llassert(previewp != NULL); @@ -1460,17 +1360,9 @@ LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() return img; } -// static -const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal() +const LLVector3d& LLFloaterSnapshotBase::getPosTakenGlobal() { - LLFloaterSnapshot* instance = findInstance(); - if (!instance) - { - llassert(instance != NULL); - return LLVector3d::zero; - } - - LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + LLSnapshotLivePreview* previewp = getPreviewView(); if (!previewp) { llassert(previewp != NULL); @@ -1504,6 +1396,7 @@ LLSnapshotFloaterView::~LLSnapshotFloaterView() { } +// virtual BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent) { // use default handler when not in freeze-frame mode @@ -1525,6 +1418,7 @@ BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_paren return TRUE; } +// virtual BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask) { // use default handler when not in freeze-frame mode @@ -1540,6 +1434,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask) return TRUE; } +// virtual BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask) { // use default handler when not in freeze-frame mode @@ -1555,6 +1450,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } +// virtual BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask) { // use default handler when not in freeze-frame mode diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index eb3a94999b..1f303ea4d6 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2016, 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 @@ -27,54 +27,184 @@ #ifndef LL_LLFLOATERSNAPSHOT_H #define LL_LLFLOATERSNAPSHOT_H +#include "llagent.h" #include "llfloater.h" +#include "llpanelsnapshot.h" +#include "llsnapshotmodel.h" class LLSpinCtrl; +class LLSnapshotLivePreview; -class LLFloaterSnapshot : public LLFloater +class LLFloaterSnapshotBase : public LLFloater { - LOG_CLASS(LLFloaterSnapshot); + LOG_CLASS(LLFloaterSnapshotBase); + +public: + + LLFloaterSnapshotBase(const LLSD& key); + virtual ~LLFloaterSnapshotBase(); + + /*virtual*/ void draw(); + /*virtual*/ void onClose(bool app_quitting); + virtual S32 notify(const LLSD& info); + + // TODO: create a snapshot model instead + virtual void saveTexture() = 0; + void postSave(); + virtual void postPanelSwitch(); + LLPointer<LLImageFormatted> getImageData(); + LLSnapshotLivePreview* getPreviewView(); + const LLVector3d& getPosTakenGlobal(); + + const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } + void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); } + void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); } + void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); } + void inventorySaveFailed(); + + class ImplBase; + friend class ImplBase; + ImplBase* impl; + +protected: + LLUICtrl* mThumbnailPlaceholder; + LLUICtrl *mRefreshBtn, *mRefreshLabel; + LLUICtrl *mSucceessLblPanel, *mFailureLblPanel; +}; + +class LLFloaterSnapshotBase::ImplBase +{ public: - typedef enum e_snapshot_format + typedef enum e_status { - SNAPSHOT_FORMAT_PNG, - SNAPSHOT_FORMAT_JPEG, - SNAPSHOT_FORMAT_BMP - } ESnapshotFormat; + STATUS_READY, + STATUS_WORKING, + STATUS_FINISHED + } EStatus; + + ImplBase(LLFloaterSnapshotBase* floater) : mAvatarPauseHandles(), + mLastToolset(NULL), + mAspectRatioCheckOff(false), + mNeedRefresh(false), + mStatus(STATUS_READY), + mFloater(floater) + {} + virtual ~ImplBase() + { + //unpause avatars + mAvatarPauseHandles.clear(); + } + + static void onClickNewSnapshot(void* data); + static void onClickAutoSnap(LLUICtrl *ctrl, void* data); + static void onClickFilter(LLUICtrl *ctrl, void* data); + static void onClickUICheck(LLUICtrl *ctrl, void* data); + static void onClickHUDCheck(LLUICtrl *ctrl, void* data); + static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); + + virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0; + virtual LLSnapshotModel::ESnapshotType getActiveSnapshotType(LLFloaterSnapshotBase* floater); + virtual LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater) = 0; + virtual std::string getSnapshotPanelPrefix() = 0; + + LLSnapshotLivePreview* getPreviewView(); + virtual void updateControls(LLFloaterSnapshotBase* floater) = 0; + virtual void updateLayout(LLFloaterSnapshotBase* floater); + virtual void updateLivePreview(); + virtual void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); + virtual EStatus getStatus() const { return mStatus; } + virtual void setNeedRefresh(bool need); + + static BOOL updatePreviewList(bool initialized); + + void setAdvanced(bool advanced) { mAdvanced = advanced; } + + virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0; + virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); + void setWorking(bool working); + virtual void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) = 0; + +public: + LLFloaterSnapshotBase* mFloater; + std::vector<LLAnimPauseRequest> mAvatarPauseHandles; + + LLToolset* mLastToolset; + LLHandle<LLView> mPreviewHandle; + bool mAspectRatioCheckOff; + bool mNeedRefresh; + bool mAdvanced; + EStatus mStatus; +}; + +class LLFloaterSnapshot : public LLFloaterSnapshotBase +{ + LOG_CLASS(LLFloaterSnapshot); +public: LLFloaterSnapshot(const LLSD& key); - virtual ~LLFloaterSnapshot(); + /*virtual*/ ~LLFloaterSnapshot(); /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); /*virtual*/ S32 notify(const LLSD& info); static void update(); - // TODO: create a snapshot model instead + void onExtendFloater(); + static LLFloaterSnapshot* getInstance(); static LLFloaterSnapshot* findInstance(); - static void saveTexture(); - static BOOL saveLocal(); - static void postSave(); - static void postPanelSwitch(); - static void inventorySaveFailed(); - static LLPointer<LLImageFormatted> getImageData(); - static const LLVector3d& getPosTakenGlobal(); + /*virtual*/ void saveTexture(); + BOOL saveLocal(); static void setAgentEmail(const std::string& email); - static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); } + class Impl; + friend class Impl; +}; -private: - static LLUICtrl* sThumbnailPlaceholder; - LLUICtrl *mRefreshBtn, *mRefreshLabel; - LLUICtrl *mSucceessLblPanel, *mFailureLblPanel; +///---------------------------------------------------------------------------- +/// Class LLFloaterSnapshot::Impl +///---------------------------------------------------------------------------- - class Impl; - Impl& impl; +class LLFloaterSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase +{ + LOG_CLASS(LLFloaterSnapshot::Impl); +public: + Impl(LLFloaterSnapshotBase* floater) + : LLFloaterSnapshotBase::ImplBase(floater) + {} + ~Impl() + {} + + void applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked); + void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); + static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); + void onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val); + void onImageFormatChange(LLFloaterSnapshotBase* view); + void applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h); + static void onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status); + BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); + void setImageSizeSpinnersValues(LLFloaterSnapshotBase *view, S32 width, S32 height); + void updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed); + static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); + + /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true); + /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); + LLSpinCtrl* getWidthSpinner(LLFloaterSnapshotBase* floater); + LLSpinCtrl* getHeightSpinner(LLFloaterSnapshotBase* floater); + void enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable); + void setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked); + /*virtual*/ std::string getSnapshotPanelPrefix(); + + void setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname); + /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater); + +private: + /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); + void comboSetCustom(LLFloaterSnapshotBase *floater, const std::string& comboname); + void checkAspectRatio(LLFloaterSnapshotBase *view, S32 index); + void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); }; class LLSnapshotFloaterView : public LLFloaterView diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index c48b1a3325..4bab89ace2 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -241,8 +241,8 @@ void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible) mPreviewHandle = previewp->getHandle(); previewp->setContainer(this); - previewp->setSnapshotType(previewp->SNAPSHOT_WEB); - previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB); + previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG); previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 024e315632..dece3fc1ea 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -55,7 +55,8 @@ LLFloaterWebContent::_Params::_Params() preferred_media_size("preferred_media_size"), trusted_content("trusted_content", false), show_page_title("show_page_title", true), - clean_browser("clean_browser", false) + clean_browser("clean_browser", false), + dev_mode("dev_mode", false) {} LLFloaterWebContent::LLFloaterWebContent( const Params& params ) @@ -74,14 +75,16 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params ) mShowPageTitle(params.show_page_title), mAllowNavigation(true), mCurrentURL(""), - mDisplayURL("") + mDisplayURL(""), + mDevelopMode(params.dev_mode) // if called from "Develop" Menu, set a flag and change things to be more useful for devs { mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); - mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); + mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this)); + mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2)); } BOOL LLFloaterWebContent::postBuild() @@ -195,8 +198,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) width + getRect().getWidth() - browser_rect.getWidth(), height + getRect().getHeight() - browser_rect.getHeight()); - LL_DEBUGS() << "geometry change: " << geom << LL_ENDL; - LLRect new_rect; getParent()->screenRectToLocal(geom, &new_rect); setShape(new_rect); @@ -205,8 +206,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) // static void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) { - LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL; - if (!p.id.isProvided()) { p.id = LLUUID::generateNewID().asString(); @@ -224,12 +223,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) // and close the least recently opened one if this will put us over the limit. LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class); - LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL; - - for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) - { - LL_DEBUGS() << " " << (*iter)->getKey()["target"] << LL_ENDL; - } if(instances.size() >= (size_t)browser_window_limit) { @@ -241,16 +234,19 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p) void LLFloaterWebContent::open_media(const Params& p) { - // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); - mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML); + mWebBrowser->setHomePageUrl(p.url); mWebBrowser->setTarget(p.target); - mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser); + mWebBrowser->navigateTo(p.url); set_current_url(p.url); getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome); getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome); + + // turn additional debug controls on but only for Develop mode (Develop menu open) + getChild<LLLayoutPanel>("debug_controls")->setVisible(mDevelopMode); + bool address_entry_enabled = p.allow_address_entry && !p.trusted_content; mAllowNavigation = p.allow_back_forward_navigation; getChildView("address")->setEnabled(address_entry_enabled); @@ -499,7 +495,7 @@ void LLFloaterWebContent::onEnterAddress() LLStringUtil::trim(url); if ( url.length() > 0 ) { - mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + mWebBrowser->navigateTo(url); }; } @@ -508,9 +504,18 @@ void LLFloaterWebContent::onPopExternal() // make sure there is at least something there. // (perhaps this test should be for minimum length of a URL) std::string url = mAddressCombo->getValue().asString(); - LLStringUtil::trim(url); - if ( url.length() > 0 ) + LLStringUtil::trim(url); + if (url.length() > 0) + { + LLWeb::loadURLExternal(url); + }; +} + +void LLFloaterWebContent::onTestURL(std::string url) +{ + LLStringUtil::trim(url); + if (url.length() > 0) { - LLWeb::loadURLExternal( url ); + mWebBrowser->navigateTo(url); }; } diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 4291fd9f2c..0bf93504c2 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -58,7 +58,8 @@ public: allow_back_forward_navigation, trusted_content, show_page_title, - clean_browser; + clean_browser, + dev_mode; Optional<LLRect> preferred_media_size; _Params(); @@ -92,6 +93,7 @@ protected: void onClickStop(); void onEnterAddress(); void onPopExternal(); + void onTestURL(std::string url); static void preCreate(Params& p); void open_media(const Params& ); @@ -113,6 +115,7 @@ protected: std::string mUUID; bool mShowPageTitle; bool mAllowNavigation; + bool mDevelopMode; }; #endif // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp index 271dd44c1f..7c2a3cad43 100644 --- a/indra/newview/llgroupiconctrl.cpp +++ b/indra/newview/llgroupiconctrl.cpp @@ -74,9 +74,16 @@ LLGroupIconCtrl::~LLGroupIconCtrl() LLGroupMgr::getInstance()->removeObserver(this); } -void LLGroupIconCtrl::setIconId(const LLSD& value) +void LLGroupIconCtrl::setIconId(const LLUUID& icon_id) { - LLIconCtrl::setValue(value); + if (icon_id.notNull()) + { + LLIconCtrl::setValue(icon_id); + } + else + { + LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI); + } } void LLGroupIconCtrl::setValue(const LLSD& value) @@ -122,14 +129,7 @@ bool LLGroupIconCtrl::updateFromCache() LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId); if (!group_data) return false; - if (group_data->mInsigniaID.notNull()) - { - LLIconCtrl::setValue(group_data->mInsigniaID); - } - else - { - LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI); - } + setIconId(group_data->mInsigniaID); if (mDrawTooltip && !group_data->mName.empty()) { diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h index f8b22cf581..43e384d3e2 100644 --- a/indra/newview/llgroupiconctrl.h +++ b/indra/newview/llgroupiconctrl.h @@ -66,7 +66,13 @@ public: */ virtual void setValue(const LLSD& value); - void setIconId(const LLSD& value); + /** + * Sets icon_id as icon value directly. Avoids LLGroupMgr cache checks for group id + * Uses default icon in case id is null. + * + * @params icon_id - it is processed as icon id, default image will be used in case id is null. + */ + void setIconId(const LLUUID& icon_id); // LLGroupMgrObserver observer trigger virtual void changed(LLGroupChange gc); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 6126db2988..62414d3bbb 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -379,10 +379,7 @@ void LLGroupListItem::setGroupID(const LLUUID& group_id) void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id) { - if (group_icon_id.notNull()) - { - mGroupIcon->setIconId(group_icon_id); - } + mGroupIcon->setIconId(group_icon_id); } void LLGroupListItem::setGroupIconVisible(bool visible) diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 52e83fe412..6b1e196182 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -53,7 +53,7 @@ const F32 VERTICAL_PADDING = 12.f; const F32 BUFFER_SIZE = 2.f; const F32 HUD_TEXT_MAX_WIDTH = 190.f; const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f; -const F32 MAX_DRAW_DISTANCE = 64.f; +const F32 MAX_DRAW_DISTANCE = 300.f; std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects; std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects; @@ -394,7 +394,20 @@ void LLHUDText::updateVisibility() LLVector3 pos_agent_center = gAgent.getPosAgentFromGlobal(mPositionGlobal) - dir_from_camera; F32 last_distance_center = (pos_agent_center - LLViewerCamera::getInstance()->getOrigin()).magVec(); - if(last_distance_center > MAX_DRAW_DISTANCE) + F32 max_draw_distance = gSavedSettings.getF32("PrimTextMaxDrawDistance"); + + if(max_draw_distance < 0) + { + max_draw_distance = 0; + gSavedSettings.setF32("PrimTextMaxDrawDistance", max_draw_distance); + } + else if(max_draw_distance > MAX_DRAW_DISTANCE) + { + max_draw_distance = MAX_DRAW_DISTANCE; + gSavedSettings.setF32("PrimTextMaxDrawDistance", MAX_DRAW_DISTANCE); + } + + if(last_distance_center > max_draw_distance) { mVisible = FALSE; return; diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp index 8e91af321e..a4fce36783 100644 --- a/indra/newview/llinspectgroup.cpp +++ b/indra/newview/llinspectgroup.cpp @@ -41,6 +41,7 @@ #include "lltooltip.h" // positionViewNearMouse() #include "lltrans.h" #include "lluictrl.h" +#include "llgroupiconctrl.h" ////////////////////////////////////////////////////////////////////////////// // LLInspectGroup @@ -233,7 +234,7 @@ void LLInspectGroup::processGroupData() getChild<LLUICtrl>("group_details")->setValue( LLSD(data->mCharter) ); - getChild<LLUICtrl>("group_icon")->setValue( LLSD(data->mInsigniaID) ); + getChild<LLGroupIconCtrl>("group_icon")->setIconId(data->mInsigniaID); std::string cost; bool is_member = LLGroupActions::isInGroup(mGroupID); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 26c9b40fb1..eebb6a0384 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -286,6 +286,16 @@ BOOL LLInvFVBridge::cutToClipboard() return FALSE; } +// virtual +bool LLInvFVBridge::isCutToClipboard() +{ + if (LLClipboard::instance().isCutMode()) + { + return LLClipboard::instance().isOnClipboard(mUUID); + } + return false; +} + // Callback for cutToClipboard if DAMA required... BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response) { @@ -307,9 +317,7 @@ BOOL LLInvFVBridge::perform_cutToClipboard() if (obj && isItemMovable() && isItemRemovable()) { LLClipboard::instance().setCutMode(true); - BOOL added_to_clipboard = LLClipboard::instance().addToClipboard(mUUID); - removeObject(&gInventory, mUUID); // Always perform the remove even if the object couldn't make it to the clipboard - return added_to_clipboard; + return LLClipboard::instance().addToClipboard(mUUID); } return FALSE; } @@ -1390,6 +1398,12 @@ bool LLInvFVBridge::canShare() const // Categories can be given. can_share = (model->getCategory(mUUID) != NULL); } + + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if ((mUUID == trash_id) || gInventory.isObjectDescendentOf(mUUID, trash_id)) + { + can_share = false; + } } } @@ -1925,13 +1939,15 @@ BOOL LLItemBridge::removeItem() } // move it to the trash - LLPreview::hide(mUUID, TRUE); LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); LLViewerInventoryItem* item = getItem(); if (!item) return FALSE; - + if (item->getType() != LLAssetType::AT_LSL_TEXT) + { + LLPreview::hide(mUUID, TRUE); + } // Already in trash if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE; @@ -4358,10 +4374,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response // Returns true if the item can be moved to Current Outfit or any outfit folder. static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) { - if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && - (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && - (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) && - (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) + LLInventoryType::EType inv_type = inv_item->getInventoryType(); + if ((inv_type != LLInventoryType::IT_WEARABLE) && + (inv_type != LLInventoryType::IT_GESTURE) && + (inv_type != LLInventoryType::IT_ATTACHMENT) && + (inv_type != LLInventoryType::IT_OBJECT) && + (inv_type != LLInventoryType::IT_SNAPSHOT) && + (inv_type != LLInventoryType::IT_TEXTURE)) { return FALSE; } @@ -4372,6 +4391,11 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr return FALSE; } + if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT)) + { + return TRUE; + } + if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID())) { return FALSE; @@ -4422,6 +4446,14 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) { + if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)) + { + LLAppearanceMgr::instance().removeOutfitPhoto(mUUID); + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb); + return; + } + // BAP - should skip if dup. if (move_is_into_current_outfit) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 9053c61171..df25e01688 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -116,6 +116,7 @@ public: virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard(); + virtual bool isCutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 003bbcafed..e995c138b4 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -84,21 +84,18 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); - // Clipboard cut items are *always* filtered so we need this value upfront - 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; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - return passed_clipboard; + return true; } bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true); passed = passed && checkAgainstFilterType(listener); passed = passed && checkAgainstPermissions(listener); passed = passed && checkAgainstFilterLinks(listener); - passed = passed && passed_clipboard; return passed; } @@ -108,9 +105,8 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true); const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); - const bool passed_clipboard = checkAgainstClipboard(item->getUUID()); - return passed_filtertype && passed_permissions && passed_clipboard && passed_string; + return passed_filtertype && passed_permissions && passed_string; } bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const @@ -129,13 +125,10 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { - // Always check against the clipboard - const BOOL passed_clipboard = checkAgainstClipboard(folder_id); - // we're showing all folders, overriding filter if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) { - return passed_clipboard; + return true; } // when applying a filter, matching folders get their contents downloaded first @@ -201,7 +194,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const LLViewerInventoryItem* item = gInventory.getItem(folder_id); if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) { - return passed_clipboard; + return true; } if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) @@ -216,7 +209,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return false; } - return passed_clipboard; + return true; } bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9a33e210ff..503fa28a33 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -582,7 +582,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, // Add the category to the internal representation LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 cat->setDescendentCount(0); LLCategoryUpdate update(cat->getParentUUID(), 1); accountForUpdate(update); @@ -640,7 +640,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), result["name"].asString(), gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 cat->setDescendentCount(0); LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); @@ -914,8 +914,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id); if( item_array ) { + LLInventoryModel::LLCategoryUpdate update(category_id, 1); + gInventory.accountForUpdate(update); + // *FIX: bit of a hack to call update server from here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -956,9 +959,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) { + LLInventoryModel::LLCategoryUpdate update(parent_id, 1); + gInventory.accountForUpdate(update); // *FIX: bit of a hack to call update server from // here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -1045,7 +1050,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 if(old_cat) { // We already have an old category, modify its values - U32 mask = LLInventoryObserver::NONE; LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) @@ -1100,7 +1104,8 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 item_array_t* itemsp = new item_array_t; mParentChildCategoryTree[new_cat->getUUID()] = catsp; mParentChildItemTree[new_cat->getUUID()] = itemsp; - addChangedMask(LLInventoryObserver::ADD, cat->getUUID()); + mask |= LLInventoryObserver::ADD; + addChangedMask(mask, cat->getUUID()); } } @@ -1390,7 +1395,11 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f } // From purgeObject() - LLPreview::hide(object_id); + LLViewerInventoryItem *item = getItem(object_id); + if (item && (item->getType() != LLAssetType::AT_LSL_TEXT)) + { + LLPreview::hide(object_id, TRUE); + } deleteObject(object_id, fix_broken_links, do_notify_observers); } } diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index aa934f95a1..a55938f334 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -181,7 +181,12 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) if (gDirUtilp->fileExists(mFilename)) { // verifying that the file has indeed been modified + +#ifndef LL_WINDOWS const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename)); +#else + const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(utf8str_to_utf16str(mFilename))); +#endif LLSD new_last_modified = asctime(localtime(&temp_time)); if (mLastModified.asString() != new_last_modified.asString()) diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 53b2ca2b74..11bc1425f9 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -243,7 +243,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) params.commit_on_focus_lost(false); params.follows.flags(FOLLOWS_ALL); mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params); - mTextEntry->setContextMenu(NULL); + mTextEntry->resetContextMenu(); addChild(mTextEntry); // LLLineEditor is replaced with LLLocationLineEditor diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 639641d1c2..485d4677b1 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -244,7 +244,10 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename = cleanFileName(filename); filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); - filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + if (!filename.empty()) + { + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } return filename; } diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 1fb05e047a..69881e8589 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -1,4 +1,4 @@ -/** +/** * @file llmanip.h * @brief LLManip class definition * @@ -37,7 +37,7 @@ class LLToolComposite; class LLVector3; class LLObjectSelection; -const S32 MIN_DIVISION_PIXEL_WIDTH = 9; +const S32 MIN_DIVISION_PIXEL_WIDTH = 3; class LLManip : public LLTool { diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b4259a456c..3975d3980b 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llmaniptranslate.cpp * @brief LLManipTranslate class implementation * @@ -548,12 +548,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) if (off_axis_magnitude > mSnapOffsetMeters) { mInSnapRegime = TRUE; - LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal); LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); - if (!gSavedSettings.getBOOL("SnapToMouseCursor")) - { - cursor_snap_agent -= mouse_down_offset; - } F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 6cc7a0fc99..54f95520db 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -773,7 +773,9 @@ void LLMarketplaceData::getMerchantStatusCoro() std::string url = getSLMConnectURL("/merchant"); if (url.empty()) { - LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL; + LL_WARNS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL; + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + return; } LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 9cf3249983..00043d1e72 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1007,7 +1007,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) std::string uuid = self->getClickUUID(); LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL; - LLWeb::loadURL(url, target, std::string()); + // try as slurl first + if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted)) + { + LLWeb::loadURL(url, target, std::string()); + } // CP: removing this code because we no longer support popups so this breaks the flow. // replaced with a bare call to LLWeb::LoadURL(...) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 54f8fb93d0..e42647739f 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1753,6 +1753,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size) { + if (data == NULL || data_size == 0) + { + return false; + } + LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); std::string mesh_string((char*) data, data_size); std::istringstream stream(mesh_string); @@ -3010,12 +3015,23 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b } else if (data && data_size > 0) { - // header was successfully retrieved from sim, cache in vfs - LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; + // header was successfully retrieved from sim and parsed, cache in vfs + S32 header_bytes = 0; + LLSD header; - S32 version = header["version"].asInteger(); + gMeshRepo.mThread->mHeaderMutex->lock(); + LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id); + if (iter != gMeshRepo.mThread->mMeshHeader.end()) + { + header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; + header = iter->second; + } + gMeshRepo.mThread->mHeaderMutex->unlock(); - if (version <= MAX_MESH_VERSION) + if (header_bytes > 0 + && !header.has("404") + && header.has("version") + && header["version"].asInteger() <= MAX_MESH_VERSION) { std::stringstream str; @@ -3064,6 +3080,17 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b } } } + else + { + LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL; + + // headerReceived() parsed header, but header's data is invalid so none of the LODs will be available + LLMutexLock lock(gMeshRepo.mThread->mMutex); + for (int i(0); i < 4; ++i) + { + gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + } + } } } @@ -4115,7 +4142,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32 } } - F32 max_area = 102932.f; //area of circle that encompasses region + F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559) F32 min_area = 1.f; F32 high_area = llmin(F_PI*dmid*dmid, max_area); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 70035bcc74..c3dd08c327 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -252,7 +252,7 @@ void LLFloaterMove::setSittingMode(BOOL bSitting) LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); } } - enableInstance(!bSitting); + enableInstance(); } // protected @@ -459,7 +459,7 @@ void LLFloaterMove::showModeButtons(BOOL bShow) } //static -void LLFloaterMove::enableInstance(BOOL bEnable) +void LLFloaterMove::enableInstance() { LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); if (instance) @@ -470,7 +470,7 @@ void LLFloaterMove::enableInstance(BOOL bEnable) } else { - instance->showModeButtons(bEnable); + instance->showModeButtons(isAgentAvatarValid() && !gAgentAvatarp->isSitting()); } } } @@ -566,7 +566,7 @@ BOOL LLPanelStandStopFlying::postBuild() { mStandButton = getChild<LLButton>("stand_btn"); mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this)); - mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE)); + mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance)); mStandButton->setVisible(FALSE); LLHints::registerHintTarget("stand_btn", mStandButton->getHandle()); @@ -685,8 +685,7 @@ void LLPanelStandStopFlying::onStandButtonClick() LLSelectMgr::getInstance()->deselectAllForStandingUp(); gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - setFocus(FALSE); // EXT-482 - mStandButton->setVisible(FALSE); // force visibility changing to avoid seeing Stand & Move buttons at once. + setFocus(FALSE); } void LLPanelStandStopFlying::onStopFlyingButtonClick() @@ -694,7 +693,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick() gAgent.setFlying(FALSE); setFocus(FALSE); // EXT-482 - mStopFlyingButton->setVisible(FALSE); } /** diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h index c525d9dfdb..4a31f2a814 100644 --- a/indra/newview/llmoveview.h +++ b/indra/newview/llmoveview.h @@ -56,7 +56,7 @@ public: static void setAlwaysRunMode(bool run); void setAlwaysRunModeImpl(bool run); static void setSittingMode(BOOL bSitting); - static void enableInstance(BOOL bEnable); + static void enableInstance(); /*virtual*/ void onOpen(const LLSD& key); static void sUpdateFlyingStatus(); diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 5fc73c67d1..72faa5a9e7 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -735,7 +735,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color, continue; } S32 offset = px + py * image_width; - ((U32*)datap)[offset] = color.mAll; + ((U32*)datap)[offset] = color.asRGBA(); } // top line @@ -748,7 +748,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color, continue; } S32 offset = px + py * image_width; - ((U32*)datap)[offset] = color.mAll; + ((U32*)datap)[offset] = color.asRGBA(); } } else @@ -770,7 +770,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color, continue; } S32 offset = p_x + p_y * image_width; - ((U32*)datap)[offset] = color.mAll; + ((U32*)datap)[offset] = color.asRGBA(); } } } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 2657b84ef3..63ab88da42 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -96,17 +96,21 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) LLUUID from_id = notification->getPayload()["from_id"]; - //Will not play a notification sound for inventory and teleport offer based upon chat preference - bool playSound = (!notification->isDND() - && ((notification->getName() == "UserGiveItem" - && gSavedSettings.getBOOL("PlaySoundInventoryOffer")) - || (notification->getName() == "TeleportOffered" - && gSavedSettings.getBOOL("PlaySoundTeleportOffer")))); - - if(playSound) - { - notification->playSound(); - } + if (!notification->isDND()) + { + //Will not play a notification sound for inventory and teleport offer based upon chat preference + bool playSound = (notification->getName() == "UserGiveItem" + && gSavedSettings.getBOOL("PlaySoundInventoryOffer")) + || ((notification->getName() == "TeleportOffered" + || notification->getName() == "TeleportOffered_MaturityExceeded" + || notification->getName() == "TeleportOffered_MaturityBlocked") + && gSavedSettings.getBOOL("PlaySoundTeleportOffer")); + + if (playSound) + { + notification->playSound(); + } + } LLHandlerUtil::spawnIMSession(name, from_id); LLHandlerUtil::addNotifPanelToIM(notification); diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp new file mode 100644 index 0000000000..de6a36ce2f --- /dev/null +++ b/indra/newview/lloutfitgallery.cpp @@ -0,0 +1,1288 @@ +/** + * @file lloutfitgallery.cpp + * @author Pavlo Kryvych + * @brief Visual gallery of agent's outfits for My Appearance side panel + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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 "lloutfitgallery.h" + +#include <boost/foreach.hpp> + +// llcommon +#include "llcommonutils.h" +#include "llvfile.h" + +#include "llappearancemgr.h" +#include "lleconomy.h" +#include "llerror.h" +#include "llfilepicker.h" +#include "llfloaterperms.h" +#include "llfloaterreg.h" +#include "llfloateroutfitsnapshot.h" +#include "llimagedimensionsinfo.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "lllocalbitmaps.h" +#include "llnotificationsutil.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llwearableitemslist.h" + +static LLPanelInjector<LLOutfitGallery> t_outfit_gallery("outfit_gallery"); + +#define MAX_OUTFIT_PHOTO_WIDTH 256 +#define MAX_OUTFIT_PHOTO_HEIGHT 256 + +LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p) + : LLOutfitListBase(), + mTexturesObserver(NULL), + mOutfitsObserver(NULL), + mScrollPanel(NULL), + mGalleryPanel(NULL), + mGalleryCreated(false), + mRowCount(0), + mItemsAddedCount(0), + mOutfitLinkPending(NULL), + mOutfitRenamePending(NULL), + mRowPanelHeight(p.row_panel_height), + mVerticalGap(p.vertical_gap), + mHorizontalGap(p.horizontal_gap), + mItemWidth(p.item_width), + mItemHeight(p.item_height), + mItemHorizontalGap(p.item_horizontal_gap), + mItemsInRow(p.items_in_row), + mRowPanWidthFactor(p.row_panel_width_factor), + mGalleryWidthFactor(p.gallery_width_factor), + mTextureSelected(NULL) +{ + updateGalleryWidth(); +} + +LLOutfitGallery::Params::Params() + : row_panel_height("row_panel_height", 180), + vertical_gap("vertical_gap", 10), + horizontal_gap("horizontal_gap", 10), + item_width("item_width", 150), + item_height("item_height", 175), + item_horizontal_gap("item_horizontal_gap", 16), + items_in_row("items_in_row", 3), + row_panel_width_factor("row_panel_width_factor", 166), + gallery_width_factor("gallery_width_factor", 163) +{ + addSynonym(row_panel_height, "row_height"); +} + +const LLOutfitGallery::Params& LLOutfitGallery::getDefaultParams() +{ + return LLUICtrlFactory::getDefaultParams<LLOutfitGallery>(); +} + +BOOL LLOutfitGallery::postBuild() +{ + BOOL rv = LLOutfitListBase::postBuild(); + mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel"); + mGalleryPanel = getChild<LLPanel>("gallery_panel"); + mMessageTextBox = getChild<LLTextBox>("no_outfits_txt"); + mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this); + return rv; +} + +void LLOutfitGallery::onOpen(const LLSD& info) +{ + LLOutfitListBase::onOpen(info); + if (!mGalleryCreated) + { + loadPhotos(); + uuid_vec_t cats; + getCurrentCategories(cats); + int n = cats.size(); + buildGalleryPanel(n); + mScrollPanel->addChild(mGalleryPanel); + for (int i = 0; i < n; i++) + { + addToGallery(mOutfitMap[cats[i]]); + } + reArrangeRows(); + mGalleryCreated = true; + } +} + +void LLOutfitGallery::draw() +{ + LLPanel::draw(); + if (mGalleryCreated) + { + updateRowsIfNeeded(); + } +} + +void LLOutfitGallery::updateRowsIfNeeded() +{ + if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) + { + reArrangeRows(1); + } + else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > 3) + { + reArrangeRows(-1); + } +} + +bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2) +{ + if(gSavedSettings.getBOOL("OutfitGallerySortByName") || + ((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + { + std::string name1 = item1->getItemName(); + std::string name2 = item2->getItemName(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + return name1 < name2; + } + else + { + return item2->isDefaultImage(); + } +} + +void LLOutfitGallery::reArrangeRows(S32 row_diff) +{ + + std::vector<LLOutfitGalleryItem*> buf_items = mItems; + for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) + { + removeFromGalleryLast(*it); + } + for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it) + { + buf_items.push_back(*it); + } + mHiddenItems.clear(); + + mItemsInRow+= row_diff; + updateGalleryWidth(); + std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); + + for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) + { + (*it)->setHidden(false); + applyFilter(*it,sFilterSubString); + addToGallery(*it); + } + updateMessageVisibility(); +} + +void LLOutfitGallery::updateGalleryWidth() +{ + mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap; + mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap; +} + +LLPanel* LLOutfitGallery::addLastRow() +{ + mRowCount++; + int row = 0; + int vgap = mVerticalGap * row; + LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap); + mGalleryPanel->addChild(result); + return result; +} + +void LLOutfitGallery::moveRowUp(int row) +{ + moveRow(row, mRowCount - 1 - row + 1); +} + +void LLOutfitGallery::moveRowDown(int row) +{ + moveRow(row, mRowCount - 1 - row - 1); +} + +void LLOutfitGallery::moveRow(int row, int pos) +{ + int vgap = mVerticalGap * pos; + moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap); +} + +void LLOutfitGallery::removeLastRow() +{ + mRowCount--; + mGalleryPanel->removeChild(mLastRowPanel); + mRowPanels.pop_back(); + mLastRowPanel = mRowPanels.back(); +} + +LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap) +{ + LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap); + lpanel->addChild(item); + row_stack->addChild(lpanel); + mItemPanels.push_back(lpanel); + return lpanel; +} + +void LLOutfitGallery::addToGallery(LLOutfitGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.push_back(item); + return; + } + mItemsAddedCount++; + mItemIndexMap[item] = mItemsAddedCount - 1; + int n = mItemsAddedCount; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int n_prev = n - 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + + bool add_row = row_count != row_count_prev; + int pos = 0; + if (add_row) + { + for (int i = 0; i < row_count_prev; i++) + { + moveRowUp(i); + } + mLastRowPanel = addLastRow(); + mRowPanels.push_back(mLastRowPanel); + } + pos = (n - 1) % mItemsInRow; + mItems.push_back(item); + addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos); + reshapeGalleryPanel(row_count); +} + + +void LLOutfitGallery::removeFromGalleryLast(LLOutfitGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.pop_back(); + return; + } + int n_prev = mItemsAddedCount; + int n = mItemsAddedCount - 1; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + mItemsAddedCount--; + + bool remove_row = row_count != row_count_prev; + removeFromLastRow(mItems[mItemsAddedCount]); + mItems.pop_back(); + if (remove_row) + { + for (int i = 0; i < row_count_prev - 1; i++) + { + moveRowDown(i); + } + removeLastRow(); + } + reshapeGalleryPanel(row_count); +} + + +void LLOutfitGallery::removeFromGalleryMiddle(LLOutfitGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end()); + return; + } + int n = mItemIndexMap[item]; + mItemIndexMap.erase(item); + std::vector<LLOutfitGalleryItem*> saved; + for (int i = mItemsAddedCount - 1; i > n; i--) + { + saved.push_back(mItems[i]); + removeFromGalleryLast(mItems[i]); + } + removeFromGalleryLast(mItems[n]); + int saved_count = saved.size(); + for (int i = 0; i < saved_count; i++) + { + addToGallery(saved.back()); + saved.pop_back(); + } +} + +void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item) +{ + mItemPanels.back()->removeChild(item); + mLastRowPanel->removeChild(mItemPanels.back()); + mItemPanels.pop_back(); +} + +LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name) +{ + LLOutfitGalleryItem::Params giparams; + LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams); + gitem->reshape(mItemWidth, mItemHeight); + gitem->setVisible(true); + gitem->setFollowsLeft(); + gitem->setFollowsTop(); + gitem->setOutfitName(name); + return gitem; +} + +void LLOutfitGallery::buildGalleryPanel(int row_count) +{ + LLPanel::Params params; + mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); + reshapeGalleryPanel(row_count); +} + +void LLOutfitGallery::reshapeGalleryPanel(int row_count) +{ + int bottom = 0; + int left = 0; + int height = row_count * (mRowPanelHeight + mVerticalGap); + LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom); + mGalleryPanel->setRect(rect); + mGalleryPanel->reshape(mGalleryWidth, height); + mGalleryPanel->setVisible(true); + mGalleryPanel->setFollowsLeft(); + mGalleryPanel->setFollowsTop(); +} + +LLPanel* LLOutfitGallery::buildItemPanel(int left) +{ + LLPanel::Params lpparams; + int top = 0; + LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams); + LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); + lpanel->setRect(rect); + lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); + lpanel->setVisible(true); + lpanel->setFollowsLeft(); + lpanel->setFollowsTop(); + return lpanel; +} + +LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom) +{ + LLPanel::Params sparams; + LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams); + moveRowPanel(stack, left, bottom); + return stack; +} + +void LLOutfitGallery::moveRowPanel(LLPanel* stack, int left, int bottom) +{ + LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom); + stack->setRect(rect); + stack->reshape(mRowPanelWidth, mRowPanelHeight); + stack->setVisible(true); + stack->setFollowsLeft(); + stack->setFollowsTop(); +} + +LLOutfitGallery::~LLOutfitGallery() +{ + delete mOutfitGalleryMenu; + + if (gInventory.containsObserver(mTexturesObserver)) + { + gInventory.removeObserver(mTexturesObserver); + } + delete mTexturesObserver; + + if (gInventory.containsObserver(mOutfitsObserver)) + { + gInventory.removeObserver(mOutfitsObserver); + } + delete mOutfitsObserver; +} + +void LLOutfitGallery::setFilterSubString(const std::string& string) +{ + sFilterSubString = string; + reArrangeRows(); +} + +void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) +{ + if (mOutfitMap[base_id]) + { + mOutfitMap[base_id]->setOutfitWorn(true); + } + if (mOutfitMap[prev_id]) + { + mOutfitMap[prev_id]->setOutfitWorn(false); + } +} + +void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring) +{ + if (!item) return; + + std::string outfit_name = item->getItemName(); + LLStringUtil::toUpper(outfit_name); + + std::string cur_filter = filter_substring; + LLStringUtil::toUpper(cur_filter); + + bool hidden = (std::string::npos == outfit_name.find(cur_filter)); + item->setHidden(hidden); +} + +void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) +{ +} + +void LLOutfitGallery::getCurrentCategories(uuid_vec_t& vcur) +{ + for (outfit_map_t::const_iterator iter = mOutfitMap.begin(); + iter != mOutfitMap.end(); + iter++) + { + if ((*iter).second != NULL) + { + vcur.push_back((*iter).first); + } + } +} + +void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (!cat) return; + + std::string name = cat->getName(); + LLOutfitGalleryItem* item = buildGalleryItem(name); + mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item)); + item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this, + _1, _2, _3, cat_id)); + LLWearableItemsList* list = NULL; + item->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id)); + if (mGalleryCreated) + { + addToGallery(item); + } + + LLViewerInventoryCategory* outfit_category = gInventory.getCategory(cat_id); + if (!outfit_category) + return; + + if (mOutfitsObserver == NULL) + { + mOutfitsObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mOutfitsObserver); + } + + // Start observing changes in "My Outfits" category. + mOutfitsObserver->addCategory(cat_id, + boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id)); + + outfit_category->fetch(); + refreshOutfit(cat_id); +} + +void LLOutfitGallery::updateRemovedCategory(LLUUID cat_id) +{ + outfit_map_t::iterator outfits_iter = mOutfitMap.find(cat_id); + if (outfits_iter != mOutfitMap.end()) + { + // 0. Remove category from observer. + mOutfitsObserver->removeCategory(cat_id); + + //const LLUUID& outfit_id = outfits_iter->first; + LLOutfitGalleryItem* item = outfits_iter->second; + + // An outfit is removed from the list. Do the following: + // 2. Remove the outfit from selection. + deselectOutfit(cat_id); + + // 3. Remove category UUID to accordion tab mapping. + mOutfitMap.erase(outfits_iter); + + // 4. Remove outfit from gallery. + removeFromGalleryMiddle(item); + + // kill removed item + if (item != NULL) + { + item->die(); + } + } + +} + +void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) +{ + outfit_map_t::iterator outfit_iter = mOutfitMap.find(cat->getUUID()); + if (outfit_iter != mOutfitMap.end()) + { + // Update name of outfit in gallery + LLOutfitGalleryItem* item = outfit_iter->second; + if (item) + { + item->setOutfitName(name); + } + } +} + +void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ + if (mOutfitMenu && cat_id.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(cat_id); + mOutfitGalleryMenu->show(ctrl, selected_uuids, x, y); + } +} + +void LLOutfitGallery::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +{ + if (mSelectedOutfitUUID == category_id) + return; + if (mOutfitMap[mSelectedOutfitUUID]) + { + mOutfitMap[mSelectedOutfitUUID]->setSelected(FALSE); + } + if (mOutfitMap[category_id]) + { + mOutfitMap[category_id]->setSelected(TRUE); + } +} + +void LLOutfitGallery::wearSelectedOutfit() +{ + LLAppearanceMgr::instance().replaceCurrentOutfit(getSelectedOutfitUUID()); +} + +bool LLOutfitGallery::hasItemSelected() +{ + return false; +} + +bool LLOutfitGallery::canWearSelected() +{ + return false; +} + +bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id) +{ + if (mOutfitMap[outfit_cat_id]) + { + return mOutfitMap[outfit_cat_id]->isDefaultImage(); + } + return false; +} + +void LLOutfitGallery::updateMessageVisibility() +{ + if(mItems.empty()) + { + mMessageTextBox->setVisible(TRUE); + mScrollPanel->setVisible(FALSE); + std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg"); + mMessageTextBox->setValue(message); + } + else + { + mScrollPanel->setVisible(TRUE); + mMessageTextBox->setVisible(FALSE); + } +} + +LLOutfitListGearMenuBase* LLOutfitGallery::createGearMenu() +{ + return new LLOutfitGalleryGearMenu(this); +} + +static LLDefaultChildRegistry::Register<LLOutfitGalleryItem> r("outfit_gallery_item"); + +LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p) + : LLPanel(p), + mTexturep(NULL), + mSelected(false), + mWorn(false), + mDefaultImage(true), + mOutfitName("") +{ + buildFromFile("panel_outfit_gallery_item.xml"); +} + +LLOutfitGalleryItem::~LLOutfitGalleryItem() +{ + +} + +BOOL LLOutfitGalleryItem::postBuild() +{ + setDefaultImage(); + + mOutfitNameText = getChild<LLTextBox>("outfit_name"); + mOutfitWornText = getChild<LLTextBox>("outfit_worn_text"); + mFotoBgPanel = getChild<LLPanel>("foto_bg_panel"); + mTextBgPanel = getChild<LLPanel>("text_bg_panel"); + setOutfitWorn(false); + mHidden = false; + return TRUE; +} + +void LLOutfitGalleryItem::draw() +{ + LLPanel::draw(); + + // Draw border + LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "OutfitGalleryItemSelected" : "OutfitGalleryItemUnselected", LLColor4::white); + LLRect border = getChildView("preview_outfit")->getRect(); + border.mRight = border.mRight + 1; + gl_rect_2d(border, border_color.get(), FALSE); + + // If the floater is focused, don't apply its alpha to the texture (STORM-677). + const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + if (mTexturep) + { + LLRect interior = border; + interior.stretch(-1); + + gl_draw_scaled_image(interior.mLeft - 1, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha); + + // Pump the priority + mTexturep->addTextureStats((F32)(interior.getWidth() * interior.getHeight())); + } + +} + +void LLOutfitGalleryItem::setOutfitName(std::string name) +{ + mOutfitNameText->setText(name); + mOutfitNameText->setToolTip(name); + mOutfitName = name; +} + +void LLOutfitGalleryItem::setOutfitWorn(bool value) +{ + mWorn = value; + LLStringUtil::format_map_t worn_string_args; + std::string worn_string = getString("worn_string", worn_string_args); + LLUIColor text_color = LLUIColorTable::instance().getColor(mSelected ? "White" : (mWorn ? "OutfitGalleryItemWorn" : "White"), LLColor4::white); + mOutfitWornText->setReadOnlyColor(text_color.get()); + mOutfitNameText->setReadOnlyColor(text_color.get()); + mOutfitWornText->setValue(value ? worn_string : ""); +} + +void LLOutfitGalleryItem::setSelected(bool value) +{ + mSelected = value; + mTextBgPanel->setBackgroundVisible(value); + setOutfitWorn(mWorn); +} + +BOOL LLOutfitGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleMouseDown(x, y, mask); +} + +BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleRightMouseDown(x, y, mask); +} + +void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id) +{ + mImageAssetId = image_asset_id; + mTexturep = LLViewerTextureManager::getFetchedTexture(image_asset_id, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + getChildView("preview_outfit")->setVisible(FALSE); + mDefaultImage = false; +} + +LLUUID LLOutfitGalleryItem::getImageAssetId() +{ + return mImageAssetId; +} + +void LLOutfitGalleryItem::setDefaultImage() +{ + mTexturep = NULL; + mImageAssetId.setNull(); + getChildView("preview_outfit")->setVisible(TRUE); + mDefaultImage = true; +} + +LLContextMenu* LLOutfitGalleryContextMenu::createMenu() +{ + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + LLUUID selected_id = mUUIDs.front(); + + registrar.add("Outfit.WearReplace", + boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.WearAdd", + boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.TakeOff", + boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.Edit", boost::bind(editOutfit)); + registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); + registrar.add("Outfit.Delete", boost::bind(&LLOutfitGalleryContextMenu::onRemoveOutfit, this, selected_id)); + registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2)); + registrar.add("Outfit.UploadPhoto", boost::bind(&LLOutfitGalleryContextMenu::onUploadPhoto, this, selected_id)); + registrar.add("Outfit.SelectPhoto", boost::bind(&LLOutfitGalleryContextMenu::onSelectPhoto, this, selected_id)); + registrar.add("Outfit.TakeSnapshot", boost::bind(&LLOutfitGalleryContextMenu::onTakeSnapshot, this, selected_id)); + registrar.add("Outfit.RemovePhoto", boost::bind(&LLOutfitGalleryContextMenu::onRemovePhoto, this, selected_id)); + enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2)); + enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2)); + + return createFromFile("menu_gallery_outfit_tab.xml"); +} + +void LLOutfitGalleryContextMenu::onUploadPhoto(const LLUUID& outfit_cat_id) +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery && outfit_cat_id.notNull()) + { + gallery->uploadPhoto(outfit_cat_id); + } +} + +void LLOutfitGalleryContextMenu::onSelectPhoto(const LLUUID& outfit_cat_id) +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery && outfit_cat_id.notNull()) + { + gallery->onSelectPhoto(outfit_cat_id); + } +} + +void LLOutfitGalleryContextMenu::onRemovePhoto(const LLUUID& outfit_cat_id) +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery && outfit_cat_id.notNull()) + { + gallery->checkRemovePhoto(outfit_cat_id); + gallery->refreshOutfit(outfit_cat_id); + } +} + +void LLOutfitGalleryContextMenu::onTakeSnapshot(const LLUUID& outfit_cat_id) +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery && outfit_cat_id.notNull()) + { + gallery->onTakeSnapshot(outfit_cat_id); + } +} + +void LLOutfitGalleryContextMenu::onRemoveOutfit(const LLUUID& outfit_cat_id) +{ + LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation, this, _1, _2, outfit_cat_id)); +} + +void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + if (outfit_cat_id.notNull()) + { + gInventory.removeCategory(outfit_cat_id); + } +} + +void LLOutfitGalleryContextMenu::onCreate(const LLSD& data) +{ + LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); + if (type == LLWearableType::WT_NONE) + { + LL_WARNS() << "Invalid wearable type" << LL_ENDL; + return; + } + + LLAgentWearables::createWearable(type, true); +} + +bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param) +{ + return LLOutfitContextMenu::onEnable(param); +} + +bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param) +{ + if ("remove_photo" == param) + { + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + LLUUID selected_id = mUUIDs.front(); + if (gallery && selected_id.notNull()) + { + return !gallery->hasDefaultImage(selected_id); + } + } + return LLOutfitContextMenu::onVisible(param); +} + +LLOutfitGalleryGearMenu::LLOutfitGalleryGearMenu(LLOutfitListBase* olist) + : LLOutfitListGearMenuBase(olist) +{ +} + +void LLOutfitGalleryGearMenu::onUpdateItemsVisibility() +{ + if (!mMenu) return; + bool have_selection = getSelectedOutfitID().notNull(); + mMenu->setItemVisible("expand", FALSE); + mMenu->setItemVisible("collapse", FALSE); + mMenu->setItemVisible("upload_photo", have_selection); + mMenu->setItemVisible("select_photo", have_selection); + mMenu->setItemVisible("take_snapshot", have_selection); + mMenu->setItemVisible("remove_photo", !hasDefaultImage()); + mMenu->setItemVisible("sepatator3", TRUE); + mMenu->setItemVisible("sort_folders_by_name", TRUE); + LLOutfitListGearMenuBase::onUpdateItemsVisibility(); +} + +void LLOutfitGalleryGearMenu::onUploadFoto() +{ + LLUUID selected_outfit_id = getSelectedOutfitID(); + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery && selected_outfit_id.notNull()) + { + gallery->uploadPhoto(selected_outfit_id); + } +} + +void LLOutfitGalleryGearMenu::onSelectPhoto() +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + LLUUID selected_outfit_id = getSelectedOutfitID(); + if (gallery && !selected_outfit_id.isNull()) + { + gallery->onSelectPhoto(selected_outfit_id); + } +} + +void LLOutfitGalleryGearMenu::onRemovePhoto() +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + LLUUID selected_outfit_id = getSelectedOutfitID(); + if (gallery && !selected_outfit_id.isNull()) + { + gallery->checkRemovePhoto(selected_outfit_id); + gallery->refreshOutfit(selected_outfit_id); + } +} + +void LLOutfitGalleryGearMenu::onTakeSnapshot() +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + LLUUID selected_outfit_id = getSelectedOutfitID(); + if (gallery && !selected_outfit_id.isNull()) + { + gallery->onTakeSnapshot(selected_outfit_id); + } +} + +void LLOutfitGalleryGearMenu::onChangeSortOrder() +{ + bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName"); + gSavedSettings.setBOOL("OutfitGallerySortByName", sort_by_name); + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + if (gallery) + { + gallery->reArrangeRows(); + } +} + +bool LLOutfitGalleryGearMenu::hasDefaultImage() +{ + LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList); + LLUUID selected_outfit_id = getSelectedOutfitID(); + if (gallery && selected_outfit_id.notNull()) + { + return gallery->hasDefaultImage(selected_outfit_id); + } + return true; +} + +void LLOutfitGallery::onTextureSelectionChanged(LLInventoryItem* itemp) +{ +} + +void LLOutfitGallery::loadPhotos() +{ + //Iterate over inventory + LLUUID textures = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); + LLViewerInventoryCategory* textures_category = gInventory.getCategory(textures); + if (!textures_category) + return; + if (mTexturesObserver == NULL) + { + mTexturesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mTexturesObserver); + } + + // Start observing changes in "Textures" category. + mTexturesObserver->addCategory(textures, + boost::bind(&LLOutfitGallery::refreshTextures, this, textures)); + + textures_category->fetch(); +} + +void LLOutfitGallery::refreshOutfit(const LLUUID& category_id) +{ + LLViewerInventoryCategory* category = gInventory.getCategory(category_id); + { + bool photo_loaded = false; + LLInventoryModel::cat_array_t sub_cat_array; + LLInventoryModel::item_array_t outfit_item_array; + // Collect all sub-categories of a given category. + gInventory.collectDescendents( + category->getUUID(), + sub_cat_array, + outfit_item_array, + LLInventoryModel::EXCLUDE_TRASH); + BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array) + { + LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem(); + if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) + { + LLUUID asset_id = linked_item->getAssetUUID(); + mOutfitMap[category_id]->setImageAssetId(asset_id); + photo_loaded = true; + std::string linked_item_name = linked_item->getName(); + if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == linked_item_name) + { + LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending); + LLStringUtil::format_map_t photo_string_args; + photo_string_args["OUTFIT_NAME"] = outfit_cat->getName(); + std::string new_name = getString("outfit_photo_string", photo_string_args); + LLSD updates; + updates["name"] = new_name; + update_inventory_item(linked_item->getUUID(), updates, NULL); + mOutfitRenamePending.setNull(); + LLFloater* inv_floater = LLFloaterReg::getInstance("inventory"); + if (inv_floater) + { + inv_floater->closeFloater(); + } + LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance"); + if (appearance_floater) + { + appearance_floater->setFocus(TRUE); + } + } + break; + } + if (!photo_loaded) + { + mOutfitMap[category_id]->setDefaultImage(); + } + } + } + + if (mGalleryCreated && !LLApp::isQuitting()) + { + reArrangeRows(); + } +} + +void LLOutfitGallery::refreshTextures(const LLUUID& category_id) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + // Collect all sub-categories of a given category. + LLIsType is_texture(LLAssetType::AT_TEXTURE); + gInventory.collectDescendentsIf( + category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_texture); + + //Find texture which contain pending outfit ID string in name + LLViewerInventoryItem* photo_upload_item = NULL; + BOOST_FOREACH(LLViewerInventoryItem* item, item_array) + { + std::string name = item->getName(); + if (!mOutfitLinkPending.isNull() && name == mOutfitLinkPending.asString()) + { + photo_upload_item = item; + break; + } + } + + if (photo_upload_item != NULL) + { + LLUUID photo_item_id = photo_upload_item->getUUID(); + LLInventoryObject* upload_object = gInventory.getObject(photo_item_id); + if (!upload_object) + { + LL_WARNS() << "LLOutfitGallery::refreshTextures added_object is null!" << LL_ENDL; + } + else + { + linkPhotoToOutfit(photo_item_id, mOutfitLinkPending); + mOutfitRenamePending = mOutfitLinkPending; + mOutfitLinkPending.setNull(); + } + } +} + +void LLOutfitGallery::uploadPhoto(LLUUID outfit_id) +{ + outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); + if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) + { + return; + } + + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) + { + std::string filename = picker.getFirstFile(); + LLLocalBitmap* unit = new LLLocalBitmap(filename); + if (unit->getValid()) + { + std::string exten = gDirUtilp->getExtension(filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); + + LLImageDimensionsInfo image_info; + std::string image_load_error; + if (!image_info.load(filename, codec)) + { + image_load_error = image_info.getLastError(); + } + + S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; + S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; + + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); + + image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); + } + + if (!image_load_error.empty()) + { + LLSD subst; + subst["REASON"] = image_load_error; + LLNotificationsUtil::add("OutfitPhotoLoadError", subst); + return; + } + + S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). + void *nruserdata = NULL; + nruserdata = (void *)&outfit_id; + + LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); + if (!outfit_cat) return; + + checkRemovePhoto(outfit_id); + std::string upload_pending_name = outfit_id.asString(); + std::string upload_pending_desc = ""; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + LLUUID photo_id = upload_new_resource(filename, // file + upload_pending_name, + upload_pending_desc, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), + upload_pending_name, callback, expected_upload_cost, nruserdata); + mOutfitLinkPending = outfit_id; + } + } +} + +void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id) +{ + LLPointer<LLInventoryCallback> cb = new LLUpdateGalleryOnPhotoLinked(); + link_inventory_object(outfit_id, photo_id, cb); +} + +bool LLOutfitGallery::checkRemovePhoto(LLUUID outfit_id) +{ + LLAppearanceMgr::instance().removeOutfitPhoto(outfit_id); + return true; +} + +void LLUpdateGalleryOnPhotoLinked::fire(const LLUUID& inv_item_id) +{ +} + +LLUUID LLOutfitGallery::getPhotoAssetId(const LLUUID& outfit_id) +{ + outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); + if (outfit_it != mOutfitMap.end()) + { + return outfit_it->second->getImageAssetId(); + } + return LLUUID(); +} + +LLUUID LLOutfitGallery::getDefaultPhoto() +{ + return LLUUID(); +} + +void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id) +{ + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + + if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT) + { + LLUUID image_item_id; + if (id.notNull()) + { + image_item_id = id; + } + else + { + image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE); + if (image_item_id.isNull()) + { + LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL; + return; + } + } + + std::string image_load_error; + S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; + S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; + if (mTextureSelected.isNull() || + mTextureSelected->getFullWidth() == 0 || + mTextureSelected->getFullHeight() == 0) + { + image_load_error = LLTrans::getString("outfit_photo_verify_dimensions_error"); + LL_WARNS() << "Cannot verify selected texture dimensions" << LL_ENDL; + return; + } + S32 width = mTextureSelected->getFullWidth(); + S32 height = mTextureSelected->getFullHeight(); + if ((width > max_width) || (height > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); + + image_load_error = LLTrans::getString("outfit_photo_select_dimensions_error", args); + } + + if (!image_load_error.empty()) + { + LLSD subst; + subst["REASON"] = image_load_error; + LLNotificationsUtil::add("OutfitPhotoLoadError", subst); + return; + } + + checkRemovePhoto(getSelectedOutfitUUID()); + linkPhotoToOutfit(image_item_id, getSelectedOutfitUUID()); + } +} + +void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id) +{ + if (selected_outfit_id.notNull()) + { + + // show hourglass cursor when loading inventory window + // because inventory construction is slooow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloater* floaterp = mFloaterHandle.get(); + + // Show the dialog + if (floaterp) + { + floaterp->openFloater(); + } + else + { + floaterp = new LLFloaterTexturePicker( + this, + getPhotoAssetId(selected_outfit_id), + getPhotoAssetId(selected_outfit_id), + getPhotoAssetId(selected_outfit_id), + FALSE, + TRUE, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + PERM_NONE, + FALSE, + NULL); + + mFloaterHandle = floaterp->getHandle(); + mTextureSelected = NULL; + + LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); + if (texture_floaterp) + { + texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1)); + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2)); + texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1)); + texture_floaterp->setLocalTextureEnabled(FALSE); + } + + floaterp->openFloater(); + } + floaterp->setFocus(TRUE); + } +} + +void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id) +{ + LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot"); + LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance(); + if (snapshot_floater) + { + snapshot_floater->setOutfitID(selected_outfit_id); + snapshot_floater->getInstance()->setGallery(this); + } +} + +void LLOutfitGallery::onBeforeOutfitSnapshotSave() +{ + LLUUID selected_outfit_id = getSelectedOutfitUUID(); + if (!selected_outfit_id.isNull()) + { + checkRemovePhoto(selected_outfit_id); + } +} + +void LLOutfitGallery::onAfterOutfitSnapshotSave() +{ + LLUUID selected_outfit_id = getSelectedOutfitUUID(); + if (!selected_outfit_id.isNull()) + { + mOutfitLinkPending = selected_outfit_id; + } +} + +void LLOutfitGallery::onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture) +{ + mTextureSelected = texture; +} diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h new file mode 100644 index 0000000000..6b13f264a4 --- /dev/null +++ b/indra/newview/lloutfitgallery.h @@ -0,0 +1,284 @@ +/** + * @file lloutfitgallery.h + * @author Pavlo Kryvych + * @brief Visual gallery of agent's outfits for My Appearance side panel + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2015, 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_LLOUTFITGALLERYCTRL_H +#define LL_LLOUTFITGALLERYCTRL_H + +#include "llextendedstatus.h" +#include "lliconctrl.h" +#include "lllayoutstack.h" +#include "lloutfitslist.h" +#include "llpanelappearancetab.h" +#include "lltexturectrl.h" +#include "llviewertexture.h" + +#include <vector> + +class LLVFS; +class LLOutfitGallery; +class LLOutfitGalleryItem; +class LLOutfitListGearMenuBase; +class LLOutfitGalleryGearMenu; +class LLOutfitGalleryContextMenu; + +class LLUpdateGalleryOnPhotoLinked : public LLInventoryCallback +{ +public: + LLUpdateGalleryOnPhotoLinked(){} + virtual ~LLUpdateGalleryOnPhotoLinked(){} + /* virtual */ void fire(const LLUUID& inv_item_id); +private: +}; + +class LLOutfitGallery : public LLOutfitListBase +{ +public: + friend class LLOutfitGalleryGearMenu; + friend class LLOutfitGalleryContextMenu; + friend class LLUpdateGalleryOnPhotoLinked; + + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<S32> row_panel_height; + Optional<S32> row_panel_width_factor; + Optional<S32> gallery_width_factor; + Optional<S32> vertical_gap; + Optional<S32> horizontal_gap; + Optional<S32> item_width; + Optional<S32> item_height; + Optional<S32> item_horizontal_gap; + Optional<S32> items_in_row; + + Params(); + }; + + static const LLOutfitGallery::Params& getDefaultParams(); + + LLOutfitGallery(const LLOutfitGallery::Params& params = getDefaultParams()); + virtual ~LLOutfitGallery(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& info); + /*virtual*/ void draw(); + + void onSelectPhoto(LLUUID selected_outfit_id); + void onTakeSnapshot(LLUUID selected_outfit_id); + + void wearSelectedOutfit(); + + + /*virtual*/ void setFilterSubString(const std::string& string); + + /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur); + /*virtual*/ void updateAddedCategory(LLUUID cat_id); + /*virtual*/ void updateRemovedCategory(LLUUID cat_id); + /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + + /*virtual*/ bool hasItemSelected(); + /*virtual*/ bool canWearSelected(); + + /*virtual*/ bool getHasExpandableFolders() { return FALSE; } + + void updateMessageVisibility(); + bool hasDefaultImage(const LLUUID& outfit_cat_id); + + void refreshTextures(const LLUUID& category_id); + void refreshOutfit(const LLUUID& category_id); + + void onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id); + void onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture); + void onBeforeOutfitSnapshotSave(); + void onAfterOutfitSnapshotSave(); +protected: + /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id); + /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid); + /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); + /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + + /*virtual*/ void onCollapseAllFolders() {} + /*virtual*/ void onExpandAllFolders() {} + /*virtual*/ LLOutfitListGearMenuBase* createGearMenu(); + + void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring); + +private: + void loadPhotos(); + void uploadPhoto(LLUUID outfit_id); + LLUUID getPhotoAssetId(const LLUUID& outfit_id); + LLUUID getDefaultPhoto(); + void linkPhotoToOutfit(LLUUID outfit_id, LLUUID photo_id); + bool checkRemovePhoto(LLUUID outfit_id); + void addToGallery(LLOutfitGalleryItem* item); + void removeFromGalleryLast(LLOutfitGalleryItem* item); + void removeFromGalleryMiddle(LLOutfitGalleryItem* item); + LLPanel* addLastRow(); + void removeLastRow(); + void moveRowUp(int row); + void moveRowDown(int row); + void moveRow(int row, int pos); + LLPanel* addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap); + void removeFromLastRow(LLOutfitGalleryItem* item); + void reArrangeRows(S32 row_diff = 0); + void updateRowsIfNeeded(); + void updateGalleryWidth(); + + LLOutfitGalleryItem* buildGalleryItem(std::string name); + + void onTextureSelectionChanged(LLInventoryItem* itemp); + + void buildGalleryPanel(int row_count); + void reshapeGalleryPanel(int row_count); + LLPanel* buildItemPanel(int left); + LLPanel* buildRowPanel(int left, int bottom); + void moveRowPanel(LLPanel* stack, int left, int bottom); + std::vector<LLPanel*> mRowPanels; + std::vector<LLPanel*> mItemPanels; + std::vector<LLOutfitGalleryItem*> mItems; + std::vector<LLOutfitGalleryItem*> mHiddenItems; + LLScrollContainer* mScrollPanel; + LLPanel* mGalleryPanel; + LLPanel* mLastRowPanel; + LLUUID mOutfitLinkPending; + LLUUID mOutfitRenamePending; + LLTextBox* mMessageTextBox; + bool mGalleryCreated; + int mRowCount; + int mItemsAddedCount; + LLPointer<LLViewerTexture> mTextureSelected; + /* Params */ + int mRowPanelHeight; + int mVerticalGap; + int mHorizontalGap; + int mItemWidth; + int mItemHeight; + int mItemHorizontalGap; + int mItemsInRow; + int mRowPanelWidth; + int mGalleryWidth; + int mRowPanWidthFactor; + int mGalleryWidthFactor; + + LLListContextMenu* mOutfitGalleryMenu; + + LLHandle<LLFloater> mFloaterHandle; + + typedef std::map<LLUUID, LLOutfitGalleryItem*> outfit_map_t; + typedef outfit_map_t::value_type outfit_map_value_t; + outfit_map_t mOutfitMap; + typedef std::map<LLOutfitGalleryItem*, int> item_num_map_t; + typedef item_num_map_t::value_type item_numb_map_value_t; + item_num_map_t mItemIndexMap; + + + LLInventoryCategoriesObserver* mTexturesObserver; + LLInventoryCategoriesObserver* mOutfitsObserver; +}; +class LLOutfitGalleryContextMenu : public LLOutfitContextMenu +{ +public: + + friend class LLOutfitGallery; + LLOutfitGalleryContextMenu(LLOutfitListBase* outfit_list) + : LLOutfitContextMenu(outfit_list), + mOutfitList(outfit_list){} +protected: + /* virtual */ LLContextMenu* createMenu(); + bool onEnable(LLSD::String param); + bool onVisible(LLSD::String param); + void onUploadPhoto(const LLUUID& outfit_cat_id); + void onSelectPhoto(const LLUUID& outfit_cat_id); + void onRemovePhoto(const LLUUID& outfit_cat_id); + void onTakeSnapshot(const LLUUID& outfit_cat_id); + void onCreate(const LLSD& data); + void onRemoveOutfit(const LLUUID& outfit_cat_id); + void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id); +private: + LLOutfitListBase* mOutfitList; +}; + + +class LLOutfitGalleryGearMenu : public LLOutfitListGearMenuBase +{ +public: + friend class LLOutfitGallery; + LLOutfitGalleryGearMenu(LLOutfitListBase* olist); + +protected: + /*virtual*/ void onUpdateItemsVisibility(); +private: + /*virtual*/ void onUploadFoto(); + /*virtual*/ void onSelectPhoto(); + /*virtual*/ void onTakeSnapshot(); + /*virtual*/ void onRemovePhoto(); + /*virtual*/ void onChangeSortOrder(); + + bool hasDefaultImage(); +}; + +class LLOutfitGalleryItem : public LLPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + {}; + + LLOutfitGalleryItem(const Params& p); + virtual ~LLOutfitGalleryItem(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + void setDefaultImage(); + void setImageAssetId(LLUUID asset_id); + LLUUID getImageAssetId(); + void setOutfitName(std::string name); + void setOutfitWorn(bool value); + void setSelected(bool value); + + std::string getItemName() {return mOutfitName;} + bool isDefaultImage() {return mDefaultImage;} + + bool isHidden() {return mHidden;} + void setHidden(bool hidden) {mHidden = hidden;} + +private: + LLPointer<LLViewerFetchedTexture> mTexturep; + LLUUID mImageAssetId; + LLTextBox* mOutfitNameText; + LLTextBox* mOutfitWornText; + LLPanel* mTextBgPanel; + LLPanel* mFotoBgPanel; + bool mSelected; + bool mWorn; + bool mDefaultImage; + bool mHidden; + std::string mOutfitName; +}; + +#endif // LL_LLOUTFITGALLERYCTRL_H diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 883221382c..87c3c5042b 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -38,7 +38,6 @@ #include "llfloatersidepanelcontainer.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" -#include "lllistcontextmenu.h" #include "llmenubutton.h" #include "llnotificationsutil.h" #include "lloutfitobserver.h" @@ -98,276 +97,18 @@ const outfit_accordion_tab_params& get_accordion_tab_params() } -////////////////////////////////////////////////////////////////////////// - -class LLOutfitListGearMenu -{ -public: - LLOutfitListGearMenu(LLOutfitsList* olist) - : mOutfitList(olist), - mMenu(NULL) - { - llassert_always(mOutfitList); - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this)); - registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this)); - registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this)); - registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); - registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2)); - registrar.add("Gear.Collapse", boost::bind(&LLOutfitsList::collapse_all_folders, mOutfitList)); - registrar.add("Gear.Expand", boost::bind(&LLOutfitsList::expand_all_folders, mOutfitList)); - - registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this)); - - enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2)); - enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2)); - - mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( - "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - llassert(mMenu); - } - - void updateItemsVisibility() - { - if (!mMenu) return; - - bool have_selection = getSelectedOutfitID().notNull(); - mMenu->setItemVisible("sepatator1", have_selection); - mMenu->setItemVisible("sepatator2", have_selection); - mMenu->arrangeAndClear(); // update menu height - } - - LLToggleableMenu* getMenu() { return mMenu; } - -private: - const LLUUID& getSelectedOutfitID() - { - return mOutfitList->getSelectedOutfitUUID(); - } - - LLViewerInventoryCategory* getSelectedOutfit() - { - const LLUUID& selected_outfit_id = getSelectedOutfitID(); - if (selected_outfit_id.isNull()) - { - return NULL; - } - - LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id); - return cat; - } - - void onWear() - { - LLViewerInventoryCategory* selected_outfit = getSelectedOutfit(); - if (selected_outfit) - { - LLAppearanceMgr::instance().wearInventoryCategory( - selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE); - } - } - - void onAdd() - { - const LLUUID& selected_id = getSelectedOutfitID(); - - if (selected_id.notNull()) - { - LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id); - } - } - - void onTakeOff() - { - // Take off selected outfit. - const LLUUID& selected_outfit_id = getSelectedOutfitID(); - if (selected_outfit_id.notNull()) - { - LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id); - } - } - - void onRename() - { - const LLUUID& selected_outfit_id = getSelectedOutfitID(); - if (selected_outfit_id.notNull()) - { - LLAppearanceMgr::instance().renameOutfit(selected_outfit_id); - } - } - - void onCreate(const LLSD& data) - { - LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); - if (type == LLWearableType::WT_NONE) - { - LL_WARNS() << "Invalid wearable type" << LL_ENDL; - return; - } - - LLAgentWearables::createWearable(type, true); - } - - bool onEnable(LLSD::String param) - { - // Handle the "Wear - Replace Current Outfit" menu option specially - // because LLOutfitList::isActionEnabled() checks whether it's allowed - // to wear selected outfit OR selected items, while we're only - // interested in the outfit (STORM-183). - if ("wear" == param) - { - return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID()); - } - - return mOutfitList->isActionEnabled(param); - } - - bool onVisible(LLSD::String param) - { - const LLUUID& selected_outfit_id = getSelectedOutfitID(); - if (selected_outfit_id.isNull()) // no selection or invalid outfit selected - { - return false; - } - - // *TODO This condition leads to menu item behavior inconsistent with - // "Wear" button behavior and should be modified or removed. - bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; - - if ("wear" == param) - { - return !is_worn; - } - - return true; - } - - LLOutfitsList* mOutfitList; - LLToggleableMenu* mMenu; -}; - -////////////////////////////////////////////////////////////////////////// - -class LLOutfitContextMenu : public LLListContextMenu -{ -public: - - LLOutfitContextMenu(LLOutfitsList* outfit_list) - : LLListContextMenu(), - mOutfitList(outfit_list) - {} -protected: - /* virtual */ LLContextMenu* createMenu() - { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - LLUUID selected_id = mUUIDs.front(); - - registrar.add("Outfit.WearReplace", - boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); - registrar.add("Outfit.WearAdd", - boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); - registrar.add("Outfit.TakeOff", - boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); - registrar.add("Outfit.Edit", boost::bind(editOutfit)); - registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); - registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); - - enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2)); - enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2)); - - return createFromFile("menu_outfit_tab.xml"); - } - - bool onEnable(LLSD::String param) - { - LLUUID outfit_cat_id = mUUIDs.back(); - - if ("rename" == param) - { - return get_is_category_renameable(&gInventory, outfit_cat_id); - } - else if ("wear_replace" == param) - { - return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); - } - else if ("wear_add" == param) - { - return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); - } - else if ("take_off" == param) - { - return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id); - } - - return true; - } - - bool onVisible(LLSD::String param) - { - LLUUID outfit_cat_id = mUUIDs.back(); - bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; - - if ("edit" == param) - { - return is_worn; - } - else if ("wear_replace" == param) - { - return !is_worn; - } - else if ("delete" == param) - { - return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); - } - - return true; - } - - static void editOutfit() - { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); - } - - static void renameOutfit(const LLUUID& outfit_cat_id) - { - LLAppearanceMgr::instance().renameOutfit(outfit_cat_id); - } - -private: - LLOutfitsList* mOutfitList; -}; - -////////////////////////////////////////////////////////////////////////// - static LLPanelInjector<LLOutfitsList> t_outfits_list("outfits_list"); LLOutfitsList::LLOutfitsList() - : LLPanelAppearanceTab() - , mAccordion(NULL) + : LLOutfitListBase() + , mAccordion(NULL) , mListCommands(NULL) - , mIsInitialized(false) , mItemSelected(false) { - mCategoriesObserver = new LLInventoryCategoriesObserver(); - - mGearMenu = new LLOutfitListGearMenu(this); - mOutfitMenu = new LLOutfitContextMenu(this); } LLOutfitsList::~LLOutfitsList() { - delete mGearMenu; - delete mOutfitMenu; - - if (gInventory.containsObserver(mCategoriesObserver)) - { - gInventory.removeObserver(mCategoriesObserver); - } - delete mCategoriesObserver; } BOOL LLOutfitsList::postBuild() @@ -375,54 +116,20 @@ BOOL LLOutfitsList::postBuild() mAccordion = getChild<LLAccordionCtrl>("outfits_accordion"); mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR); - LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); - - menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenu::updateItemsVisibility, mGearMenu)); - menu_gear_btn->setMenu(mGearMenu->getMenu()); - - return TRUE; + return LLOutfitListBase::postBuild(); } //virtual -void LLOutfitsList::onOpen(const LLSD& /*info*/) +void LLOutfitsList::onOpen(const LLSD& info) { - if (!mIsInitialized) - { - // *TODO: I'm not sure is this check necessary but it never match while developing. - if (!gInventory.isInventoryUsable()) - return; + if (!mIsInitialized) + { + const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + // Start observing changes in Current Outfit category. + mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); + } - const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - - // *TODO: I'm not sure is this check necessary but it never match while developing. - LLViewerInventoryCategory* category = gInventory.getCategory(outfits); - if (!category) - return; - - gInventory.addObserver(mCategoriesObserver); - - // Start observing changes in "My Outfits" category. - mCategoriesObserver->addCategory(outfits, - boost::bind(&LLOutfitsList::refreshList, this, outfits)); - - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - - // Start observing changes in Current Outfit category. - mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); - - LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this)); - LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this)); - - // Fetch "My Outfits" contents and refresh the list to display - // initially fetched items. If not all items are fetched now - // the observer will refresh the list as soon as the new items - // arrive. - category->fetch(); - refreshList(outfits); - highlightBaseOutfit(); - - mIsInitialized = true; - } + LLOutfitListBase::onOpen(info); LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab(); if (!selected_tab) return; @@ -431,174 +138,131 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/) selected_tab->showAndFocusHeader(); } -void LLOutfitsList::refreshList(const LLUUID& category_id) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - - // Collect all sub-categories of a given category. - LLIsType is_category(LLAssetType::AT_CATEGORY); - gInventory.collectDescendentsIf( - category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_category); - - uuid_vec_t vadded; - uuid_vec_t vremoved; - - // Create added and removed items vectors. - computeDifference(cat_array, vadded, vremoved); - - // Handle added tabs. - for (uuid_vec_t::const_iterator iter = vadded.begin(); - iter != vadded.end(); - ++iter) - { - const LLUUID cat_id = (*iter); - LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); - if (!cat) continue; - - std::string name = cat->getName(); - - outfit_accordion_tab_params tab_params(get_accordion_tab_params()); - LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); - if (!tab) continue; - LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); - wearable_list->setShape(tab->getLocalRect()); - tab->addChild(wearable_list); - tab->setName(name); - tab->setTitle(name); - - // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. - tab->setDisplayChildren(false); - mAccordion->addCollapsibleCtrl(tab); - - // Start observing the new outfit category. - LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list"); - if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) - { - // Remove accordion tab if category could not be added to observer. - mAccordion->removeCollapsibleCtrl(tab); - - // kill removed tab - tab->die(); - continue; - } - - // Map the new tab with outfit category UUID. - mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); - - tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this, - _1, _2, _3, cat_id)); +void LLOutfitsList::updateAddedCategory(LLUUID cat_id) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (!cat) return; - // Setting tab focus callback to monitor currently selected outfit. - tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id)); + std::string name = cat->getName(); - // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) - tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); + outfit_accordion_tab_params tab_params(get_accordion_tab_params()); + LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params); + if (!tab) return; + LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list); + wearable_list->setShape(tab->getLocalRect()); + tab->addChild(wearable_list); - // force showing list items that don't match current filter(EXT-7158) - list->setForceShowingUnmatchedItems(true); + tab->setName(name); + tab->setTitle(name); - // Setting list commit callback to monitor currently selected wearable item. - list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1)); + // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. + tab->setDisplayChildren(false); + mAccordion->addCollapsibleCtrl(tab); - // Setting list refresh callback to apply filter on list change. - list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); + // Start observing the new outfit category. + LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list"); + if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id))) + { + // Remove accordion tab if category could not be added to observer. + mAccordion->removeCollapsibleCtrl(tab); - list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); + // kill removed tab + tab->die(); + return; + } - // Fetch the new outfit contents. - cat->fetch(); + // Map the new tab with outfit category UUID. + mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); - // Refresh the list of outfit items after fetch(). - // Further list updates will be triggered by the category observer. - list->updateList(cat_id); + tab->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this, + _1, _2, _3, cat_id)); - // If filter is currently applied we store the initial tab state and - // open it to show matched items if any. - if (!sFilterSubString.empty()) - { - tab->notifyChildren(LLSD().with("action","store_state")); - tab->setDisplayChildren(true); + // Setting tab focus callback to monitor currently selected outfit. + tab->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id)); - // Setting mForceRefresh flag will make the list refresh its contents - // even if it is not currently visible. This is required to apply the - // filter to the newly added list. - list->setForceRefresh(true); + // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875) + tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id)); - list->setFilterSubString(sFilterSubString); - } - } + // force showing list items that don't match current filter(EXT-7158) + list->setForceShowingUnmatchedItems(true); - // Handle removed tabs. - for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter) - { - outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); - if (outfits_iter != mOutfitsMap.end()) - { - const LLUUID& outfit_id = outfits_iter->first; - LLAccordionCtrlTab* tab = outfits_iter->second; + // Setting list commit callback to monitor currently selected wearable item. + list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1)); - // An outfit is removed from the list. Do the following: - // 1. Remove outfit category from observer to stop monitoring its changes. - mCategoriesObserver->removeCategory(outfit_id); + // Setting list refresh callback to apply filter on list change. + list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); - // 2. Remove the outfit from selection. - deselectOutfit(outfit_id); + list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); - // 3. Remove category UUID to accordion tab mapping. - mOutfitsMap.erase(outfits_iter); + // Fetch the new outfit contents. + cat->fetch(); - // 4. Remove outfit tab from accordion. - mAccordion->removeCollapsibleCtrl(tab); + // Refresh the list of outfit items after fetch(). + // Further list updates will be triggered by the category observer. + list->updateList(cat_id); - // kill removed tab - if (tab != NULL) - { - tab->die(); - } - } - } + // If filter is currently applied we store the initial tab state and + // open it to show matched items if any. + if (!sFilterSubString.empty()) + { + tab->notifyChildren(LLSD().with("action", "store_state")); + tab->setDisplayChildren(true); - // Get changed items from inventory model and update outfit tabs - // which might have been renamed. - const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); - for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); - items_iter != changed_items.end(); - ++items_iter) - { - updateOutfitTab(*items_iter); - } + // Setting mForceRefresh flag will make the list refresh its contents + // even if it is not currently visible. This is required to apply the + // filter to the newly added list. + list->setForceRefresh(true); - mAccordion->sort(); + list->setFilterSubString(sFilterSubString); + } } -void LLOutfitsList::highlightBaseOutfit() +void LLOutfitsList::updateRemovedCategory(LLUUID cat_id) { - // id of base outfit - LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); - if (base_id != mHighlightedOutfitUUID) - { - if (mOutfitsMap[mHighlightedOutfitUUID]) - { - mOutfitsMap[mHighlightedOutfitUUID]->setTitleFontStyle("NORMAL"); - mOutfitsMap[mHighlightedOutfitUUID]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor")); - } + outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat_id); + if (outfits_iter != mOutfitsMap.end()) + { + const LLUUID& outfit_id = outfits_iter->first; + LLAccordionCtrlTab* tab = outfits_iter->second; + + // An outfit is removed from the list. Do the following: + // 1. Remove outfit category from observer to stop monitoring its changes. + mCategoriesObserver->removeCategory(outfit_id); + + // 2. Remove the outfit from selection. + deselectOutfit(outfit_id); + + // 3. Remove category UUID to accordion tab mapping. + mOutfitsMap.erase(outfits_iter); + + // 4. Remove outfit tab from accordion. + mAccordion->removeCollapsibleCtrl(tab); + + // kill removed tab + if (tab != NULL) + { + tab->die(); + } + } +} - mHighlightedOutfitUUID = base_id; - } - if (mOutfitsMap[base_id]) +//virtual +void LLOutfitsList::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) +{ + if (mOutfitsMap[prev_id]) + { + mOutfitsMap[prev_id]->setTitleFontStyle("NORMAL"); + mOutfitsMap[prev_id]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor")); + } + if (mOutfitsMap[base_id]) { mOutfitsMap[base_id]->setTitleFontStyle("BOLD"); mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor")); } } -void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) +void LLOutfitsList::onListSelectionChange(LLUICtrl* ctrl) { LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl); if (!list) return; @@ -606,10 +270,10 @@ void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID()); if (!item) return; - changeOutfitSelection(list, item->getParentUUID()); + ChangeOutfitSelection(list, item->getParentUUID()); } -void LLOutfitsList::performAction(std::string action) +void LLOutfitListBase::performAction(std::string action) { if (mSelectedOutfitUUID.isNull()) return; @@ -630,23 +294,7 @@ void LLOutfitsList::performAction(std::string action) } } -void LLOutfitsList::removeSelected() -{ - LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2)); -} - -void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled - - if (mSelectedOutfitUUID.notNull()) - { - gInventory.removeCategory(mSelectedOutfitUUID); - } -} - -void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid) +void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) { for (outfits_map_t::iterator iter = mOutfitsMap.begin(); iter != mOutfitsMap.end(); @@ -661,7 +309,7 @@ void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid) if (!list) continue; tab->setFocus(TRUE); - changeOutfitSelection(list, outfit_uuid); + ChangeOutfitSelection(list, outfit_uuid); tab->setDisplayChildren(true); } @@ -677,14 +325,14 @@ void LLOutfitsList::setFilterSubString(const std::string& string) } // virtual -bool LLOutfitsList::isActionEnabled(const LLSD& userdata) +bool LLOutfitListBase::isActionEnabled(const LLSD& userdata) { if (mSelectedOutfitUUID.isNull()) return false; const std::string command_name = userdata.asString(); if (command_name == "delete") { - return !mItemSelected && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID); + return !hasItemSelected() && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID); } if (command_name == "rename") { @@ -745,7 +393,7 @@ void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const } } -void LLOutfitsList::collapse_all_folders() +void LLOutfitsList::onCollapseAllFolders() { for (outfits_map_t::iterator iter = mOutfitsMap.begin(); iter != mOutfitsMap.end(); @@ -759,7 +407,7 @@ void LLOutfitsList::collapse_all_folders() } } -void LLOutfitsList::expand_all_folders() +void LLOutfitsList::onExpandAllFolders() { for (outfits_map_t::iterator iter = mOutfitsMap.begin(); iter != mOutfitsMap.end(); @@ -773,11 +421,6 @@ void LLOutfitsList::expand_all_folders() } } -boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb) -{ - return mSelectionChangeSignal.connect(cb); -} - bool LLOutfitsList::hasItemSelected() { return mItemSelected; @@ -786,42 +429,12 @@ bool LLOutfitsList::hasItemSelected() ////////////////////////////////////////////////////////////////////////// // Private methods ////////////////////////////////////////////////////////////////////////// -void LLOutfitsList::computeDifference( - const LLInventoryModel::cat_array_t& vcats, - uuid_vec_t& vadded, - uuid_vec_t& vremoved) -{ - uuid_vec_t vnew; - // Creating a vector of newly collected sub-categories UUIDs. - for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); - iter != vcats.end(); - iter++) - { - vnew.push_back((*iter)->getUUID()); - } - - uuid_vec_t vcur; - // Creating a vector of currently displayed sub-categories UUIDs. - for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); - iter != mOutfitsMap.end(); - iter++) - { - vcur.push_back((*iter).first); - } - LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); -} - -void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) +void LLOutfitsList::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) { - outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id); + outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat->getUUID()); if (outfits_iter != mOutfitsMap.end()) { - LLViewerInventoryCategory *cat = gInventory.getCategory(category_id); - if (!cat) return; - - std::string name = cat->getName(); - // Update tab name with the new category name. LLAccordionCtrlTab* tab = outfits_iter->second; if (tab) @@ -836,10 +449,10 @@ void LLOutfitsList::resetItemSelection(LLWearableItemsList* list, const LLUUID& { list->resetSelection(); mItemSelected = false; - setSelectedOutfitUUID(category_id); + signalSelectionOutfitUUID(category_id); } -void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +void LLOutfitsList::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) { MASK mask = gKeyboard->currentMask(TRUE); @@ -865,24 +478,14 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI mItemSelected = list && (list->getSelectedItem() != NULL); mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list)); - setSelectedOutfitUUID(category_id); -} - -void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id) -{ - mSelectionChangeSignal(mSelectedOutfitUUID = category_id); } void LLOutfitsList::deselectOutfit(const LLUUID& category_id) { // Remove selected lists map entry. mSelectedListsMap.erase(category_id); - - // Reset selection if the outfit is selected. - if (category_id == mSelectedOutfitUUID) - { - setSelectedOutfitUUID(LLUUID::null); - } + + LLOutfitListBase::deselectOutfit(category_id); } void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID& category_id) @@ -890,7 +493,7 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID // Try restoring outfit selection after filtering. if (mAccordion->getSelectedTab() == tab) { - setSelectedOutfitUUID(category_id); + signalSelectionOutfitUUID(category_id); } } @@ -1036,24 +639,6 @@ bool LLOutfitsList::canWearSelected() return true; } -void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) -{ - LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl); - if(mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull()) - { - // Focus tab header to trigger tab selection change. - LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header"); - if (header) - { - header->setFocus(TRUE); - } - - uuid_vec_t selected_uuids; - selected_uuids.push_back(cat_id); - mOutfitMenu->show(ctrl, selected_uuids, x, y); - } -} - void LLOutfitsList::wearSelectedItems() { uuid_vec_t selected_uuids; @@ -1132,6 +717,47 @@ void LLOutfitsList::onCOFChanged() } } +void LLOutfitsList::getCurrentCategories(uuid_vec_t& vcur) +{ + // Creating a vector of currently displayed sub-categories UUIDs. + for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); + iter != mOutfitsMap.end(); + iter++) + { + vcur.push_back((*iter).first); + } +} + + +void LLOutfitsList::sortOutfits() +{ + mAccordion->sort(); +} + +void LLOutfitsList::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ + LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl); + if (mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull()) + { + // Focus tab header to trigger tab selection change. + LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header"); + if (header) + { + header->setFocus(TRUE); + } + + uuid_vec_t selected_uuids; + selected_uuids.push_back(cat_id); + mOutfitMenu->show(ctrl, selected_uuids, x, y); + } +} + +LLOutfitListGearMenuBase* LLOutfitsList::createGearMenu() +{ + return new LLOutfitListGearMenu(this); +} + + bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y) { if(!tab || !tab->getHeaderVisible()) return false; @@ -1140,4 +766,512 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y) return y >= header_bottom; } +LLOutfitListBase::LLOutfitListBase() + : LLPanelAppearanceTab() + , mIsInitialized(false) +{ + mCategoriesObserver = new LLInventoryCategoriesObserver(); + mOutfitMenu = new LLOutfitContextMenu(this); + //mGearMenu = createGearMenu(); +} + +LLOutfitListBase::~LLOutfitListBase() +{ + delete mOutfitMenu; + delete mGearMenu; + + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; +} + +void LLOutfitListBase::onOpen(const LLSD& info) +{ + if (!mIsInitialized) + { + // *TODO: I'm not sure is this check necessary but it never match while developing. + if (!gInventory.isInventoryUsable()) + return; + + const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + // *TODO: I'm not sure is this check necessary but it never match while developing. + LLViewerInventoryCategory* category = gInventory.getCategory(outfits); + if (!category) + return; + + gInventory.addObserver(mCategoriesObserver); + + // Start observing changes in "My Outfits" category. + mCategoriesObserver->addCategory(outfits, + boost::bind(&LLOutfitListBase::refreshList, this, outfits)); + + const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + + // Start observing changes in Current Outfit category. + //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); + + LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this)); + LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this)); + + // Fetch "My Outfits" contents and refresh the list to display + // initially fetched items. If not all items are fetched now + // the observer will refresh the list as soon as the new items + // arrive. + category->fetch(); + refreshList(outfits); + highlightBaseOutfit(); + + mIsInitialized = true; + } +} + +void LLOutfitListBase::refreshList(const LLUUID& category_id) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + // Collect all sub-categories of a given category. + LLIsType is_category(LLAssetType::AT_CATEGORY); + gInventory.collectDescendentsIf( + category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_category); + + uuid_vec_t vadded; + uuid_vec_t vremoved; + + // Create added and removed items vectors. + computeDifference(cat_array, vadded, vremoved); + + // Handle added tabs. + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + const LLUUID cat_id = (*iter); + updateAddedCategory(cat_id); + } + + // Handle removed tabs. + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + const LLUUID cat_id = (*iter); + updateRemovedCategory(cat_id); + } + + // Get changed items from inventory model and update outfit tabs + // which might have been renamed. + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); + items_iter != changed_items.end(); + ++items_iter) + { + LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter); + if (!cat) return; + + std::string name = cat->getName(); + + updateChangedCategoryName(cat, name); + } + + sortOutfits(); +} + +void LLOutfitListBase::computeDifference( + const LLInventoryModel::cat_array_t& vcats, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vnew; + // Creating a vector of newly collected sub-categories UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); + iter != vcats.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + + uuid_vec_t vcur; + getCurrentCategories(vcur); + + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); +} + +void LLOutfitListBase::sortOutfits() +{ +} + +void LLOutfitListBase::highlightBaseOutfit() +{ + // id of base outfit + LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); + if (base_id != mHighlightedOutfitUUID) + { + LLUUID prev_id = mHighlightedOutfitUUID; + mHighlightedOutfitUUID = base_id; + onHighlightBaseOutfit(base_id, prev_id); + } + +} + +void LLOutfitListBase::removeSelected() +{ + LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitListBase::onOutfitsRemovalConfirmation, this, _1, _2)); +} + +void LLOutfitListBase::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + if (mSelectedOutfitUUID.notNull()) + { + gInventory.removeCategory(mSelectedOutfitUUID); + } +} + +void LLOutfitListBase::setSelectedOutfitByUUID(const LLUUID& outfit_uuid) +{ + onSetSelectedOutfitByUUID(outfit_uuid); +} + +boost::signals2::connection LLOutfitListBase::setSelectionChangeCallback(selection_change_callback_t cb) +{ + return mSelectionChangeSignal.connect(cb); +} + +void LLOutfitListBase::signalSelectionOutfitUUID(const LLUUID& category_id) +{ + mSelectionChangeSignal(category_id); +} + +void LLOutfitListBase::outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) +{ + onOutfitRightClick(ctrl, x, y, cat_id); +} + +void LLOutfitListBase::ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) +{ + onChangeOutfitSelection(list, category_id); + mSelectedOutfitUUID = category_id; + signalSelectionOutfitUUID(category_id); +} + +BOOL LLOutfitListBase::postBuild() +{ + mGearMenu = createGearMenu(); + + LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); + + menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenuBase::updateItemsVisibility, mGearMenu)); + menu_gear_btn->setMenu(mGearMenu->getMenu()); + return TRUE; +} + +void LLOutfitListBase::collapseAllFolders() +{ + onCollapseAllFolders(); +} + +void LLOutfitListBase::expandAllFolders() +{ + onExpandAllFolders(); +} + +void LLOutfitListBase::deselectOutfit(const LLUUID& category_id) +{ + // Reset selection if the outfit is selected. + if (category_id == mSelectedOutfitUUID) + { + signalSelectionOutfitUUID(LLUUID::null); + } +} + +LLContextMenu* LLOutfitContextMenu::createMenu() +{ + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + LLUUID selected_id = mUUIDs.front(); + + registrar.add("Outfit.WearReplace", + boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.WearAdd", + boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.TakeOff", + boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); + registrar.add("Outfit.Edit", boost::bind(editOutfit)); + registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); + registrar.add("Outfit.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList)); + + enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2)); + enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2)); + + return createFromFile("menu_outfit_tab.xml"); + +} + +bool LLOutfitContextMenu::onEnable(LLSD::String param) +{ + LLUUID outfit_cat_id = mUUIDs.back(); + + if ("rename" == param) + { + return get_is_category_renameable(&gInventory, outfit_cat_id); + } + else if ("wear_replace" == param) + { + return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id); + } + else if ("wear_add" == param) + { + return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id); + } + else if ("take_off" == param) + { + return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id); + } + + return true; +} + +bool LLOutfitContextMenu::onVisible(LLSD::String param) +{ + LLUUID outfit_cat_id = mUUIDs.back(); + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; + + if ("edit" == param) + { + return is_worn; + } + else if ("wear_replace" == param) + { + return !is_worn; + } + else if ("delete" == param) + { + return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); + } + + return true; +} + +//static +void LLOutfitContextMenu::editOutfit() +{ + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); +} + +void LLOutfitContextMenu::renameOutfit(const LLUUID& outfit_cat_id) +{ + LLAppearanceMgr::instance().renameOutfit(outfit_cat_id); +} + +LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist) + : mOutfitList(olist), + mMenu(NULL) +{ + llassert_always(mOutfitList); + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenuBase::onWear, this)); + registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenuBase::onTakeOff, this)); + registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenuBase::onRename, this)); + registrar.add("Gear.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList)); + registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenuBase::onCreate, this, _2)); + registrar.add("Gear.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, mOutfitList)); + registrar.add("Gear.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, mOutfitList)); + + registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this)); + + registrar.add("Gear.UploadPhoto", boost::bind(&LLOutfitListGearMenuBase::onUploadFoto, this)); + registrar.add("Gear.SelectPhoto", boost::bind(&LLOutfitListGearMenuBase::onSelectPhoto, this)); + registrar.add("Gear.TakeSnapshot", boost::bind(&LLOutfitListGearMenuBase::onTakeSnapshot, this)); + registrar.add("Gear.RemovePhoto", boost::bind(&LLOutfitListGearMenuBase::onRemovePhoto, this)); + registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this)); + + enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2)); + enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenuBase::onVisible, this, _2)); + + mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( + "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + llassert(mMenu); +} + +LLOutfitListGearMenuBase::~LLOutfitListGearMenuBase() +{} + +void LLOutfitListGearMenuBase::updateItemsVisibility() +{ + onUpdateItemsVisibility(); +} + +void LLOutfitListGearMenuBase::onUpdateItemsVisibility() +{ + if (!mMenu) return; + + bool have_selection = getSelectedOutfitID().notNull(); + mMenu->setItemVisible("sepatator1", have_selection); + mMenu->setItemVisible("sepatator2", have_selection); + mMenu->arrangeAndClear(); // update menu height +} + +LLToggleableMenu* LLOutfitListGearMenuBase::getMenu() +{ + return mMenu; +} +const LLUUID& LLOutfitListGearMenuBase::getSelectedOutfitID() +{ + return mOutfitList->getSelectedOutfitUUID(); +} + +LLViewerInventoryCategory* LLOutfitListGearMenuBase::getSelectedOutfit() +{ + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) + { + return NULL; + } + + LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id); + return cat; +} + +void LLOutfitListGearMenuBase::onWear() +{ + LLViewerInventoryCategory* selected_outfit = getSelectedOutfit(); + if (selected_outfit) + { + LLAppearanceMgr::instance().wearInventoryCategory( + selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE); + } +} + +void LLOutfitListGearMenuBase::onAdd() +{ + const LLUUID& selected_id = getSelectedOutfitID(); + + if (selected_id.notNull()) + { + LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id); + } +} + +void LLOutfitListGearMenuBase::onTakeOff() +{ + // Take off selected outfit. + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.notNull()) + { + LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id); + } +} + +void LLOutfitListGearMenuBase::onRename() +{ + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.notNull()) + { + LLAppearanceMgr::instance().renameOutfit(selected_outfit_id); + } +} + +void LLOutfitListGearMenuBase::onCreate(const LLSD& data) +{ + LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); + if (type == LLWearableType::WT_NONE) + { + LL_WARNS() << "Invalid wearable type" << LL_ENDL; + return; + } + + LLAgentWearables::createWearable(type, true); +} + +bool LLOutfitListGearMenuBase::onEnable(LLSD::String param) +{ + // Handle the "Wear - Replace Current Outfit" menu option specially + // because LLOutfitList::isActionEnabled() checks whether it's allowed + // to wear selected outfit OR selected items, while we're only + // interested in the outfit (STORM-183). + if ("wear" == param) + { + return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID()); + } + + return mOutfitList->isActionEnabled(param); +} + +bool LLOutfitListGearMenuBase::onVisible(LLSD::String param) +{ + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) // no selection or invalid outfit selected + { + return false; + } + + // *TODO This condition leads to menu item behavior inconsistent with + // "Wear" button behavior and should be modified or removed. + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; + + if ("wear" == param) + { + return !is_worn; + } + + return true; +} + +void LLOutfitListGearMenuBase::onUploadFoto() +{ + +} + +void LLOutfitListGearMenuBase::onSelectPhoto() +{ + +} + +void LLOutfitListGearMenuBase::onTakeSnapshot() +{ + +} + +void LLOutfitListGearMenuBase::onRemovePhoto() +{ + +} + +void LLOutfitListGearMenuBase::onChangeSortOrder() +{ + +} + +LLOutfitListGearMenu::LLOutfitListGearMenu(LLOutfitListBase* olist) + : LLOutfitListGearMenuBase(olist) +{} + +LLOutfitListGearMenu::~LLOutfitListGearMenu() +{} + +void LLOutfitListGearMenu::onUpdateItemsVisibility() +{ + if (!mMenu) return; + mMenu->setItemVisible("expand", TRUE); + mMenu->setItemVisible("collapse", TRUE); + mMenu->setItemVisible("upload_photo", FALSE); + mMenu->setItemVisible("select_photo", FALSE); + mMenu->setItemVisible("take_snapshot", FALSE); + mMenu->setItemVisible("remove_photo", FALSE); + mMenu->setItemVisible("sepatator3", FALSE); + mMenu->setItemVisible("sort_folders_by_name", FALSE); + LLOutfitListGearMenuBase::onUpdateItemsVisibility(); +} + // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 2e3fb3f488..81be8de94f 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -32,11 +32,14 @@ // newview #include "llinventorymodel.h" +#include "lllistcontextmenu.h" #include "llpanelappearancetab.h" +#include "lltoggleablemenu.h" +#include "llviewermenu.h" class LLAccordionCtrlTab; class LLInventoryCategoriesObserver; -class LLOutfitListGearMenu; +class LLOutfitListGearMenuBase; class LLWearableItemsList; class LLListContextMenu; @@ -57,6 +60,142 @@ public: /*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const; }; +class LLOutfitListBase : public LLPanelAppearanceTab +{ +public: + typedef boost::function<void(const LLUUID&)> selection_change_callback_t; + typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t; + + LLOutfitListBase(); + virtual ~LLOutfitListBase(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& info); + + void refreshList(const LLUUID& category_id); + void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); + // highlights currently worn outfit in list and unhighlights previously worn + void highlightBaseOutfit(); + void ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + + + virtual void getCurrentCategories(uuid_vec_t& vcur) = 0; + virtual void updateAddedCategory(LLUUID cat_id) = 0; + virtual void updateRemovedCategory(LLUUID cat_id) = 0; + virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0; + virtual void sortOutfits(); + + void removeSelected(); + void setSelectedOutfitByUUID(const LLUUID& outfit_uuid); + const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } + boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); + void outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); + + virtual bool isActionEnabled(const LLSD& userdata); + virtual void performAction(std::string action); + virtual bool hasItemSelected() = 0; + virtual bool canWearSelected() = 0; + + virtual void deselectOutfit(const LLUUID& category_id); + + void signalSelectionOutfitUUID(const LLUUID& category_id); + + void collapseAllFolders(); + virtual void onCollapseAllFolders() = 0; + + void expandAllFolders(); + virtual void onExpandAllFolders() = 0; + + virtual bool getHasExpandableFolders() = 0; + +protected: + virtual LLOutfitListGearMenuBase* createGearMenu() = 0; + virtual void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) = 0; + virtual void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) = 0; + virtual void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) = 0; + void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); + virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0; + + bool mIsInitialized; + LLInventoryCategoriesObserver* mCategoriesObserver; + LLUUID mSelectedOutfitUUID; + // id of currently highlited outfit + LLUUID mHighlightedOutfitUUID; + selection_change_signal_t mSelectionChangeSignal; + LLListContextMenu* mOutfitMenu; + LLOutfitListGearMenuBase* mGearMenu; +}; + +////////////////////////////////////////////////////////////////////////// + +class LLOutfitContextMenu : public LLListContextMenu +{ +public: + + LLOutfitContextMenu(LLOutfitListBase* outfit_list) + : LLListContextMenu(), + mOutfitList(outfit_list) + {} +protected: + /* virtual */ LLContextMenu* createMenu(); + + bool onEnable(LLSD::String param); + + bool onVisible(LLSD::String param); + + static void editOutfit(); + + static void renameOutfit(const LLUUID& outfit_cat_id); + +private: + LLOutfitListBase* mOutfitList; +}; + +class LLOutfitListGearMenuBase +{ +public: + LLOutfitListGearMenuBase(LLOutfitListBase* olist); + virtual ~LLOutfitListGearMenuBase(); + + void updateItemsVisibility(); + + LLToggleableMenu* getMenu(); + +protected: + virtual void onUpdateItemsVisibility(); + virtual void onUploadFoto(); + virtual void onSelectPhoto(); + virtual void onTakeSnapshot(); + virtual void onRemovePhoto(); + virtual void onChangeSortOrder(); + + const LLUUID& getSelectedOutfitID(); + + LLOutfitListBase* mOutfitList; + LLToggleableMenu* mMenu; +private: + + LLViewerInventoryCategory* getSelectedOutfit(); + + void onWear(); + void onAdd(); + void onTakeOff(); + void onRename(); + void onCreate(const LLSD& data); + bool onEnable(LLSD::String param); + bool onVisible(LLSD::String param); +}; + +class LLOutfitListGearMenu : public LLOutfitListGearMenuBase +{ +public: + LLOutfitListGearMenu(LLOutfitListBase* olist); + virtual ~LLOutfitListGearMenu(); + +protected: + /*virtual*/ void onUpdateItemsVisibility(); +}; + /** * @class LLOutfitsList * @@ -66,11 +205,9 @@ public: * * Starts fetching necessary inventory content on first opening. */ -class LLOutfitsList : public LLPanelAppearanceTab +class LLOutfitsList : public LLOutfitListBase { public: - typedef boost::function<void (const LLUUID&)> selection_change_callback_t; - typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t; LLOutfitsList(); virtual ~LLOutfitsList(); @@ -79,63 +216,66 @@ public: /*virtual*/ void onOpen(const LLSD& info); - void refreshList(const LLUUID& category_id); - - // highlits currently worn outfit tab text and unhighlights previously worn - void highlightBaseOutfit(); - void performAction(std::string action); + //virtual void refreshList(const LLUUID& category_id); - void removeSelected(); + /*virtual*/ void updateAddedCategory(LLUUID cat_id); + /*virtual*/ void updateRemovedCategory(LLUUID cat_id); - void setSelectedOutfitByUUID(const LLUUID& outfit_uuid); + // highlits currently worn outfit tab text and unhighlights previously worn + /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id); - /*virtual*/ void setFilterSubString(const std::string& string); + //void performAction(std::string action); - /*virtual*/ bool isActionEnabled(const LLSD& userdata); - const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } + /*virtual*/ void setFilterSubString(const std::string& string); /*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const; - boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); - - // Collects selected items from all selected lists and wears them(if possible- adds, else replaces) + // Collects selected items from all selected lists and wears them(if possible- adds, else replaces) void wearSelectedItems(); /** * Returns true if there is a selection inside currently selected outfit */ - bool hasItemSelected(); + /*virtual*/ bool hasItemSelected(); /** Collapses all outfit accordions. */ - void collapse_all_folders(); + /*virtual*/ void onCollapseAllFolders(); /** Expands all outfit accordions. */ - void expand_all_folders(); + void onExpandAllFolders(); + /*virtual*/ bool getHasExpandableFolders() { return TRUE; } -private: +protected: + LLOutfitListGearMenuBase* createGearMenu(); - void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); +private: /** * Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference */ - void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); + //void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); + + void getCurrentCategories(uuid_vec_t& vcur); /** * Updates tab displaying outfit identified by category_id. */ - void updateOutfitTab(const LLUUID& category_id); + /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + + /*virtual*/ void sortOutfits(); + + /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid); /** * Resets previous selection and stores newly selected list and outfit id. */ - void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); /** *Resets items selection inside outfit @@ -143,14 +283,9 @@ private: void resetItemSelection(LLWearableItemsList* list, const LLUUID& category_id); /** - * Saves newly selected outfit ID. - */ - void setSelectedOutfitUUID(const LLUUID& category_id); - - /** * Removes the outfit from selection. */ - void deselectOutfit(const LLUUID& category_id); + /*virtual*/ void deselectOutfit(const LLUUID& category_id); /** * Try restoring selection for a temporary hidden tab. @@ -182,15 +317,16 @@ private: */ bool canWearSelected(); - void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); void onCOFChanged(); - void onSelectionChange(LLUICtrl* ctrl); + void onListSelectionChange(LLUICtrl* ctrl); + + /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); static void onOutfitRename(const LLSD& notification, const LLSD& response); - LLInventoryCategoriesObserver* mCategoriesObserver; + //LLInventoryCategoriesObserver* mCategoriesObserver; LLAccordionCtrl* mAccordion; LLPanel* mListCommands; @@ -199,11 +335,6 @@ private: typedef wearables_lists_map_t::value_type wearables_lists_map_value_t; wearables_lists_map_t mSelectedListsMap; - LLUUID mSelectedOutfitUUID; - // id of currently highlited outfit - LLUUID mHighlightedOutfitUUID; - selection_change_signal_t mSelectionChangeSignal; - typedef std::map<LLUUID, LLAccordionCtrlTab*> outfits_map_t; typedef outfits_map_t::value_type outfits_map_value_t; outfits_map_t mOutfitsMap; @@ -212,10 +343,9 @@ private: // Used to monitor COF changes for updating items worn state. See EXT-8636. uuid_vec_t mCOFLinkedItems; - LLOutfitListGearMenu* mGearMenu; - LLListContextMenu* mOutfitMenu; + //LLOutfitListGearMenu* mGearMenu; - bool mIsInitialized; + //bool mIsInitialized; /** * True if there is a selection inside currently selected outfit */ diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index b2164c1f21..d17f5494a0 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -199,7 +199,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group) mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor"); - mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCII ); + mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCIINoLeadingSpace ); } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c779ba5cdd..eb40616a9c 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -106,7 +106,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mSavedFolderState(NULL), mFilterText(""), mMenuGearDefault(NULL), - mMenuAdd(NULL), + mMenuAddHandle(), mNeedUploadCost(true) { // Menu Callbacks (non contex menus) @@ -200,10 +200,15 @@ BOOL LLPanelMainInventory::postBuild() // *TODO:Get the cost info from the server const std::string upload_cost("10"); - mMenuAdd->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost); - mMenuAdd->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost); - mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost); - mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost); + + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { + menu->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost); + menu->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost); + menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost); + menu->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost); + } // Trigger callback for focus received so we can deselect items in inbox/outbox LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this)); @@ -983,7 +988,8 @@ void LLPanelMainInventory::initListCommandsHandlers() mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGearMenuButton->setMenu(mMenuGearDefault); - mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mMenuAddHandle = menu->getHandle(); // Update the trash button when selected item(s) get worn or taken off. LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); @@ -1001,11 +1007,15 @@ void LLPanelMainInventory::onAddButtonClick() // Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed // unless "Always show folders" is checked in the filter options. bool recent_active = ("Recent Items" == mActivePanel->getName()); - mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active); + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { + menu->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active); - setUploadCostIfNeeded(); + setUploadCostIfNeeded(); - showActionMenu(mMenuAdd,"add_btn"); + showActionMenu(menu,"add_btn"); + } } void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) @@ -1156,7 +1166,11 @@ void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) { if(!new_visibility) { - mMenuAdd->setVisible(FALSE); + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { + menu->setVisible(FALSE); + } getActivePanel()->getRootFolder()->finishRenamingItem(); } } @@ -1289,9 +1303,10 @@ void LLPanelMainInventory::setUploadCostIfNeeded() // have two instances of Inventory panel at the moment(and two instances of context menu), // call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances. - if(mNeedUploadCost && mMenuAdd) + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if(mNeedUploadCost && menu) { - LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload"); + LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload"); if(upload_menu) { S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 290e2e5f47..efa18b42c1 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -156,8 +156,8 @@ protected: private: LLDragAndDropButton* mTrashButton; LLToggleableMenu* mMenuGearDefault; - LLMenuGL* mMenuAdd; LLMenuButton* mGearMenuButton; + LLHandle<LLView> mMenuAddHandle; bool mNeedUploadCost; // List Commands // diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 8331c152e2..8b9941c0ca 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1059,9 +1059,6 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) case LLAssetType::AT_BODYPART: applyListViewFilter(LVIT_BODYPART); break; - case LLAssetType::AT_GESTURE: - applyListViewFilter(LVIT_GESTURES); - break; case LLAssetType::AT_CLOTHING: default: applyListViewFilter(LVIT_CLOTHING); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 841bb4337a..30870daf40 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -80,7 +80,6 @@ public: { LVIT_ALL = 0, LVIT_CLOTHING, - LVIT_GESTURES, LVIT_BODYPART, LVIT_ATTACHMENT, LVIT_SHAPE, diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 1e1f59055f..3f700496a9 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -37,6 +37,7 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "lloutfitobserver.h" +#include "lloutfitgallery.h" #include "lloutfitslist.h" #include "llpanelwearing.h" #include "llsaveoutfitcombobtn.h" @@ -44,6 +45,7 @@ #include "llviewerfoldertype.h" static const std::string OUTFITS_TAB_NAME = "outfitslist_tab"; +static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab"; static const std::string COF_TAB_NAME = "cof_tab"; static LLPanelInjector<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory"); @@ -165,14 +167,22 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string) void LLPanelOutfitsInventory::onWearButtonClick() { - if (mMyOutfitsPanel->hasItemSelected()) + if(isOutfitsListPanelActive()) { - mMyOutfitsPanel->wearSelectedItems(); + if (mMyOutfitsPanel->hasItemSelected()) + { + mMyOutfitsPanel->wearSelectedItems(); + } + else + { + mMyOutfitsPanel->performAction("replaceoutfit"); + } } - else + else if(isOutfitsGalleryPanelActive()) { - mMyOutfitsPanel->performAction("replaceoutfit"); + mOutfitGalleryPanel->wearSelectedOutfit(); } + } bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD& response) @@ -234,6 +244,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers() mListCommands = getChild<LLPanel>("bottom_panel"); mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this)); mMyOutfitsPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this)); + mOutfitGalleryPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this)); } void LLPanelOutfitsInventory::updateListCommands() @@ -245,15 +256,23 @@ void LLPanelOutfitsInventory::updateListCommands() LLButton* wear_btn = mListCommands->getChild<LLButton>("wear_btn"); mMyOutfitsPanel->childSetEnabled("trash_btn", trash_enabled); + mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled); wear_btn->setEnabled(wear_enabled); wear_btn->setVisible(wear_visible); mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); - wear_btn->setToolTip(getString(mMyOutfitsPanel->hasItemSelected() ? "wear_items_tooltip" : "wear_outfit_tooltip")); + wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip")); } void LLPanelOutfitsInventory::onTrashButtonClick() { - mMyOutfitsPanel->removeSelected(); + if(isOutfitsListPanelActive()) + { + mMyOutfitsPanel->removeSelected(); + } + else if(isOutfitsGalleryPanelActive()) + { + mOutfitGalleryPanel->removeSelected(); + } } bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) @@ -268,12 +287,16 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) void LLPanelOutfitsInventory::initTabPanels() { + //TODO: Add LLOutfitGallery change callback mCurrentOutfitPanel = findChild<LLPanelWearing>(COF_TAB_NAME); mCurrentOutfitPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); mMyOutfitsPanel = findChild<LLOutfitsList>(OUTFITS_TAB_NAME); mMyOutfitsPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); + mOutfitGalleryPanel = findChild<LLOutfitGallery>(OUTFIT_GALLERY_TAB_NAME); + mOutfitGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); + mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs"); mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this)); } @@ -296,6 +319,22 @@ bool LLPanelOutfitsInventory::isCOFPanelActive() const return mActivePanel->getName() == COF_TAB_NAME; } +bool LLPanelOutfitsInventory::isOutfitsListPanelActive() const +{ + if (!mActivePanel) return false; + + return mActivePanel->getName() == OUTFITS_TAB_NAME; +} + +bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const +{ + if (!mActivePanel) return false; + + return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME; +} + + + void LLPanelOutfitsInventory::setWearablesLoading(bool val) { updateVerbs(); diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index a7917b457c..6a0ea04fa6 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -30,8 +30,9 @@ #include "llpanel.h" +class LLOutfitGallery; class LLOutfitsList; -class LLOutfitListGearMenu; +class LLOutfitListGearMenuBase; class LLPanelAppearanceTab; class LLPanelWearing; class LLMenuGL; @@ -72,10 +73,13 @@ protected: void initTabPanels(); void onTabChange(); bool isCOFPanelActive() const; + bool isOutfitsListPanelActive() const; + bool isOutfitsGalleryPanelActive() const; private: LLPanelAppearanceTab* mActivePanel; LLOutfitsList* mMyOutfitsPanel; + LLOutfitGallery* mOutfitGalleryPanel; LLPanelWearing* mCurrentOutfitPanel; // tab panels // diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 763657ebad..0bcd8a9e63 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mVolumeSliderVisible(0), mWindowShade(NULL), mHideImmediately(false), - mSecureURL(false) + mSecureURL(false), + mMediaPlaySliderCtrlMouseDownValue(0.0) { mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this)); mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this)); mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this)); - mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this)); + mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this)); + mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this)); mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this)); mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this)); @@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL() #endif // USE_COMBO_BOX_FOR_MEDIA_URL } -void LLPanelPrimMediaControls::onCommitSlider() + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown() { - focusOnTarget(); + mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal(); - LLViewerMediaImpl* media_impl = getTargetMediaImpl(); - if (media_impl) + mUpdateSlider = false; +} + +void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp() +{ + F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal(); + + if (mMediaPlaySliderCtrlMouseDownValue != cur_value) { - // get slider value - F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal(); - if(slider_value <= 0.0) - { - media_impl->stop(); - } - else + focusOnTarget(); + + LLViewerMediaImpl* media_impl = getTargetMediaImpl(); + if (media_impl) { - media_impl->seek(slider_value*mMovieDuration); - //mUpdateSlider= false; + if (cur_value <= 0.0) + { + media_impl->stop(); + } + else + { + media_impl->seek(cur_value * mMovieDuration); + } } + + mUpdateSlider = true; } -} +} void LLPanelPrimMediaControls::onCommitVolumeUp() { diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 6d2eb3430e..21d5236074 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -107,8 +107,10 @@ private: void updateZoom(); void setCurrentURL(); - void onCommitSlider(); - + + void onMediaPlaySliderCtrlMouseDown(); + void onMediaPlaySliderCtrlMouseUp(); + void onCommitVolumeUp(); void onCommitVolumeDown(); void onCommitVolumeSlider(); @@ -219,6 +221,8 @@ private: S32 mVolumeSliderVisible; LLNotificationPtr mActiveNotification; + + F64 mMediaPlaySliderCtrlMouseDownValue; }; #endif // LL_PANELPRIMMEDIACONTROLS_H diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 184238c40c..8afa35efa0 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -44,19 +44,11 @@ static const std::string PANEL_PICKS = "panel_picks"; std::string getProfileURL(const std::string& agent_name) { - std::string url; - - if (LLGridManager::getInstance()->isInProductionGrid()) - { - url = gSavedSettings.getString("WebProfileURL"); - } - else - { - url = gSavedSettings.getString("WebProfileNonProductionURL"); - } + std::string url = "[WEB_PROFILE_URL][AGENT_NAME]"; LLSD subs; + subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); subs["AGENT_NAME"] = agent_name; - url = LLWeb::expandURLSubstitutions(url,subs); + url = LLWeb::expandURLSubstitutions(url, subs); LLStringUtil::toLower(url); return url; } diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp index 106fb4997e..a17e3f9e78 100644 --- a/indra/newview/llpanelsnapshot.cpp +++ b/indra/newview/llpanelsnapshot.cpp @@ -29,6 +29,8 @@ // libs #include "llcombobox.h" +#include "llfloater.h" +#include "llfloatersnapshot.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "lltrans.h" @@ -50,15 +52,29 @@ S32 power_of_two(S32 sz, S32 upper) return res; } +LLPanelSnapshot::LLPanelSnapshot() + : mSnapshotFloater(NULL) +{} + // virtual BOOL LLPanelSnapshot::postBuild() { getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onResolutionComboCommit, this, _1)); - getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); - getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); - getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1)); - + if (!getWidthSpinnerName().empty()) + { + getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); + } + if (!getHeightSpinnerName().empty()) + { + getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this)); + } + if (!getAspectRatioCBName().empty()) + { + getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1)); + } updateControls(LLSD()); + + mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>(); return TRUE; } @@ -76,13 +92,13 @@ void LLPanelSnapshot::onOpen(const LLSD& key) // e.g. attempt to send a large BMP image by email. if (old_format != new_format) { - LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); + getParentByType<LLFloater>()->notify(LLSD().with("image-format-change", true)); } } -LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const +LLSnapshotModel::ESnapshotFormat LLPanelSnapshot::getImageFormat() const { - return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; + return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } void LLPanelSnapshot::enableControls(BOOL enable) @@ -92,27 +108,32 @@ void LLPanelSnapshot::enableControls(BOOL enable) LLSpinCtrl* LLPanelSnapshot::getWidthSpinner() { + llassert(!getWidthSpinnerName().empty()); return getChild<LLSpinCtrl>(getWidthSpinnerName()); } LLSpinCtrl* LLPanelSnapshot::getHeightSpinner() { + llassert(!getHeightSpinnerName().empty()); return getChild<LLSpinCtrl>(getHeightSpinnerName()); } S32 LLPanelSnapshot::getTypedPreviewWidth() const { + llassert(!getWidthSpinnerName().empty()); return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); } S32 LLPanelSnapshot::getTypedPreviewHeight() const { - return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); + llassert(!getHeightSpinnerName().empty()); + return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); } void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable) { - getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); + llassert(!getAspectRatioCBName().empty()); + getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); } LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer() @@ -171,14 +192,17 @@ void LLPanelSnapshot::goBack() void LLPanelSnapshot::cancel() { goBack(); - LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-ready", true)); + getParentByType<LLFloater>()->notify(LLSD().with("set-ready", true)); } void LLPanelSnapshot::onCustomResolutionCommit() { LLSD info; - LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(getWidthSpinnerName()); - LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(getHeightSpinnerName()); + std::string widthSpinnerName = getWidthSpinnerName(); + std::string heightSpinnerName = getHeightSpinnerName(); + llassert(!widthSpinnerName.empty() && !heightSpinnerName.empty()); + LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(widthSpinnerName); + LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(heightSpinnerName); if (getName() == "panel_snapshot_inventory") { S32 width = widthSpinner->getValue().asInteger(); @@ -197,17 +221,22 @@ void LLPanelSnapshot::onCustomResolutionCommit() info["w"] = widthSpinner->getValue().asInteger(); info["h"] = heightSpinner->getValue().asInteger(); } - LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); + getParentByType<LLFloater>()->notify(LLSD().with("custom-res-change", info)); } void LLPanelSnapshot::onResolutionComboCommit(LLUICtrl* ctrl) { LLSD info; info["combo-res-change"]["control-name"] = ctrl->getName(); - LLFloaterSnapshot::getInstance()->notify(info); + getParentByType<LLFloater>()->notify(info); } void LLPanelSnapshot::onKeepAspectRatioCommit(LLUICtrl* ctrl) { - LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); + getParentByType<LLFloater>()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} + +LLSnapshotModel::ESnapshotType LLPanelSnapshot::getSnapshotType() +{ + return LLSnapshotModel::SNAPSHOT_WEB; } diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h index 42ad798d60..55273797cc 100644 --- a/indra/newview/llpanelsnapshot.h +++ b/indra/newview/llpanelsnapshot.h @@ -27,9 +27,13 @@ #ifndef LL_LLPANELSNAPSHOT_H #define LL_LLPANELSNAPSHOT_H -#include "llfloatersnapshot.h" +//#include "llfloatersnapshot.h" +#include "llpanel.h" +#include "llsnapshotmodel.h" +class LLSpinCtrl; class LLSideTrayPanelContainer; +class LLFloaterSnapshotBase; /** * Snapshot panel base class. @@ -37,6 +41,8 @@ class LLSideTrayPanelContainer; class LLPanelSnapshot: public LLPanel { public: + LLPanelSnapshot(); + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); @@ -51,7 +57,8 @@ public: virtual LLSpinCtrl* getWidthSpinner(); virtual LLSpinCtrl* getHeightSpinner(); virtual void enableAspectRatioCheckbox(BOOL enable); - virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; + virtual LLSnapshotModel::ESnapshotFormat getImageFormat() const; + virtual LLSnapshotModel::ESnapshotType getSnapshotType(); virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings void enableControls(BOOL enable); @@ -59,12 +66,14 @@ protected: LLSideTrayPanelContainer* getParentContainer(); void updateImageQualityLevel(); void goBack(); ///< Switch to the default (Snapshot Options) panel - void cancel(); + virtual void cancel(); // common UI callbacks void onCustomResolutionCommit(); void onResolutionComboCommit(LLUICtrl* ctrl); void onKeepAspectRatioCommit(LLUICtrl* ctrl); + + LLFloaterSnapshotBase* mSnapshotFloater; }; #endif // LL_LLPANELSNAPSHOT_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index a2d1752c6a..b2952834fb 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -33,6 +33,7 @@ #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model #include "llpanelsnapshot.h" +#include "llsnapshotlivepreview.h" #include "llviewercontrol.h" // gSavedSettings #include "llstatusbar.h" // can_afford_transaction() #include "llnotificationsutil.h" @@ -40,8 +41,22 @@ /** * The panel provides UI for saving snapshot as an inventory texture. */ +class LLPanelSnapshotInventoryBase + : public LLPanelSnapshot +{ + LOG_CLASS(LLPanelSnapshotInventoryBase); + +public: + LLPanelSnapshotInventoryBase(); + + /*virtual*/ BOOL postBuild(); +protected: + void onSend(); + /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); +}; + class LLPanelSnapshotInventory -: public LLPanelSnapshot + : public LLPanelSnapshotInventoryBase { LOG_CLASS(LLPanelSnapshotInventory); @@ -60,10 +75,46 @@ private: /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; } /*virtual*/ void updateControls(const LLSD& info); - void onSend(); }; -static LLPanelInjector<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory"); +class LLPanelOutfitSnapshotInventory + : public LLPanelSnapshotInventoryBase +{ + LOG_CLASS(LLPanelOutfitSnapshotInventory); + +public: + LLPanelOutfitSnapshotInventory(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + /*virtual*/ std::string getWidthSpinnerName() const { return ""; } + /*virtual*/ std::string getHeightSpinnerName() const { return ""; } + /*virtual*/ std::string getAspectRatioCBName() const { return ""; } + /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; } + /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; } + /*virtual*/ void updateControls(const LLSD& info); + + /*virtual*/ void cancel(); +}; + +static LLPanelInjector<LLPanelSnapshotInventory> panel_class1("llpanelsnapshotinventory"); + +static LLPanelInjector<LLPanelOutfitSnapshotInventory> panel_class2("llpaneloutfitsnapshotinventory"); + +LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase() +{ +} + +BOOL LLPanelSnapshotInventoryBase::postBuild() +{ + return LLPanelSnapshot::postBuild(); +} + +LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType() +{ + return LLSnapshotModel::SNAPSHOT_TEXTURE; +} LLPanelSnapshotInventory::LLPanelSnapshotInventory() { @@ -78,7 +129,7 @@ BOOL LLPanelSnapshotInventory::postBuild() getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE); getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1)); - return LLPanelSnapshot::postBuild(); + return LLPanelSnapshotInventoryBase::postBuild(); } // virtual @@ -102,19 +153,59 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected); } -void LLPanelSnapshotInventory::onSend() +void LLPanelSnapshotInventoryBase::onSend() { S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); if (can_afford_transaction(expected_upload_cost)) { - LLFloaterSnapshot::saveTexture(); - LLFloaterSnapshot::postSave(); + if (mSnapshotFloater) + { + mSnapshotFloater->saveTexture(); + mSnapshotFloater->postSave(); + } } else { LLSD args; args["COST"] = llformat("%d", expected_upload_cost); LLNotificationsUtil::add("ErrorPhotoCannotAfford", args); - LLFloaterSnapshot::inventorySaveFailed(); + if (mSnapshotFloater) + { + mSnapshotFloater->inventorySaveFailed(); + } + } +} + +LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory() +{ + mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this)); + mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this)); +} + +// virtual +BOOL LLPanelOutfitSnapshotInventory::postBuild() +{ + return LLPanelSnapshotInventoryBase::postBuild(); +} + +// virtual +void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key) +{ + getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); + LLPanelSnapshot::onOpen(key); +} + +// virtual +void LLPanelOutfitSnapshotInventory::updateControls(const LLSD& info) +{ + const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; + getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); +} + +void LLPanelOutfitSnapshotInventory::cancel() +{ + if (mSnapshotFloater) + { + mSnapshotFloater->closeFloater(); } } diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 01dfdc4ece..3652c10586 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -33,6 +33,7 @@ #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model #include "llpanelsnapshot.h" +#include "llsnapshotlivepreview.h" #include "llviewercontrol.h" // gSavedSettings #include "llviewerwindow.h" @@ -55,7 +56,8 @@ private: /*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; } /*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; } /*virtual*/ std::string getImageSizePanelName() const { return "local_image_size_lp"; } - /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; + /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const; + /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); /*virtual*/ void updateControls(const LLSD& info); S32 mLocalFormat; @@ -94,23 +96,23 @@ void LLPanelSnapshotLocal::onOpen(const LLSD& key) } // virtual -LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const +LLSnapshotModel::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const { - LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + LLSnapshotModel::ESnapshotFormat fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG; LLComboBox* local_format_combo = getChild<LLComboBox>("local_format_combo"); const std::string id = local_format_combo->getValue().asString(); if (id == "PNG") { - fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG; } else if (id == "JPEG") { - fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; + fmt = LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } else if (id == "BMP") { - fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP; + fmt = LLSnapshotModel::SNAPSHOT_FORMAT_BMP; } return fmt; @@ -119,11 +121,11 @@ LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const // virtual void LLPanelSnapshotLocal::updateControls(const LLSD& info) { - LLFloaterSnapshot::ESnapshotFormat fmt = - (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); + LLSnapshotModel::ESnapshotFormat fmt = + (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt); - const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + const bool show_quality_ctrls = (fmt == LLSnapshotModel::SNAPSHOT_FORMAT_JPEG); getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls); getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls); @@ -162,10 +164,10 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl) LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); floater->notify(LLSD().with("set-working", true)); - BOOL saved = LLFloaterSnapshot::saveLocal(); + BOOL saved = floater->saveLocal(); if (saved) { - LLFloaterSnapshot::postSave(); + mSnapshotFloater->postSave(); goBack(); floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); } @@ -174,3 +176,8 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl) cancel(); } } + +LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType() +{ + return LLSnapshotModel::SNAPSHOT_LOCAL; +} diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 0fc9ceec83..269f16c5e4 100644 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -62,6 +62,8 @@ private: void onSendToFacebook(); void onSendToTwitter(); void onSendToFlickr(); + + LLFloaterSnapshotBase* mSnapshotFloater; }; static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions"); @@ -86,6 +88,7 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions() // virtual BOOL LLPanelSnapshotOptions::postBuild() { + mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>(); return LLPanel::postBuild(); } @@ -112,7 +115,7 @@ void LLPanelSnapshotOptions::openPanel(const std::string& panel_name) parent->openPanel(panel_name); parent->getCurrentPanel()->onOpen(LLSD()); - LLFloaterSnapshot::postPanelSwitch(); + mSnapshotFloater->postPanelSwitch(); } void LLPanelSnapshotOptions::onSaveToProfile() diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp index e4f39aac04..be8bde09f8 100644 --- a/indra/newview/llpanelsnapshotpostcard.cpp +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -38,6 +38,7 @@ #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model #include "llpanelsnapshot.h" #include "llpostcard.h" +#include "llsnapshotlivepreview.h" #include "llviewercontrol.h" // gSavedSettings #include "llviewerwindow.h" #include "llviewerregion.h" @@ -64,12 +65,13 @@ private: /*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; } /*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; } /*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; } - /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; } + /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } + /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); /*virtual*/ void updateControls(const LLSD& info); bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); - static void sendPostcardFinished(LLSD result); - void sendPostcard(); + static void sendPostcardFinished(LLSD result); + void sendPostcard(); void onMsgFormFocusRecieved(); void onFormatComboCommit(LLUICtrl* ctrl); @@ -93,13 +95,6 @@ LLPanelSnapshotPostcard::LLPanelSnapshotPostcard() // virtual BOOL LLPanelSnapshotPostcard::postBuild() { - // pick up the user's up-to-date email address - gAgent.sendAgentUserInfoRequest(); - - std::string name_string; - LLAgentUI::buildFullname(name_string); - getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); - // For the first time a user focuses to .the msg box, all text will be selected. getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this)); @@ -113,6 +108,16 @@ BOOL LLPanelSnapshotPostcard::postBuild() // virtual void LLPanelSnapshotPostcard::onOpen(const LLSD& key) { + // pick up the user's up-to-date email address + if (mAgentEmail.empty()) + { + gAgent.sendAgentUserInfoRequest(); + + std::string name_string; + LLAgentUI::buildFullname(name_string); + getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); + } + LLPanelSnapshot::onOpen(key); } @@ -190,8 +195,8 @@ void LLPanelSnapshotPostcard::sendPostcard() getChild<LLUICtrl>("to_form")->getValue().asString(), getChild<LLUICtrl>("subject_form")->getValue().asString(), getChild<LLUICtrl>("msg_form")->getValue().asString(), - LLFloaterSnapshot::getPosTakenGlobal(), - LLFloaterSnapshot::getImageData(), + mSnapshotFloater->getPosTakenGlobal(), + mSnapshotFloater->getImageData(), boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4))); LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); @@ -205,7 +210,7 @@ void LLPanelSnapshotPostcard::sendPostcard() // Give user feedback of the event. gViewerWindow->playSnapshotAnimAndSound(); - LLFloaterSnapshot::postSave(); + mSnapshotFloater->postSave(); } void LLPanelSnapshotPostcard::onMsgFormFocusRecieved() @@ -264,3 +269,8 @@ void LLPanelSnapshotPostcard::onSend() // Send postcard. sendPostcard(); } + +LLSnapshotModel::ESnapshotType LLPanelSnapshotPostcard::getSnapshotType() +{ + return LLSnapshotModel::SNAPSHOT_POSTCARD; +} diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp index 8949eb73eb..38dec78030 100644 --- a/indra/newview/llpanelsnapshotprofile.cpp +++ b/indra/newview/llpanelsnapshotprofile.cpp @@ -58,7 +58,7 @@ private: /*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; } /*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; } /*virtual*/ std::string getImageSizePanelName() const { return "profile_image_size_lp"; } - /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; } + /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; } /*virtual*/ void updateControls(const LLSD& info); void onSend(); @@ -96,6 +96,6 @@ void LLPanelSnapshotProfile::onSend() std::string caption = getChild<LLUICtrl>("caption")->getValue().asString(); bool add_location = getChild<LLUICtrl>("add_location_cb")->getValue().asBoolean(); - LLWebProfile::uploadImage(LLFloaterSnapshot::getImageData(), caption, add_location); - LLFloaterSnapshot::postSave(); + LLWebProfile::uploadImage(mSnapshotFloater->getImageData(), caption, add_location); + mSnapshotFloater->postSave(); } diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index d0353259a5..796372ba04 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -30,13 +30,19 @@ #include "lltoggleablemenu.h" +#include "llagent.h" +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" #include "llappearancemgr.h" #include "llfloatersidepanelcontainer.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llmenubutton.h" +#include "llscrolllistctrl.h" #include "llviewermenu.h" +#include "llviewerregion.h" #include "llwearableitemslist.h" #include "llsdserialize.h" #include "llclipboard.h" @@ -146,11 +152,47 @@ protected: menu->setItemVisible("detach", allow_detach); menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach); menu->setItemVisible("show_original", mUUIDs.size() == 1); + menu->setItemVisible("edit_item", FALSE); } }; ////////////////////////////////////////////////////////////////////////// +class LLTempAttachmentsContextMenu : public LLListContextMenu +{ +public: + LLTempAttachmentsContextMenu(LLPanelWearing* panel_wearing) + : mPanelWearing(panel_wearing) + {} +protected: + /* virtual */ LLContextMenu* createMenu() + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + + registrar.add("Wearing.EditItem", boost::bind(&LLPanelWearing::onEditAttachment, mPanelWearing)); + registrar.add("Wearing.Detach", boost::bind(&LLPanelWearing::onRemoveAttachment, mPanelWearing)); + LLContextMenu* menu = createFromFile("menu_wearing_tab.xml"); + + updateMenuItemsVisibility(menu); + + return menu; + } + + void updateMenuItemsVisibility(LLContextMenu* menu) + { + menu->setItemVisible("take_off", FALSE); + menu->setItemVisible("detach", TRUE); + menu->setItemVisible("edit_outfit_separator", TRUE); + menu->setItemVisible("show_original", FALSE); + menu->setItemVisible("edit_item", TRUE); + menu->setItemVisible("edit", FALSE); + } + + LLPanelWearing* mPanelWearing; +}; + +////////////////////////////////////////////////////////////////////////// + std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null; static LLPanelInjector<LLPanelWearing> t_panel_wearing("panel_wearing"); @@ -159,30 +201,47 @@ LLPanelWearing::LLPanelWearing() : LLPanelAppearanceTab() , mCOFItemsList(NULL) , mIsInitialized(false) + , mAttachmentsChangedConnection() { mCategoriesObserver = new LLInventoryCategoriesObserver(); mGearMenu = new LLWearingGearMenu(this); mContextMenu = new LLWearingContextMenu(); + mAttachmentsMenu = new LLTempAttachmentsContextMenu(this); } LLPanelWearing::~LLPanelWearing() { delete mGearMenu; delete mContextMenu; + delete mAttachmentsMenu; if (gInventory.containsObserver(mCategoriesObserver)) { gInventory.removeObserver(mCategoriesObserver); } delete mCategoriesObserver; + + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } } BOOL LLPanelWearing::postBuild() { + mAccordionCtrl = getChild<LLAccordionCtrl>("wearables_accordion"); + mWearablesTab = getChild<LLAccordionCtrlTab>("tab_wearables"); + mAttachmentsTab = getChild<LLAccordionCtrlTab>("tab_temp_attachments"); + mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLPanelWearing::onAccordionTabStateChanged, this)); + mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list"); mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3)); + mTempItemsList = getChild<LLScrollListCtrl>("temp_attachments_list"); + mTempItemsList->setFgUnselectedColor(LLColor4::white); + mTempItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onTempAttachmentsListRightClick, this, _1, _2, _3)); + LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); menu_gear_btn->setMenu(mGearMenu->getMenu()); @@ -223,6 +282,44 @@ void LLPanelWearing::onOpen(const LLSD& /*info*/) } } +void LLPanelWearing::draw() +{ + if (mUpdateTimer.getStarted() && (mUpdateTimer.getElapsedTimeF32() > 0.1)) + { + mUpdateTimer.stop(); + updateAttachmentsList(); + } + LLPanel::draw(); +} + +void LLPanelWearing::onAccordionTabStateChanged() +{ + if(mAttachmentsTab->isExpanded()) + { + startUpdateTimer(); + mAttachmentsChangedConnection = LLAppearanceMgr::instance().setAttachmentsChangedCallback(boost::bind(&LLPanelWearing::startUpdateTimer, this)); + } + else + { + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } + } +} + +void LLPanelWearing::startUpdateTimer() +{ + if (!mUpdateTimer.getStarted()) + { + mUpdateTimer.start(); + } + else + { + mUpdateTimer.reset(); + } +} + // virtual void LLPanelWearing::setFilterSubString(const std::string& string) { @@ -251,6 +348,124 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata) return false; } +void LLPanelWearing::updateAttachmentsList() +{ + std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments(); + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + if(!attachs.empty()) + { + if(!populateAttachmentsList()) + { + requestAttachmentDetails(); + } + } + else + { + std::string no_attachments = getString("no_attachments"); + LLSD row; + row["columns"][0]["column"] = "text"; + row["columns"][0]["value"] = no_attachments; + row["columns"][0]["font"] = "SansSerifBold"; + mTempItemsList->addElement(row); + } +} + +bool LLPanelWearing::populateAttachmentsList(bool update) +{ + bool populated = true; + if(mTempItemsList) + { + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments(); + + std::string icon_name = LLInventoryIcon::getIconName(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT); + for (std::vector<LLViewerObject*>::iterator iter = attachs.begin(); + iter != attachs.end(); ++iter) + { + LLViewerObject *attachment = *iter; + LLSD row; + row["id"] = attachment->getID(); + row["columns"][0]["column"] = "icon"; + row["columns"][0]["type"] = "icon"; + row["columns"][0]["value"] = icon_name; + row["columns"][1]["column"] = "text"; + if(mObjectNames.count(attachment->getID()) && !mObjectNames[attachment->getID()].empty()) + { + row["columns"][1]["value"] = mObjectNames[attachment->getID()]; + } + else if(update) + { + row["columns"][1]["value"] = attachment->getID(); + populated = false; + } + else + { + row["columns"][1]["value"] = "Loading..."; + populated = false; + } + mTempItemsList->addElement(row); + mAttachmentsMap[attachment->getID()] = attachment; + } + } + return populated; +} + +void LLPanelWearing::requestAttachmentDetails() +{ + LLSD body; + std::string url = gAgent.getRegion()->getCapability("AttachmentResources"); + if (!url.empty()) + { + LLCoros::instance().launch("LLPanelWearing::getAttachmentLimitsCoro", + boost::bind(&LLPanelWearing::getAttachmentLimitsCoro, this, url)); + } +} + +void LLPanelWearing::getAttachmentLimitsCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL; + return; + } + + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + setAttachmentDetails(result); +} + + +void LLPanelWearing::setAttachmentDetails(LLSD content) +{ + mObjectNames.clear(); + S32 number_attachments = content["attachments"].size(); + for(int i = 0; i < number_attachments; i++) + { + S32 number_objects = content["attachments"][i]["objects"].size(); + for(int j = 0; j < number_objects; j++) + { + LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID(); + std::string name = content["attachments"][i]["objects"][j]["name"].asString(); + mObjectNames[task_id] = name; + } + } + if(!mObjectNames.empty()) + { + populateAttachmentsList(true); + } +} + boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb) { if (!mCOFItemsList) return boost::signals2::connection(); @@ -270,6 +485,20 @@ void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) mContextMenu->show(ctrl, selected_uuids, x, y); } +void LLPanelWearing::onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) +{ + LLScrollListCtrl* list = dynamic_cast<LLScrollListCtrl*>(ctrl); + if (!list) return; + list->selectItemAt(x, y, MASK_NONE); + uuid_vec_t selected_uuids; + + if(list->getCurrentID().notNull()) + { + selected_uuids.push_back(list->getCurrentID()); + mAttachmentsMenu->show(ctrl, selected_uuids, x, y); + } +} + bool LLPanelWearing::hasItemSelected() { return mCOFItemsList->getSelectedItem() != NULL; @@ -280,6 +509,28 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const mCOFItemsList->getSelectedUUIDs(selected_uuids); } +void LLPanelWearing::onEditAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + handle_object_edit(); + } +} + +void LLPanelWearing::onRemoveAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + LLSelectMgr::getInstance()->sendDropAttachment(); + } +} + void LLPanelWearing::copyToClipboard() { std::string text; diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index 9a212b3cca..c5cb79092a 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -31,9 +31,14 @@ // newview #include "llpanelappearancetab.h" +#include "llselectmgr.h" +#include "lltimer.h" +class LLAccordionCtrl; +class LLAccordionCtrlTab; class LLInventoryCategoriesObserver; class LLListContextMenu; +class LLScrollListCtrl; class LLWearableItemsList; class LLWearingGearMenu; @@ -52,6 +57,8 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(const LLSD& info); /*virtual*/ void setFilterSubString(const std::string& string); @@ -62,17 +69,43 @@ public: /*virtual*/ void copyToClipboard(); + void startUpdateTimer(); + void updateAttachmentsList(); + boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb); bool hasItemSelected(); + bool populateAttachmentsList(bool update = false); + void onAccordionTabStateChanged(); + void setAttachmentDetails(LLSD content); + void requestAttachmentDetails(); + void onEditAttachment(); + void onRemoveAttachment(); + private: void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + void onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + + void getAttachmentLimitsCoro(std::string url); LLInventoryCategoriesObserver* mCategoriesObserver; LLWearableItemsList* mCOFItemsList; + LLScrollListCtrl* mTempItemsList; LLWearingGearMenu* mGearMenu; LLListContextMenu* mContextMenu; + LLListContextMenu* mAttachmentsMenu; + + LLAccordionCtrlTab* mWearablesTab; + LLAccordionCtrlTab* mAttachmentsTab; + LLAccordionCtrl* mAccordionCtrl; + + std::map<LLUUID, LLViewerObject*> mAttachmentsMap; + + std::map<LLUUID, std::string> mObjectNames; + + boost::signals2::connection mAttachmentsChangedConnection; + LLFrameTimer mUpdateTimer; bool mIsInitialized; }; diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp index b886e46765..eb7b95552e 100644 --- a/indra/newview/llpathfindinglinksetlist.cpp +++ b/indra/newview/llpathfindinglinksetlist.cpp @@ -204,7 +204,10 @@ void LLPathfindingLinksetList::parseLinksetListData(const LLSD& pLinksetListData { const std::string& uuid(linksetDataIter->first); const LLSD& linksetData = linksetDataIter->second; - LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData)); - objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr)); + if(linksetData.size() != 0) + { + LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData)); + objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr)); + } } } diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index 9957039f72..836f63bffa 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -104,8 +104,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam if (found) { std::string path = gDirUtilp->add(dir, file); - std::string name = gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true); - + std::string name = LLURI::unescape(gDirUtilp->getBaseFileName(path, /*strip_exten = */ true)); LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL; if (PRESETS_DEFAULT != name) diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index ba9845ef04..510d91839d 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -437,6 +437,23 @@ void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, } } +void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId) +{ + + LLSD floater_key; + floater_key["taskid"] = taskId; + floater_key["itemid"] = itemId; + LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", floater_key); + if (nc) + { + if (nc->hasEmbeddedInventory()) + { + gVFS->removeFile(newAssetId, LLAssetType::AT_NOTECARD); + } + nc->setAssetId(newAssetId); + nc->refreshFromInventory(); + } +} bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) { @@ -485,7 +502,7 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) else if (!mObjectUUID.isNull() && !task_url.empty()) { uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, - boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _3, LLUUID::null))); + boost::bind(&LLPreviewNotecard::finishTaskUpload, _1, _3, mObjectUUID))); url = task_url; } diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index ba571995f6..017c4485ba 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -96,6 +96,7 @@ protected: bool handleConfirmDeleteDialog(const LLSD& notification, const LLSD& response); static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId); + static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId); protected: LLViewerTextEditor* mEditor; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 5b1b356597..f28ffce602 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -375,7 +375,8 @@ LLScriptEdCore::LLScriptEdCore( mLiveFile(NULL), mLive(live), mContainer(container), - mHasScriptData(FALSE) + mHasScriptData(FALSE), + mScriptRemoved(FALSE) { setFollowsAll(); setBorderVisible(FALSE); @@ -666,7 +667,7 @@ bool LLScriptEdCore::hasChanged() void LLScriptEdCore::draw() { BOOL script_changed = hasChanged(); - getChildView("Save_btn")->setEnabled(script_changed); + getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved); if( mEditor->hasFocus() ) { @@ -840,7 +841,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string) BOOL LLScriptEdCore::canClose() { - if(mForceClose || !hasChanged()) + if(mForceClose || !hasChanged() || mScriptRemoved) { return TRUE; } @@ -1511,6 +1512,17 @@ BOOL LLPreviewLSL::postBuild() return LLPreview::postBuild(); } +void LLPreviewLSL::draw() +{ + const LLInventoryItem* item = getItem(); + if(!item) + { + setTitle(LLTrans::getString("ScriptWasDeleted")); + mScriptEd->setItemRemoved(TRUE); + } + + LLPreview::draw(); +} // virtual void LLPreviewLSL::callbackLSLCompileSucceeded() { diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index a8c6a6eeeb..6b31125641 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -119,6 +119,8 @@ public: void setScriptName(const std::string& name){mScriptName = name;}; + void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;}; + private: void onBtnHelp(); void onBtnDynamicHelp(); @@ -163,6 +165,7 @@ private: BOOL mHasScriptData; LLLiveLSLFile* mLiveFile; LLUUID mAssociatedExperience; + BOOL mScriptRemoved; LLScriptEdContainer* mContainer; // parent view @@ -198,6 +201,7 @@ public: /*virtual*/ BOOL postBuild(); protected: + virtual void draw(); virtual BOOL canClose(); void closeIfNeeded(); diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 4f9f83b6f2..72d7cf1e45 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -29,6 +29,8 @@ #include "llviewerprecompiledheaders.h" #include "llsecapi.h" #include "llsechandler_basic.h" +#include "llexception.h" +#include "stringize.h" #include <openssl/evp.h> #include <openssl/err.h> #include <map> @@ -64,12 +66,12 @@ void initializeSecHandler() } catch (LLProtectedDataException e) { - exception_msg = e.getMessage(); + exception_msg = e.what(); } } if (!exception_msg.empty()) // an exception was thrown. { - throw LLProtectedDataException(exception_msg.c_str()); + LLTHROW(LLProtectedDataException(exception_msg)); } } @@ -101,6 +103,7 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred) LLSD LLCredential::getLoginParams() { LLSD result = LLSD::emptyMap(); + std::string username; try { if (mIdentifier["type"].asString() == "agent") @@ -109,17 +112,19 @@ LLSD LLCredential::getLoginParams() result["passwd"] = "$1$" + mAuthenticator["secret"].asString(); result["first"] = mIdentifier["first_name"]; result["last"] = mIdentifier["last_name"]; - + username = result["first"].asString() + " " + result["last"].asString(); } else if (mIdentifier["type"].asString() == "account") { result["username"] = mIdentifier["account_name"]; result["passwd"] = mAuthenticator["secret"]; - + username = result["username"].asString(); } } catch (...) { + // nat 2016-08-18: not clear what exceptions the above COULD throw?! + LOG_UNHANDLED_EXCEPTION(STRINGIZE("for '" << username << "'")); // we could have corrupt data, so simply return a null login param if so LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL; } diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 6fe3ee31cf..6af5a28fa5 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -32,6 +32,7 @@ #include <openssl/x509.h> #include <ostream> #include "llpointer.h" +#include "llexception.h" #ifdef LL_WINDOWS #pragma warning(disable:4250) @@ -116,17 +117,13 @@ -class LLProtectedDataException +struct LLProtectedDataException: public LLException { -public: - LLProtectedDataException(const char *msg) + LLProtectedDataException(const std::string& msg): + LLException(msg) { - LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL; - mMsg = (std::string)msg; + LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL; } - std::string getMessage() { return mMsg; } -protected: - std::string mMsg; }; // class LLCertificate @@ -334,22 +331,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred); // All error handling is via exceptions. -class LLCertException +class LLCertException: public LLException { public: - LLCertException(LLPointer<LLCertificate> cert, const char* msg) + LLCertException(LLPointer<LLCertificate> cert, const std::string& msg): + LLException(msg) { mCert = cert; - LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL; - mMsg = (std::string)msg; + LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL; } - LLPointer<LLCertificate> getCert() { return mCert; } - std::string getMessage() { return mMsg; } + virtual ~LLCertException() throw() {} + LLPointer<LLCertificate> getCert() const { return mCert; } protected: LLPointer<LLCertificate> mCert; - std::string mMsg; }; class LLInvalidCertificate : public LLCertException @@ -358,6 +354,7 @@ public: LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid") { } + virtual ~LLInvalidCertificate() throw() {} protected: }; @@ -367,6 +364,7 @@ public: LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted") { } + virtual ~LLCertValidationTrustException() throw() {} protected: }; @@ -378,7 +376,7 @@ public: { mHostname = hostname; } - + virtual ~LLCertValidationHostnameException() throw() {} std::string getHostname() { return mHostname; } protected: std::string mHostname; @@ -392,6 +390,7 @@ public: { mTime = current_time; } + virtual ~LLCertValidationExpirationException() throw() {} LLDate GetTime() { return mTime; } protected: LLDate mTime; @@ -403,6 +402,7 @@ public: LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage") { } + virtual ~LLCertKeyUsageValidationException() throw() {} protected: }; @@ -412,6 +412,7 @@ public: LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints") { } + virtual ~LLCertBasicConstraintsValidationException() throw() {} protected: }; @@ -421,6 +422,7 @@ public: LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature") { } + virtual ~LLCertValidationInvalidSignatureException() throw() {} protected: }; diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 40516f9bbb..d6fb801cc0 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,6 +35,8 @@ #include "llfile.h" #include "lldir.h" #include "llviewercontrol.h" +#include "llexception.h" +#include "stringize.h" #include <vector> #include <ios> #include <openssl/ossl_typ.h> @@ -72,14 +74,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) if(pem_bio == NULL) { LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; - throw LLInvalidCertificate(this); + LLTHROW(LLInvalidCertificate(this)); } mCert = NULL; PEM_read_bio_X509(pem_bio, &mCert, 0, NULL); BIO_free(pem_bio); if (!mCert) { - throw LLInvalidCertificate(this); + LLTHROW(LLInvalidCertificate(this)); } } @@ -88,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert) { if (!pCert || !pCert->cert_info) { - throw LLInvalidCertificate(this); + LLTHROW(LLInvalidCertificate(this)); } mCert = X509_dup(pCert); } @@ -617,7 +619,7 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename) } catch (...) { - LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL; + LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file"); } X509_free(cert_x509); cert_x509 = NULL; @@ -873,22 +875,22 @@ void _validateCert(int validation_policy, // check basic properties exist in the cert if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING)) { - throw LLCertException(cert, "Cert doesn't have a Subject Name"); + LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name")); } if(!current_cert_info.has(CERT_ISSUER_NAME_STRING)) { - throw LLCertException(cert, "Cert doesn't have an Issuer Name"); + LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name")); } // check basic properties exist in the cert if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO)) { - throw LLCertException(cert, "Cert doesn't have an expiration period"); + LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period")); } if (!current_cert_info.has(CERT_SHA1_DIGEST)) { - throw LLCertException(cert, "No SHA1 digest"); + LLTHROW(LLCertException(cert, "No SHA1 digest")); } if (validation_policy & VALIDATION_POLICY_TIME) @@ -903,7 +905,7 @@ void _validateCert(int validation_policy, if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) || (validation_date > current_cert_info[CERT_VALID_TO].asDate())) { - throw LLCertValidationExpirationException(cert, validation_date); + LLTHROW(LLCertValidationExpirationException(cert, validation_date)); } } if (validation_policy & VALIDATION_POLICY_SSL_KU) @@ -914,14 +916,14 @@ void _validateCert(int validation_policy, !(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT))))) { - throw LLCertKeyUsageValidationException(cert); + LLTHROW(LLCertKeyUsageValidationException(cert)); } // only validate EKU if the cert has it if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() && (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE], LLSD((std::string)CERT_EKU_SERVER_AUTH)))) { - throw LLCertKeyUsageValidationException(cert); + LLTHROW(LLCertKeyUsageValidationException(cert)); } } if (validation_policy & VALIDATION_POLICY_CA_KU) @@ -930,7 +932,7 @@ void _validateCert(int validation_policy, (!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], (std::string)CERT_KU_CERT_SIGN))) { - throw LLCertKeyUsageValidationException(cert); + LLTHROW(LLCertKeyUsageValidationException(cert)); } } @@ -942,13 +944,13 @@ void _validateCert(int validation_policy, if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) || !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA]) { - throw LLCertBasicConstraintsValidationException(cert); + LLTHROW(LLCertBasicConstraintsValidationException(cert)); } if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) && ((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) && (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger()))) { - throw LLCertBasicConstraintsValidationException(cert); + LLTHROW(LLCertBasicConstraintsValidationException(cert)); } } } @@ -1018,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(cert_chain->size() < 1) { - throw LLCertException(NULL, "No certs in chain"); + LLTHROW(LLCertException(NULL, "No certs in chain")); } iterator current_cert = cert_chain->begin(); LLSD current_cert_info; @@ -1033,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy, (*current_cert)->getLLSD(current_cert_info); if(!validation_params.has(CERT_HOSTNAME)) { - throw LLCertException((*current_cert), "No hostname passed in for validation"); + LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation")); } if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN)) { - throw LLInvalidCertificate((*current_cert)); + LLTHROW(LLInvalidCertificate((*current_cert))); } LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << @@ -1054,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy, X509* cert_x509 = (*current_cert)->getOpenSSLX509(); if(!cert_x509) { - throw LLInvalidCertificate((*current_cert)); + LLTHROW(LLInvalidCertificate((*current_cert))); } std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); X509_free( cert_x509 ); @@ -1075,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if((validation_date < cache_entry->second.first) || (validation_date > cache_entry->second.second)) { - throw LLCertValidationExpirationException((*current_cert), validation_date); + LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date)); } } // successfully found in cache @@ -1107,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*current_cert), previous_cert)) { - throw LLCertValidationInvalidSignatureException(previous_cert); + LLTHROW(LLCertValidationInvalidSignatureException(previous_cert)); } } _validateCert(local_validation_policy, @@ -1156,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*found_store_cert), (*current_cert))) { - throw LLCertValidationInvalidSignatureException(*current_cert); + LLTHROW(LLCertValidationInvalidSignatureException(*current_cert)); } // successfully validated. mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time); @@ -1173,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if (validation_policy & VALIDATION_POLICY_TRUSTED) { // we reached the end without finding a trusted cert. - throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]); + LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1])); } mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time); @@ -1261,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData() protected_data_stream.read((char *)salt, STORE_SALT_SIZE); if (protected_data_stream.gcount() < STORE_SALT_SIZE) { - throw LLProtectedDataException("Config file too short."); + LLTHROW(LLProtectedDataException("Config file too short.")); } cipher.decrypt(salt, STORE_SALT_SIZE); @@ -1301,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData() if (parser->parse(parse_stream, mProtectedDataMap, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) { - throw LLProtectedDataException("Config file cannot be decrypted."); + LLTHROW(LLProtectedDataException("Config file cannot be decrypted.")); } } } @@ -1364,7 +1366,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() } catch (...) { - LL_WARNS() << "LLProtectedDataException(Error writing Protected Data Store)" << LL_ENDL; + LOG_UNHANDLED_EXCEPTION("LLProtectedDataException(Error writing Protected Data Store)"); // it's good practice to clean up any secure information on error // (even though this file isn't really secure. Perhaps in the future // it may be, however. @@ -1372,39 +1374,39 @@ void LLSecAPIBasicHandler::_writeProtectedData() // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Error writing Protected Data Store"); + //LLTHROW(LLProtectedDataException("Error writing Protected Data Store")); } - try - { - // move the temporary file to the specified file location. - if((( (LLFile::isfile(mProtectedDataFilename) != 0) - && (LLFile::remove(mProtectedDataFilename) != 0))) - || (LLFile::rename(tmp_filename, mProtectedDataFilename))) - { - LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL; - LLFile::remove(tmp_filename); + try + { + // move the temporary file to the specified file location. + if((( (LLFile::isfile(mProtectedDataFilename) != 0) + && (LLFile::remove(mProtectedDataFilename) != 0))) + || (LLFile::rename(tmp_filename, mProtectedDataFilename))) + { + LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL; + LLFile::remove(tmp_filename); - // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() - // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Could not overwrite protected data store"); - } + // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() + // Decided throwing an exception here was overkill until we figure out why this happens + //LLTHROW(LLProtectedDataException("Could not overwrite protected data store")); + } } catch (...) { - LL_WARNS() << "LLProtectedDataException(Error renaming '" << tmp_filename - << "' to '" << mProtectedDataFilename << "')" << LL_ENDL; + LOG_UNHANDLED_EXCEPTION(STRINGIZE("renaming '" << tmp_filename << "' to '" + << mProtectedDataFilename << "'")); // it's good practice to clean up any secure information on error // (even though this file isn't really secure. Perhaps in the future - // it may be, however. + // it may be, however). LLFile::remove(tmp_filename); //crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Error writing Protected Data Store"); + //LLTHROW(LLProtectedDataException("Error writing Protected Data Store")); } } - + // instantiate a certificate from a pem string LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert) { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 86135ee6e8..f07f0ed86c 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -383,7 +383,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { - if (!mEditWearable || mEditWearable->getVisible() == visible) + if (!mEditWearable || ((mEditWearable->getWearable() == wearable) && mEditWearable->getVisible() == visible)) { // visibility isn't changing, hence nothing to do return; diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 623565817d..049aae1336 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -86,13 +86,13 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param mNeedsFlash(TRUE), mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")), mDataSize(0), - mSnapshotType(SNAPSHOT_POSTCARD), - mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), + mSnapshotType(LLSnapshotModel::SNAPSHOT_POSTCARD), + mSnapshotFormat(LLSnapshotModel::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), mSnapshotUpToDate(FALSE), mCameraPos(LLViewerCamera::getInstance()->getOrigin()), mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), - mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), + mSnapshotBufferType(LLSnapshotModel::SNAPSHOT_TYPE_COLOR), mFilterName(""), mAllowRenderUI(TRUE), mAllowFullScreenPreview(TRUE), @@ -737,7 +737,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->getWidth(), previewp->getHeight(), previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), - previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, + previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE, previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE, previewp->mSnapshotBufferType, @@ -813,7 +813,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame() mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex]; gGL.getTexUnit(0)->bind(curr_preview_image); - curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); + curr_preview_image->setFilteringOption(getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -827,7 +827,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame() S32 LLSnapshotLivePreview::getEncodedImageWidth() const { S32 width = getWidth(); - if (getSnapshotType() == SNAPSHOT_TEXTURE) + if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE) { width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE); } @@ -836,7 +836,7 @@ S32 LLSnapshotLivePreview::getEncodedImageWidth() const S32 LLSnapshotLivePreview::getEncodedImageHeight() const { S32 height = getHeight(); - if (getSnapshotType() == SNAPSHOT_TEXTURE) + if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE) { height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE); } @@ -854,7 +854,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage() mPreviewImage->getHeight(), mPreviewImage->getComponents()); - if (getSnapshotType() == SNAPSHOT_TEXTURE) + if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE) { // We don't store the intermediate formatted image in mFormattedImage in the J2C case LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL; @@ -881,7 +881,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage() { // Update mFormattedImage if necessary getFormattedImage(); - if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) + if (getSnapshotFormat() == LLSnapshotModel::SNAPSHOT_FORMAT_BMP) { // BMP hack : copy instead of decode otherwise decode will crash. mPreviewImageEncoded->copy(mPreviewImage); @@ -903,23 +903,23 @@ void LLSnapshotLivePreview::estimateDataSize() // Compression ratio F32 ratio = 1.0; - if (getSnapshotType() == SNAPSHOT_TEXTURE) + if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE) { ratio = 8.0; // This is what we shoot for when compressing to J2C } else { - LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); + LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat(); switch (format) { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: ratio = 3.0; // Average observed PNG compression ratio break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: // Observed from JPG compression tests ratio = (110 - mSnapshotQuality) / 2; break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: ratio = 1.0; // No compression with BMP break; } @@ -947,18 +947,18 @@ LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage() } // Create the new formatted image of the appropriate format. - LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat(); + LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat(); LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL; switch (format) { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: mFormattedImage = new LLImagePNG(); break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: mFormattedImage = new LLImageJPEG(mSnapshotQuality); break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: mFormattedImage = new LLImageBMP(); break; } @@ -978,7 +978,7 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h) setHeight(h); } -void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format) +void LLSnapshotLivePreview::setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format) { if (mSnapshotFormat != format) { @@ -993,7 +993,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const h = getHeight(); } -void LLSnapshotLivePreview::saveTexture() +void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) { LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL; // gen a new uuid for this asset @@ -1033,12 +1033,14 @@ void LLSnapshotLivePreview::saveTexture() std::string who_took_it; LLAgentUI::buildFullname(who_took_it); S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - std::string name = "Snapshot: " + pos_string; - std::string desc = "Taken by " + who_took_it + " at " + pos_string; + std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string; + std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string; + LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY; + LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT; LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo( - tid, LLAssetType::AT_TEXTURE, name, desc, 0, - LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT, + tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0, + folder_type, inv_type, PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"), expected_upload_cost)); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 57e5d83f8e..b689c50320 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -27,7 +27,7 @@ #ifndef LL_LLSNAPSHOTLIVEPREVIEW_H #define LL_LLSNAPSHOTLIVEPREVIEW_H -#include "llpanelsnapshot.h" +#include "llsnapshotmodel.h" #include "llviewertexture.h" #include "llviewerwindow.h" @@ -40,14 +40,6 @@ class LLSnapshotLivePreview : public LLView { LOG_CLASS(LLSnapshotLivePreview); public: - enum ESnapshotType - { - SNAPSHOT_POSTCARD, - SNAPSHOT_TEXTURE, - SNAPSHOT_LOCAL, - SNAPSHOT_WEB - }; - struct Params : public LLInitParam::Block<Params, LLView::Params> { @@ -80,8 +72,8 @@ public: void setMaxImageSize(S32 size) ; S32 getMaxImageSize() {return mMaxImageSize ;} - ESnapshotType getSnapshotType() const { return mSnapshotType; } - LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } + LLSnapshotModel::ESnapshotType getSnapshotType() const { return mSnapshotType; } + LLSnapshotModel::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; } BOOL isSnapshotActive() { return mSnapshotActive; } LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; } @@ -98,16 +90,16 @@ public: void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; } const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } - void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } - void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format); + void setSnapshotType(LLSnapshotModel::ESnapshotType type) { mSnapshotType = type; } + void setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format); bool setSnapshotQuality(S32 quality, bool set_by_user = true); - void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } + void setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType type) { mSnapshotBufferType = type; } void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; } void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; } void setFilter(std::string filter_name) { mFilterName = filter_name; } std::string getFilter() const { return mFilterName; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); - void saveTexture(); + void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = ""); BOOL saveLocal(); LLPointer<LLImageFormatted> getFormattedImage(); @@ -169,14 +161,14 @@ private: LLVector3d mPosTakenGlobal; S32 mSnapshotQuality; S32 mDataSize; - ESnapshotType mSnapshotType; - LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat; + LLSnapshotModel::ESnapshotType mSnapshotType; + LLSnapshotModel::ESnapshotFormat mSnapshotFormat; BOOL mSnapshotUpToDate; LLFrameTimer mFallAnimTimer; LLVector3 mCameraPos; LLQuaternion mCameraRot; BOOL mSnapshotActive; - LLViewerWindow::ESnapshotType mSnapshotBufferType; + LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType; std::string mFilterName; public: diff --git a/indra/newview/llsnapshotmodel.h b/indra/newview/llsnapshotmodel.h new file mode 100644 index 0000000000..71402fb5bc --- /dev/null +++ b/indra/newview/llsnapshotmodel.h @@ -0,0 +1,55 @@ +/** +* @file llsnapshotmodel.h +* @brief Snapshot model for storing snapshot data etc. +* +* $LicenseInfo:firstyear=2004&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2016, 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_LLSNAPSHOTMODEL_H +#define LL_LLSNAPSHOTMODEL_H + +class LLSnapshotModel +{ +public: + enum ESnapshotType + { + SNAPSHOT_POSTCARD, + SNAPSHOT_TEXTURE, + SNAPSHOT_LOCAL, + SNAPSHOT_WEB + }; + + typedef enum e_snapshot_format + { + SNAPSHOT_FORMAT_PNG, + SNAPSHOT_FORMAT_JPEG, + SNAPSHOT_FORMAT_BMP + } ESnapshotFormat; + + typedef enum + { + SNAPSHOT_TYPE_COLOR, + SNAPSHOT_TYPE_DEPTH + } ESnapshotLayerType; +}; + +#endif // LL_LLSNAPSHOTMODEL_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a2c8e7772e..4e81d78455 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -771,7 +771,11 @@ bool idle_startup() LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; } } - + display_startup(); + if (gViewerWindow->getSystemUIScaleFactorChanged()) + { + LLViewerWindow::showSystemUIScaleFactorChanged(); + } LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input } else diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 2d06b8599c..d28a7cc048 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f); F32 vec[3] = { - fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), - fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), + (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), + (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), 0.f }; F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 37cc908e84..36c4f0d516 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1928,6 +1928,12 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis { //make a duplicate to keep the original raw image untouched. raw = raw->duplicate(); + if (raw->isBufferInvalid()) + { + LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL; + return false; + } + raw->scale(w, h) ; discardlevel += i ; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index e5aa740a33..24bc55c998 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -37,8 +37,6 @@ #include "llbutton.h" #include "lldraghandle.h" #include "llfocusmgr.h" -#include "llviewertexture.h" -#include "llfolderview.h" #include "llfolderviewmodel.h" #include "llinventory.h" #include "llinventoryfunctions.h" @@ -71,6 +69,7 @@ #include "llradiogroup.h" #include "llfloaterreg.h" #include "lllocalbitmaps.h" +#include "llerror.h" static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f; static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; @@ -82,118 +81,13 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1; //static const char WHITE_IMAGE_NAME[] = "Blank Texture"; //static const char NO_IMAGE_NAME[] = "None"; -////////////////////////////////////////////////////////////////////////////////////////// -// LLFloaterTexturePicker - -class LLFloaterTexturePicker : public LLFloater -{ -public: - LLFloaterTexturePicker( - LLTextureCtrl* owner, - const std::string& label, - PermissionMask immediate_filter_perm_mask, - PermissionMask dnd_filter_perm_mask, - PermissionMask non_immediate_filter_perm_mask, - BOOL can_apply_immediately, - LLUIImagePtr fallback_image_name); - - virtual ~LLFloaterTexturePicker(); - - // LLView overrides - /*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 draw(); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - - // LLFloater overrides - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_settings); - - // New functions - void setImageID( const LLUUID& image_asset_id, bool set_selection = true); - void updateImageStats(); - const LLUUID& getAssetID() { return mImageAssetID; } - const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); - void setCanApplyImmediately(BOOL b); - - void setActive( BOOL active ); - - LLTextureCtrl* getOwner() const { return mOwner; } - void setOwner(LLTextureCtrl* owner) { mOwner = owner; } - - void stopUsingPipette(); - PermissionMask getFilterPermMask(); - void updateFilterPermMask(); - void commitIfImmediateSet(); - void commitCancel(); - - void onFilterEdit(const std::string& search_string ); - - void setCanApply(bool can_preview, bool can_apply); - void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} - - static void onBtnSetToDefault( void* userdata ); - static void onBtnSelect( void* userdata ); - static void onBtnCancel( void* userdata ); - void onBtnPipette( ); - //static void onBtnRevert( void* userdata ); - static void onBtnBlank( void* userdata ); - static void onBtnNone( void* userdata ); - static void onBtnClear( void* userdata ); - void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); - static void onShowFolders(LLUICtrl* ctrl, void* userdata); - static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); - void onTextureSelect( const LLTextureEntry& te ); - - static void onModeSelect(LLUICtrl* ctrl, void *userdata); - static void onBtnAdd(void* userdata); - static void onBtnRemove(void* userdata); - static void onBtnUpload(void* userdata); - static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); - -protected: - LLPointer<LLViewerTexture> mTexturep; - LLTextureCtrl* mOwner; - - LLUUID mImageAssetID; // Currently selected texture - LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. - - LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. - LLUUID mOriginalImageAssetID; - - std::string mLabel; - - LLTextBox* mTentativeLabel; - LLTextBox* mResolutionLabel; - - std::string mPendingName; - BOOL mActive; - - LLFilterEditor* mFilterEdit; - LLInventoryPanel* mInventoryPanel; - PermissionMask mImmediateFilterPermMask; - PermissionMask mDnDFilterPermMask; - PermissionMask mNonImmediateFilterPermMask; - BOOL mCanApplyImmediately; - BOOL mNoCopyTextureSelected; - F32 mContextConeOpacity; - LLSaveFolderState mSavedFolderState; - BOOL mSelectedItemPinned; - - LLRadioGroup* mModeSelector; - LLScrollListCtrl* mLocalScrollCtrl; - -private: - bool mCanApply; - bool mCanPreview; - bool mPreviewSettingChanged; - texture_selected_callback mTextureSelectedCallback; -}; - LLFloaterTexturePicker::LLFloaterTexturePicker( - LLTextureCtrl* owner, + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, const std::string& label, PermissionMask immediate_filter_perm_mask, PermissionMask dnd_filter_perm_mask, @@ -202,9 +96,13 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( LLUIImagePtr fallback_image) : LLFloater(LLSD()), mOwner( owner ), - mImageAssetID( owner->getImageAssetID() ), - mFallbackImage( fallback_image ), - mOriginalImageAssetID(owner->getImageAssetID()), + mImageAssetID( image_asset_id ), + mOriginalImageAssetID(image_asset_id), + mFallbackImage(fallback_image), + mDefaultImageAssetID(default_image_asset_id), + mBlankImageAssetID(blank_image_asset_id), + mTentative(tentative), + mAllowNoTexture(allow_no_texture), mLabel(label), mTentativeLabel(NULL), mResolutionLabel(NULL), @@ -217,7 +115,11 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mSelectedItemPinned( FALSE ), mCanApply(true), mCanPreview(true), - mPreviewSettingChanged(false) + mPreviewSettingChanged(false), + mOnFloaterCommitCallback(NULL), + mOnFloaterCloseCallback(NULL), + mSetImageAssetIDCallback(NULL), + mOnUpdateImageStatsCallback(NULL) { buildFromFile("floater_texture_ctrl.xml"); mCanApplyImmediately = can_apply_immediately; @@ -294,6 +196,10 @@ void LLFloaterTexturePicker::updateImageStats() { std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight()); mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims); + if (mOnUpdateImageStatsCallback) + { + mOnUpdateImageStatsCallback(mTexturep); + } } else { @@ -400,9 +306,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) void LLFloaterTexturePicker::onClose(bool app_quitting) { - if (mOwner) + if (mOwner && mOnFloaterCloseCallback) { - mOwner->onFloaterClose(); + mOnFloaterCloseCallback(); } stopUsingPipette(); } @@ -582,9 +488,9 @@ void LLFloaterTexturePicker::draw() mTentativeLabel->setVisible( FALSE ); } - getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID() || mOwner->getTentative()); - getChildView("Blank")->setEnabled(mImageAssetID != mOwner->getBlankImageAssetID() || mOwner->getTentative()); - getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && (!mImageAssetID.isNull() || mOwner->getTentative())); + getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); + getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative); + getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative)); LLFloater::draw(); @@ -629,7 +535,7 @@ void LLFloaterTexturePicker::draw() } // Draw Tentative Label over the image - if( mOwner->getTentative() && !mViewModel->isDirty() ) + if( mTentative && !mViewModel->isDirty() ) { mTentativeLabel->setVisible( TRUE ); drawChild(mTentativeLabel); @@ -704,17 +610,17 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask() void LLFloaterTexturePicker::commitIfImmediateSet() { - if (!mNoCopyTextureSelected && mOwner && mCanApply) + if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) { - mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, LLUUID::null); } } void LLFloaterTexturePicker::commitCancel() { - if (!mNoCopyTextureSelected && mOwner && mCanApply) + if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) { - mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL); + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); } } @@ -725,7 +631,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) self->setCanApply(true, true); if (self->mOwner) { - self->setImageID( self->mOwner->getDefaultImageAssetID() ); + self->setImageID( self->getDefaultImageAssetID() ); } self->commitIfImmediateSet(); } @@ -735,7 +641,7 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; self->setCanApply(true, true); - self->setImageID( self->mOwner->getBlankImageAssetID() ); + self->setImageID( self->getBlankImageAssetID() ); self->commitIfImmediateSet(); } @@ -765,9 +671,9 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; self->setImageID( self->mOriginalImageAssetID ); - if (self->mOwner) + if (self->mOnFloaterCommitCallback) { - self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL); + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); } self->mViewModel->resetDirty(); self->closeFloater(); @@ -777,17 +683,18 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) void LLFloaterTexturePicker::onBtnSelect(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + LLUUID local_id = LLUUID::null; if (self->mOwner) { - LLUUID local_id = LLUUID::null; - if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty()) { LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); local_id = LLLocalBitmapMgr::getWorldID(temp_id); } - - self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id); + } + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id); } self->closeFloater(); } @@ -941,11 +848,17 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) { LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN); LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id); - self->mOwner->setImageAssetID(inworld_id); + if (self->mSetImageAssetIDCallback) + { + self->mSetImageAssetIDCallback(inworld_id); + } if (self->childGetValue("apply_immediate_check").asBoolean()) { - self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); + } } } } @@ -1028,6 +941,11 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) mInventoryPanel->setFilterSubString(search_string); } +void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled) +{ + mModeSelector->setIndexEnabled(1,enabled); +} + void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) { LLUUID inventory_item_id = findItemID(te.getID(), TRUE); @@ -1238,13 +1156,17 @@ void LLTextureCtrl::showPicker(BOOL take_focus) { floaterp = new LLFloaterTexturePicker( this, + getImageAssetID(), + getDefaultImageAssetID(), + getBlankImageAssetID(), + getTentative(), + getAllowNoTexture(), mLabel, mImmediateFilterPermMask, mDnDFilterPermMask, mNonImmediateFilterPermMask, mCanApplyImmediately, mFallbackImage); - mFloaterHandle = floaterp->getHandle(); LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); @@ -1252,6 +1174,18 @@ void LLTextureCtrl::showPicker(BOOL take_focus) { texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); } + if (texture_floaterp && mOnCloseCallback) + { + texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this)); + } + if (texture_floaterp) + { + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2)); + } + if (texture_floaterp) + { + texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1)); + } LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) @@ -1393,7 +1327,7 @@ void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) void LLTextureCtrl::setImageAssetName(const std::string& name) { - LLPointer<LLUIImage> imagep = LLUI::getUIImage(name, LLGLTexture::BOOST_PREVIEW); + LLPointer<LLUIImage> imagep = LLUI::getUIImage(name); if(imagep) { LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get()); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 15ca7bed92..61f99de5c0 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -29,12 +29,20 @@ #define LL_LLTEXTURECTRL_H #include "llcoord.h" +#include "llfiltereditor.h" #include "llfloater.h" +#include "llfolderview.h" +#include "lllocalbitmaps.h" #include "llstring.h" #include "lluictrl.h" #include "llpermissionsflags.h" +#include "llradiogroup.h" #include "lltextbox.h" // for params +#include "llviewerinventory.h" #include "llviewborder.h" // for params +#include "llviewerobject.h" +#include "llviewertexture.h" +#include "llwindow.h" class LLButton; class LLFloaterTexturePicker; @@ -166,7 +174,7 @@ public: void closeDependentFloater(); void onFloaterClose(); - void onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null); + void onFloaterCommit(ETexturePickOp op, LLUUID id); // This call is returned when a drag is detected. Your callback // should return TRUE if the drag is acceptable. @@ -227,4 +235,140 @@ private: S32 mLabelWidth; }; +////////////////////////////////////////////////////////////////////////////////////////// +// LLFloaterTexturePicker +typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLUUID id)> floater_commit_callback; +typedef boost::function<void()> floater_close_callback; +typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback; +typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback; + +class LLFloaterTexturePicker : public LLFloater +{ +public: + LLFloaterTexturePicker( + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, + const std::string& label, + PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, + PermissionMask non_immediate_filter_perm_mask, + BOOL can_apply_immediately, + LLUIImagePtr fallback_image_name + ); + + virtual ~LLFloaterTexturePicker(); + + // LLView overrides + /*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 draw(); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + + // LLFloater overrides + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_settings); + + // New functions + void setImageID(const LLUUID& image_asset_id, bool set_selection = true); + void updateImageStats(); + const LLUUID& getAssetID() { return mImageAssetID; } + const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); + void setCanApplyImmediately(BOOL b); + + void setActive(BOOL active); + + LLView* getOwner() const { return mOwner; } + void setOwner(LLView* owner) { mOwner = owner; } + void stopUsingPipette(); + PermissionMask getFilterPermMask(); + + void updateFilterPermMask(); + void commitIfImmediateSet(); + void commitCancel(); + + void onFilterEdit(const std::string& search_string); + + void setCanApply(bool can_preview, bool can_apply); + void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; } + void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; } + void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; } + void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; } + void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; } + const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; } + const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; } + + static void onBtnSetToDefault(void* userdata); + static void onBtnSelect(void* userdata); + static void onBtnCancel(void* userdata); + void onBtnPipette(); + //static void onBtnRevert( void* userdata ); + static void onBtnBlank(void* userdata); + static void onBtnNone(void* userdata); + static void onBtnClear(void* userdata); + void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + static void onShowFolders(LLUICtrl* ctrl, void* userdata); + static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); + void onTextureSelect(const LLTextureEntry& te); + + static void onModeSelect(LLUICtrl* ctrl, void *userdata); + static void onBtnAdd(void* userdata); + static void onBtnRemove(void* userdata); + static void onBtnUpload(void* userdata); + static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); + + void setLocalTextureEnabled(BOOL enabled); + +protected: + LLPointer<LLViewerTexture> mTexturep; + LLView* mOwner; + + LLUUID mImageAssetID; // Currently selected texture + LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. + LLUUID mDefaultImageAssetID; + LLUUID mBlankImageAssetID; + BOOL mTentative; + BOOL mAllowNoTexture; + LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. + LLUUID mOriginalImageAssetID; + + std::string mLabel; + + LLTextBox* mTentativeLabel; + LLTextBox* mResolutionLabel; + + std::string mPendingName; + BOOL mActive; + + LLFilterEditor* mFilterEdit; + LLInventoryPanel* mInventoryPanel; + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + PermissionMask mNonImmediateFilterPermMask; + BOOL mCanApplyImmediately; + BOOL mNoCopyTextureSelected; + F32 mContextConeOpacity; + LLSaveFolderState mSavedFolderState; + BOOL mSelectedItemPinned; + + LLRadioGroup* mModeSelector; + LLScrollListCtrl* mLocalScrollCtrl; + +private: + bool mCanApply; + bool mCanPreview; + bool mPreviewSettingChanged; + + texture_selected_callback mTextureSelectedCallback; + floater_close_callback mOnFloaterCloseCallback; + floater_commit_callback mOnFloaterCommitCallback; + set_image_asset_id_callback mSetImageAssetIDCallback; + set_on_update_image_stats_callback mOnUpdateImageStatsCallback; +}; + #endif // LL_LLTEXTURECTRL_H diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index c4696c3a01..caa055e5e0 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -223,6 +223,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info) } if (!(pick_info.mKeyMask & MASK_ALT) && + !LLFloaterCamera::inFreeCameraMode() && gAgentCamera.cameraThirdPerson() && gViewerWindow->getLeftMouseDown() && !gSavedSettings.getBOOL("FreezeTime") && diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index b0e3b5bf89..f6eb290bc3 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -267,7 +267,7 @@ bool LLToolMgr::canEdit() bool LLToolMgr::buildEnabledOrActive() { - return inEdit() || canEdit(); + return LLFloaterReg::instanceVisible("build") || canEdit(); } void LLToolMgr::toggleBuildMode(const LLSD& sdname) diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index a0ca91672a..375dce485d 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -99,10 +99,16 @@ const std::string &LLVersionInfo::getShortVersion() namespace { + // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The + // macro expands to the string name of the channel, but without quotes. We + // need to turn it into a quoted string. This macro trick does that. +#define stringize_inner(x) #x +#define stringize_outer(x) stringize_inner(x) + /// Storage of the channel name the viewer is using. // The channel name is set by hardcoded constant, // or by calling LLVersionInfo::resetChannel() - std::string sWorkingChannelName(LL_VIEWER_CHANNEL); + std::string sWorkingChannelName(stringize_outer(LL_VIEWER_CHANNEL)); // Storage for the "version and channel" string. // This will get reset too. diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp index 5c5bbdc8f5..32b2f7e9f5 100644 --- a/indra/newview/llviewchildren.cpp +++ b/indra/newview/llviewchildren.cpp @@ -79,8 +79,9 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible) default: case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break; case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break; - case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break; - case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break; + case BADGE_WARN: + case BADGE_ERROR: + child->setValue(std::string("badge_warn.j2c")); break; } } } diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 497ff4d2bf..94f1b09fa9 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -779,12 +779,17 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti if (uploadInfo->showUploadDialog()) LLUploadDialog::modalUploadFinished(); - // Let the Snapshot floater know we have finished uploading a snapshot to inventory. + // Let the Snapshot floater know we have finished uploading a snapshot to inventory LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); - if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot) + if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown()) { floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); } + LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); + if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) + { + floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); + } } //========================================================================= @@ -839,10 +844,14 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res // Let the Snapshot floater know we have failed uploading. LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); - if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot) + if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown()) { floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); } - + LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); + if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) + { + floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); + } } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 91e4980e45..6d13d28e18 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -93,6 +93,7 @@ #include "llfloaternotificationstabbed.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" +#include "llfloateroutfitsnapshot.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindinglinksets.h" @@ -333,7 +334,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>); LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); - LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); + LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>); + LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d0813544f8..0bbe9fa2c2 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1007,6 +1007,22 @@ void activate_gesture_cb(const LLUUID& inv_item) LLGestureMgr::instance().activateGesture(inv_item); } +void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) +{ + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type) + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type)) + { + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type)); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type)); + + item->setPermissions(perm); + + item->updateServer(FALSE); + } +} + void create_script_cb(const LLUUID& inv_item) { if (!inv_item.isNull()) @@ -1014,13 +1030,9 @@ void create_script_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts")); - - item->setPermissions(perm); + set_default_permissions(item, "Scripts"); - item->updateServer(FALSE); + // item was just created, update even if permissions did not changed gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -1036,13 +1048,8 @@ void create_gesture_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures")); + set_default_permissions(item, "Gestures"); - item->setPermissions(perm); - - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); @@ -1061,13 +1068,8 @@ void create_notecard_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards")); - - item->setPermissions(perm); + set_default_permissions(item, "Notecards"); - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 6ed063e066..78c4d98d55 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1490,7 +1490,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0, 1.0); } } @@ -1762,7 +1762,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool clean_browser) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { std::string plugin_basename = LLMIMETypes::implType(media_type); LLPluginClassMedia* media_source = NULL; @@ -1779,6 +1779,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setOwner(owner); media_source->setTarget(target); media_source->setSize(default_width, default_height); + media_source->setZoomFactor(zoom_factor); return media_source; } @@ -1827,6 +1828,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setSize(default_width, default_height); media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies); media_source->setLanguageCode(LLUI::getLanguage()); + media_source->setZoomFactor(zoom_factor); // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); @@ -1883,6 +1885,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the previous media source's last set size before destroying it. mMediaWidth = mMediaSource->getSetWidth(); mMediaHeight = mMediaSource->getSetHeight(); + mZoomFactor = mMediaSource->getZoomFactor(); } // Always delete the old media impl first. @@ -1905,7 +1908,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser); if (media_source) { diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 48f0d9dc4d..1fecf15fc9 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -299,7 +299,7 @@ public: void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool clean_browser = false); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index c107e8472c..3ccf3070ab 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -154,7 +154,8 @@ LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::st { LLPluginClassMediaOwner* owner = NULL; S32 default_size = 1; // audio-only - be minimal, doesn't matter - LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); + F64 default_zoom = 1.0; + LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size, default_zoom); if (media_source) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f5b06fbd19..39059fc01e 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -397,13 +397,15 @@ void set_merchant_SLM_menu() gToolBarView->enableCommand(command->id(), true); } -void check_merchant_status() +void check_merchant_status(bool force) { if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth")) { - // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() - LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); - + if (force) + { + // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); + } // Hide SLM related menu item gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE); @@ -7906,7 +7908,7 @@ void handle_web_browser_test(const LLSD& param) void handle_web_content_test(const LLSD& param) { std::string url = param.asString(); - LLWeb::loadURLInternal(url); + LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true); } void handle_show_url(const LLSD& param) diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index b7bdf00157..a553bb79a2 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -83,7 +83,7 @@ BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); BOOL enable_god_basic(void* user_data); void set_underclothes_menu_options(); -void check_merchant_status(); +void check_merchant_status(bool force = false); void exchange_callingcard(const LLUUID& dest_id); @@ -108,6 +108,7 @@ void handle_look_at_selection(const LLSD& param); void handle_zoom_to_object(LLUUID object_id); void handle_object_return(); void handle_object_delete(); +void handle_object_edit(); void handle_buy_land(); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 4f24dfafac..b48b45502b 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -37,6 +37,7 @@ #include "llfloatermap.h" #include "llfloatermodelpreview.h" #include "llfloatersnapshot.h" +#include "llfloateroutfitsnapshot.h" #include "llimage.h" #include "llimagebmp.h" #include "llimagepng.h" @@ -508,8 +509,10 @@ class LLFileEnableCloseAllWindows : public view_listener_t bool handleEvent(const LLSD& userdata) { LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); - bool is_floater_snapshot_opened = floater_snapshot && floater_snapshot->isInVisibleChain(); - bool open_children = gFloaterView->allChildrenClosed() && !is_floater_snapshot_opened; + LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance(); + bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain()) + || (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain()); + bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened; return !open_children; } }; @@ -520,7 +523,12 @@ class LLFileCloseAllWindows : public view_listener_t { bool app_quitting = false; gFloaterView->closeAllChildren(app_quitting); - LLFloaterSnapshot::getInstance()->closeFloater(app_quitting); + LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); + if (floater_snapshot) + floater_snapshot->closeFloater(app_quitting); + LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance(); + if (floater_outfit_snapshot) + floater_outfit_snapshot->closeFloater(app_quitting); if (gMenuHolder) gMenuHolder->hideMenus(); return true; } @@ -551,18 +559,18 @@ class LLFileTakeSnapshotToDisk : public view_listener_t { gViewerWindow->playSnapshotAnimAndSound(); LLPointer<LLImageFormatted> formatted; - LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); + LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); switch (fmt) { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; default: LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: formatted = new LLImagePNG; break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: formatted = new LLImageBMP; break; } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 92df3866f7..f472db080f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1639,7 +1639,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); discard_agent_offer->startFetch(); - if (catp || (itemp && itemp->isFinished())) + if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished())) { discard_agent_offer->done(); } @@ -4719,7 +4719,9 @@ void process_sound_trigger(LLMessageSystem *msg, void **) { if (!gAudiop) { +#if !LL_LINUX LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif return; } @@ -4781,7 +4783,9 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) { if (!gAudiop) { +#if !LL_LINUX LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif return; } @@ -6601,6 +6605,11 @@ void process_script_question(LLMessageSystem *msg, void **user_data) if (("ScriptTakeMoney" == script_perm.question) && has_not_only_debit) continue; + if (script_perm.question == "JoinAnExperience") + { // Some experience only permissions do not have an explicit permission bit. Add them here. + script_question += " " + LLTrans::getString("ForceSitAvatar") + "\n"; + } + script_question += " " + LLTrans::getString(script_perm.question) + "\n"; } } diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 6666aecca2..2525886222 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -49,6 +49,8 @@ const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base"; const std::string GRID_HELPER_URI_VALUE = "helper_uri"; /// the splash page url const std::string GRID_LOGIN_PAGE_VALUE = "login_page"; +/// url for the web profile site +const std::string GRID_WEB_PROFILE_VALUE = "web_profile_url"; /// internal data on system grids const std::string GRID_IS_SYSTEM_GRID_VALUE = "system_grid"; /// whether this is single or double names @@ -70,6 +72,8 @@ const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update"; const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/"; const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; +const std::string MAIN_GRID_WEB_PROFILE_URL = "https://my.secondlife.com/"; + const char* SYSTEM_GRID_SLURL_BASE = "secondlife://%s/secondlife/"; const char* DEFAULT_SLURL_BASE = "https://%s/region/"; const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app"; @@ -125,6 +129,7 @@ void LLGridManager::initialize(const std::string& grid_file) "https://secondlife.com/helpers/", DEFAULT_LOGIN_PAGE, SL_UPDATE_QUERY_URL, + MAIN_GRID_WEB_PROFILE_URL, "Agni"); addSystemGrid(LLTrans::getString("AditiGridLabel"), "util.aditi.lindenlab.com", @@ -132,6 +137,7 @@ void LLGridManager::initialize(const std::string& grid_file) "http://aditi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE, SL_UPDATE_QUERY_URL, + "https://my.aditi.lindenlab.com/", "Aditi"); LLSD other_grids; @@ -288,6 +294,10 @@ bool LLGridManager::addGrid(LLSD& grid_data) { grid_data[GRID_HELPER_URI_VALUE] = std::string("https://") + grid + "/helpers/"; } + if (!grid_data.has(GRID_WEB_PROFILE_VALUE)) + { + grid_data[GRID_WEB_PROFILE_VALUE] = std::string("https://") + grid + "/"; + } if (!grid_data.has(GRID_LOGIN_IDENTIFIER_TYPES)) { @@ -302,7 +312,8 @@ bool LLGridManager::addGrid(LLSD& grid_data) <<" id: "<<grid_data[GRID_ID_VALUE].asString()<<"\n" <<" label: "<<grid_data[GRID_LABEL_VALUE].asString()<<"\n" <<" login page: "<<grid_data[GRID_LOGIN_PAGE_VALUE].asString()<<"\n" - <<" helper page: "<<grid_data[GRID_HELPER_URI_VALUE].asString()<<"\n"; + <<" helper page: "<<grid_data[GRID_HELPER_URI_VALUE].asString()<<"\n" + <<" web profile: "<<grid_data[GRID_WEB_PROFILE_VALUE].asString()<<"\n"; /* still in LL_DEBUGS */ for (LLSD::array_const_iterator login_uris = grid_data[GRID_LOGIN_URI_VALUE].beginArray(); login_uris != grid_data[GRID_LOGIN_URI_VALUE].endArray(); @@ -339,6 +350,7 @@ void LLGridManager::addSystemGrid(const std::string& label, const std::string& helper, const std::string& login_page, const std::string& update_url_base, + const std::string& web_profile_url, const std::string& login_id) { LLSD grid = LLSD::emptyMap(); @@ -349,6 +361,7 @@ void LLGridManager::addSystemGrid(const std::string& label, grid[GRID_LOGIN_URI_VALUE].append(login_uri); grid[GRID_LOGIN_PAGE_VALUE] = login_page; grid[GRID_UPDATE_SERVICE_URL] = update_url_base; + grid[GRID_WEB_PROFILE_VALUE] = web_profile_url; grid[GRID_IS_SYSTEM_GRID_VALUE] = true; grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray(); grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT); @@ -535,6 +548,21 @@ std::string LLGridManager::getLoginPage() return login_page; } +std::string LLGridManager::getWebProfileURL(const std::string& grid) +{ + std::string web_profile_url; + std::string grid_name = getGrid(grid); + if (!grid_name.empty()) + { + web_profile_url = mGridList[grid_name][GRID_WEB_PROFILE_VALUE].asString(); + } + else + { + LL_WARNS("GridManager")<<"invalid grid '"<<grid<<"'"<<LL_ENDL; + } + return web_profile_url; +} + void LLGridManager::getLoginIdentifierTypes(LLSD& idTypes) { idTypes = mGridList[mGrid][GRID_LOGIN_IDENTIFIER_TYPES]; diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 8526c0ba7f..228303d8e2 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -166,6 +166,13 @@ class LLGridManager : public LLSingleton<LLGridManager> /// Return the application URL prefix for the selected grid std::string getAppSLURLBase() { return getAppSLURLBase(mGrid); } + /// Return the url of the resident profile web site for the given grid + std::string getWebProfileURL(const std::string& grid); + + /// Return the url of the resident profile web site for the selected grid + std::string getWebProfileURL() { return getWebProfileURL(mGrid); } + + //@} /* ================================================================ @@ -216,6 +223,7 @@ class LLGridManager : public LLSingleton<LLGridManager> const std::string& helper, const std::string& login_page, const std::string& update_url_base, + const std::string& web_profile_url, const std::string& login_id = ""); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 5edc3c9745..7964bf1848 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -244,9 +244,10 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mPixelArea(1024.f), mInventory(NULL), mInventorySerialNum(0), - mRegionp( regionp ), - mInventoryPending(FALSE), + mInvRequestState(INVENTORY_REQUEST_STOPPED), + mInvRequestXFerId(0), mInventoryDirty(FALSE), + mRegionp(regionp), mDead(FALSE), mOrphaned(FALSE), mUserSelected(FALSE), @@ -1434,10 +1435,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(MOVED | SILHOUETTE); } - else if (mText.notNull()) + else { - mText->markDead(); - mText = NULL; + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); } std::string media_url; @@ -1812,10 +1817,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(TEXTURE); } - else if(mText.notNull()) + else { - mText->markDead(); - mText = NULL; + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); } std::string media_url; @@ -2832,6 +2841,11 @@ void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener) } } +BOOL LLViewerObject::isInventoryPending() +{ + return mInvRequestState != INVENTORY_REQUEST_STOPPED; +} + void LLViewerObject::clearInventoryListeners() { for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); @@ -2870,7 +2884,7 @@ void LLViewerObject::requestInventory() void LLViewerObject::fetchInventoryFromServer() { - if (!mInventoryPending) + if (!isInventoryPending()) { delete mInventory; LLMessageSystem* msg = gMessageSystem; @@ -2883,7 +2897,7 @@ void LLViewerObject::fetchInventoryFromServer() msg->sendReliable(mRegionp->getHost()); // this will get reset by dirtyInventory or doInventoryCallback - mInventoryPending = TRUE; + mInvRequestState = INVENTORY_REQUEST_PENDING; } } @@ -2944,7 +2958,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) std::string unclean_filename; msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename); ft->mFilename = LLDir::getScrubbedFileName(unclean_filename); - + if(ft->mFilename.empty()) { LL_DEBUGS() << "Task has no inventory" << LL_ENDL; @@ -2966,13 +2980,27 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) delete ft; return; } - gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), + U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), ft->mFilename, LL_PATH_CACHE, object->mRegionp->getHost(), TRUE, &LLViewerObject::processTaskInvFile, (void**)ft, LLXferManager::HIGH_PRIORITY); + if (object->mInvRequestState == INVENTORY_XFER) + { + if (new_id > 0 && new_id != object->mInvRequestXFerId) + { + // we started new download. + gXferManager->abortRequestById(object->mInvRequestXFerId, -1); + object->mInvRequestXFerId = new_id; + } + } + else + { + object->mInvRequestState = INVENTORY_XFER; + object->mInvRequestXFerId = new_id; + } } void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status) @@ -3099,7 +3127,10 @@ void LLViewerObject::doInventoryCallback() mInventoryCallbacks.erase(curiter); } } - mInventoryPending = FALSE; + + // release inventory loading state + mInvRequestXFerId = 0; + mInvRequestState = INVENTORY_REQUEST_STOPPED; } void LLViewerObject::removeInventory(const LLUUID& item_id) @@ -4990,8 +5021,26 @@ void LLViewerObject::initHudText() void LLViewerObject::restoreHudText() { - if(mText) + if (mHudText.empty()) { + if (mText) + { + mText->markDead(); + mText = NULL; + } + } + else + { + if (!mText) + { + initHudText(); + } + else + { + // Restore default values + mText->setZCompare(TRUE); + mText->setDoFade(TRUE); + } mText->setColor(mHudTextColor); mText->setString(mHudText); } @@ -6271,7 +6320,7 @@ const LLUUID &LLViewerObject::extractAttachmentItemID() return getAttachmentItemID(); } -const std::string& LLViewerObject::getAttachmentItemName() +const std::string& LLViewerObject::getAttachmentItemName() const { static std::string empty; LLInventoryItem *item = gInventory.getItem(getAttachmentItemID()); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index cb8acfdcf8..1e8f3f4ec2 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -172,7 +172,7 @@ public: void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } virtual BOOL isAttachment() const { return FALSE; } - const std::string& getAttachmentItemName(); + const std::string& getAttachmentItemName() const; virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment virtual BOOL isHUDAttachment() const { return FALSE; } @@ -437,7 +437,7 @@ public: // viewer object has the inventory stored locally. void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); void removeInventoryListener(LLVOInventoryListener* listener); - BOOL isInventoryPending() { return mInventoryPending; } + BOOL isInventoryPending(); void clearInventoryListeners(); bool hasInventoryListeners(); void requestInventory(); @@ -720,6 +720,7 @@ private: void deleteTEImages(); // correctly deletes list of images protected: + typedef std::map<char *, LLNameValue *> name_value_map_t; name_value_map_t mNameValuePairs; // Any name-value pairs stored by script @@ -756,9 +757,17 @@ protected: callback_list_t mInventoryCallbacks; S16 mInventorySerialNum; + enum EInventoryRequestState + { + INVENTORY_REQUEST_STOPPED, + INVENTORY_REQUEST_PENDING, + INVENTORY_XFER + }; + EInventoryRequestState mInvRequestState; + U64 mInvRequestXFerId; + BOOL mInventoryDirty; + LLViewerRegion *mRegionp; // Region that this object belongs to. - BOOL mInventoryPending; - BOOL mInventoryDirty; BOOL mDead; BOOL mOrphaned; // This is an orphaned child BOOL mUserSelected; // Cached user select information diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ed719ae418..178aa1e646 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1200,7 +1200,7 @@ void LLViewerFetchedTexture::loadFromFastCache() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); @@ -1981,7 +1981,7 @@ bool LLViewerFetchedTexture::updateFetch() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 0f73515b5d..88eb13e7cd 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -451,7 +451,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // 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(); + revertValuesWithoutUpdate(); } void LLViewerWearable::setItemID(const LLUUID& item_id) @@ -471,6 +471,11 @@ void LLViewerWearable::revertValues() } } +void LLViewerWearable::revertValuesWithoutUpdate() +{ + LLWearable::revertValues(); +} + void LLViewerWearable::saveValues() { LLWearable::saveValues(); diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 62cd5e21ad..cc99f6af2f 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -85,6 +85,8 @@ public: /*virtual*/ void revertValues(); /*virtual*/ void saveValues(); + void revertValuesWithoutUpdate(); + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). /*virtual*/void setUpdated() const; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c17c50fd88..9e68bb78e0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -251,6 +251,11 @@ BOOL gDisplayBadge = FALSE; static const U8 NO_FACE = 255; BOOL gQuietSnapshot = FALSE; +// Minimum value for UIScaleFactor, also defined in preferences, ui_scale_slider +static const F32 MIN_UI_SCALE = 0.75f; +// 4.0 in preferences, but win10 supports larger scaling and value is used more as +// sanity check, so leaving space for larger values from DPI updates. +static const F32 MAX_UI_SCALE = 7.0f; static const F32 MIN_DISPLAY_SCALE = 0.75f; std::string LLViewerWindow::sSnapshotBaseName; @@ -1593,6 +1598,20 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) return FALSE; } +void LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) +{ + if (ui_scale_factor >= MIN_UI_SCALE && ui_scale_factor <= MAX_UI_SCALE) + { + gSavedSettings.setF32("UIScaleFactor", ui_scale_factor); + LLViewerWindow::reshape(window_width, window_height); + mResDirty = true; + } + else + { + LL_WARNS() << "DPI change caused UI scale to go out of bounds: " << ui_scale_factor << LL_ENDL; + } +} + void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg) { LLAppViewer::instance()->pingMainloopTimeout(msg); @@ -1655,7 +1674,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) mResDirty(false), mStatesDirty(false), mCurrResolutionIndex(0), - mProgressView(NULL) + mProgressView(NULL), + mSystemUIScaleFactorChanged(false) { // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to // pass its value right now. Instead, pass it a nullary function that @@ -1743,9 +1763,24 @@ LLViewerWindow::LLViewerWindow(const Params& p) gSavedSettings.setS32("FullScreenHeight",scr.mY); } + + F32 system_scale_factor = mWindow->getSystemUISize(); + if (system_scale_factor < MIN_UI_SCALE || system_scale_factor > MAX_UI_SCALE) + { + // reset to default; + system_scale_factor = 1.f; + } + if (p.first_run || gSavedSettings.getF32("LastSystemUIScaleFactor") != system_scale_factor) + { + mSystemUIScaleFactorChanged = !p.first_run; + gSavedSettings.setF32("LastSystemUIScaleFactor", system_scale_factor); + gSavedSettings.setF32("UIScaleFactor", system_scale_factor); + } + + // Get the real window rect the window was created with (since there are various OS-dependent reasons why // the size of a window or fullscreen context may have been adjusted slightly...) - F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor"), MIN_UI_SCALE, MAX_UI_SCALE); mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); mDisplayScale *= ui_scale_factor; @@ -1838,6 +1873,28 @@ LLViewerWindow::LLViewerWindow(const Params& p) mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); } +//static +void LLViewerWindow::showSystemUIScaleFactorChanged() +{ + LLNotificationsUtil::add("SystemUIScaleFactorChanged", LLSD(), LLSD(), onSystemUIScaleFactorChanged); +} + +//static +bool LLViewerWindow::onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(option == 0) + { + LLFloaterReg::toggleInstanceOrBringToFront("preferences"); + LLFloater* pref_floater = LLFloaterReg::getInstance("preferences"); + LLTabContainer* tab_container = pref_floater->getChild<LLTabContainer>("pref core"); + tab_container->selectTabByName("advanced1"); + + } + return false; +} + + void LLViewerWindow::initGLDefaults() { gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -4364,7 +4421,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) } } -BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) +BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type) { LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL; @@ -4403,7 +4460,7 @@ void LLViewerWindow::playSnapshotAnimAndSound() send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f); } -BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) +BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type) { return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); } @@ -4412,7 +4469,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p // Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy // the results over to the final raw image. BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, - BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size) + BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) { if (!raw) { @@ -4620,7 +4677,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); } - if (type == SNAPSHOT_TYPE_COLOR) + if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR) { glReadPixels( subimage_x_offset, out_y + subimage_y_offset, @@ -4629,7 +4686,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei raw->getData() + output_buffer_offset ); } - else // SNAPSHOT_TYPE_DEPTH + else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH { LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values glReadPixels( @@ -5211,7 +5268,7 @@ F32 LLViewerWindow::getWorldViewAspectRatio() const void LLViewerWindow::calcDisplayScale() { - F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor"), MIN_UI_SCALE, MAX_UI_SCALE); LLVector2 display_scale; display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); display_scale *= ui_scale_factor; @@ -5224,7 +5281,7 @@ void LLViewerWindow::calcDisplayScale() if (display_scale != mDisplayScale) { - LL_INFOS() << "Setting display scale to " << display_scale << LL_ENDL; + LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL; mDisplayScale = display_scale; // Init default fonts diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad06f00234..72b7370621 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -46,6 +46,7 @@ #include "llhandle.h" #include "llinitparam.h" #include "lltrace.h" +#include "llsnapshotmodel.h" #include <boost/function.hpp> #include <boost/signals2.hpp> @@ -155,7 +156,8 @@ public: min_width, min_height; Optional<bool> fullscreen, - ignore_pixel_depth; + ignore_pixel_depth, + first_run; Params(); }; @@ -209,6 +211,7 @@ public: /*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); /*virtual*/ BOOL handleTimerEvent(LLWindow *window); /*virtual*/ BOOL handleDeviceChange(LLWindow *window); + /*virtual*/ void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); /*virtual*/ void handlePauseWatchdog(LLWindow *window); @@ -342,15 +345,11 @@ public: // snapshot functionality. // perhaps some of this should move to llfloatershapshot? -MG - typedef enum - { - SNAPSHOT_TYPE_COLOR, - SNAPSHOT_TYPE_DEPTH - } ESnapshotType; - BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); + + BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, - BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE ); - BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; + BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); + BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type); BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } BOOL saveImageNumbered(LLImageFormatted *image, bool force_picker = false); @@ -418,6 +417,9 @@ public: void calcDisplayScale(); static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); + bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; } + static void showSystemUIScaleFactorChanged(); + private: bool shouldShowToolTipFor(LLMouseHandler *mh); @@ -431,6 +433,7 @@ private: S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter LLRect getChatConsoleRect(); // Get optimal cosole rect. + static bool onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response); private: LLWindow* mWindow; // graphical window object bool mActive; @@ -509,6 +512,7 @@ private: LLPointer<LLViewerObject> mDragHoveredObject; static LLTrace::SampleStatHandle<> sMouseVelocityStat; + bool mSystemUIScaleFactorChanged; // system UI scale factor changed from last run }; // diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp index 1fe5fc9800..97b405c1d0 100644 --- a/indra/newview/llviewerwindowlistener.cpp +++ b/indra/newview/llviewerwindowlistener.cpp @@ -65,9 +65,9 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow): void LLViewerWindowListener::saveSnapshot(const LLSD& event) const { - typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap; + typedef std::map<LLSD::String, LLSnapshotModel::ESnapshotLayerType> TypeMap; TypeMap types; -#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name +#define tp(name) types[#name] = LLSnapshotModel::SNAPSHOT_TYPE_##name tp(COLOR); tp(DEPTH); #undef tp @@ -84,7 +84,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const if (event.has("showui")) showui = event["showui"].asBoolean(); bool rebuild(event["rebuild"]); // defaults to false - LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR); + LLSnapshotModel::ESnapshotLayerType type(LLSnapshotModel::SNAPSHOT_TYPE_COLOR); if (event.has("type")) { TypeMap::const_iterator found = types.find(event["type"]); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index cdc7e20c2c..1425b3d42e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -186,6 +186,7 @@ const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0; +const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024; enum ERenderName { @@ -7391,16 +7392,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // No backsies zone - if we get here, the message should be valid and usable, will be processed. LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; - if (isSelf()) - { - // Note: - // locally the COF is maintained via LLInventoryModel::accountForUpdate - // which is called from various places. This should match the simhost's - // idea of what the COF version is. AIS however maintains its own version - // of the COF that should be considered canonical. - mLastUpdateReceivedCOFVersion = thisAppearanceVersion; - } - + // Note: + // locally the COF is maintained via LLInventoryModel::accountForUpdate + // which is called from various places. This should match the simhost's + // idea of what the COF version is. AIS however maintains its own version + // of the COF that should be considered canonical. + mLastUpdateReceivedCOFVersion = thisAppearanceVersion; + if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE)) { updateVisualComplexity(); @@ -8356,6 +8354,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() { U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; + hud_complexity_list_t hud_complexity_list; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { @@ -8432,6 +8431,63 @@ void LLVOAvatar::calculateUpdateRenderComplexity() } } } + if (isSelf() + && attached_object + && attached_object->isHUDAttachment() + && !attached_object->isTempAttachment() + && attached_object->mDrawable) + { + textures.clear(); + + const LLVOVolume* volume = attached_object->mDrawable->getVOVolume(); + if (volume) + { + LLHUDComplexity hud_object_complexity; + hud_object_complexity.objectName = attached_object->getAttachmentItemName(); + hud_object_complexity.objectId = attached_object->getAttachmentItemID(); + std::string joint_name; + gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name); + hud_object_complexity.jointName = joint_name; + // get cost and individual textures + hud_object_complexity.objectsCost += volume->getRenderCost(textures); + hud_object_complexity.objectsCount++; + + LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* childp = *iter; + const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp); + if (chld_volume) + { + // get cost and individual textures + hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures); + hud_object_complexity.objectsCount++; + } + } + + hud_object_complexity.texturesCount += textures.size(); + + for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin(); + volume_texture != textures.end(); + ++volume_texture) + { + // add the cost of each individual texture (ignores duplicates) + hud_object_complexity.texturesCost += volume_texture->second; + LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first); + if (tex) + { + // Note: Texture memory might be incorect since texture might be still loading. + hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory(); + if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE) + { + hud_object_complexity.largeTexturesCount++; + } + } + } + hud_complexity_list.push_back(hud_object_complexity); + } + } } } @@ -8493,11 +8549,15 @@ void LLVOAvatar::calculateUpdateRenderComplexity() static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20); - if (isSelf() && show_my_complexity_changes) - { - LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity); - } - } + if (isSelf() && show_my_complexity_changes) + { + // Avatar complexity + LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity); + + // HUD complexity + LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list); + } + } } void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set) diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 4dab213fa0..6b4a450e6f 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -283,7 +283,7 @@ void LLSkyTex::create(const F32 brightness) S32 offset = basic_offset * sComponents; U32* pix = (U32*)(data + offset); LLColor4U temp = LLColor4U(mSkyData[basic_offset]); - *pix = temp.mAll; + *pix = temp.asRGBA(); } } createGLImage(sCurrent); diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index ee8e91fb71..9cfb9773bd 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -171,7 +171,7 @@ protected: { S32 offset = (i * sResolution + j) * sComponents; U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); - *pix = col.mAll; + *pix = col.asRGBA(); } LLColor4U getPixel(const S32 i, const S32 j) @@ -179,7 +179,7 @@ protected: LLColor4U col; S32 offset = (i * sResolution + j) * sComponents; U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); - col.mAll = *pix; + col.fromRGBA( *pix ); return col; } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e69a8d1d1d..8c026bae21 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4429,7 +4429,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)) { - LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; + LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index b37e41fb85..8026dc3ea8 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -104,10 +104,10 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std // static // Explicitly open a Web URL using the Web content floater -void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid) +void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode) { LLFloaterWebContent::Params p; - p.url(url).target(target).id(uuid); + p.url(url).target(target).id(uuid).dev_mode(dev_mode); LLFloaterReg::showInstance("web_content", p); } diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 7c90badbfe..7149ce9baf 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -57,7 +57,7 @@ public: static void loadURL(const std::string& url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null); // load content using built-in browser - static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null); + static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null, bool dev_mode = false); /// Returns escaped url (eg, " " to "%20") - used by all loadURL methods static std::string escapeURL(const std::string& url); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 11d3706821..cee47a591e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects() center_y = min_y + (wy >> 1); S32 add_boundary[4] = { - 512 - (max_x - region_x), - 512 - (max_y - region_y), - 512 - (region_x - min_x), - 512 - (region_y - min_y) }; + (S32)(512 - (max_x - region_x)), + (S32)(512 - (max_y - region_y)), + (S32)(512 - (region_x - min_x)), + (S32)(512 - (region_y - min_y)) }; S32 dir; for (dir = 0; dir < 8; dir++) diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index 97a9eb7f5f..cc3645131d 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -322,7 +322,7 @@ public: mBoundListener = LLEventPumps::instance(). obtain("mainloop"). - listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1)); + listen(LLEventPump::ANONYMOUS, boost::bind(&Poller::poll, this, _1)); LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL; } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 8533625e50..e0da7f5d9e 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -948,4 +948,13 @@ <color name="SyntaxLslStringLiteral" value="1 0.14 0 1" /> + <color + name="OutfitGalleryItemSelected" + value="0.22 0.45 0.35 1" /> + <color + name="OutfitGalleryItemWorn" + value="0.33 0.58 0.47 1" /> + <color + name="OutfitGalleryItemUnselected" + value="0.4 0.4 0.4 1" /> </colors> diff --git a/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png Binary files differnew file mode 100644 index 0000000000..bacddcbb68 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.png Binary files differnew file mode 100644 index 0000000000..40e5df7d81 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Video_URL_Off.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72037a84b3..f2da22256c 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -676,7 +676,10 @@ with the same filename but different name <texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" /> <texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" /> - <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/> + + <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" /> + + <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/> <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false" scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" /> @@ -774,6 +777,9 @@ with the same filename but different name <texture name="default_land_picture.j2c" /> <texture name="default_profile_picture.j2c" /> <texture name="locked_image.j2c" /> + <texture name="badge_note.j2c" /> + <texture name="badge_warn.j2c" /> + <texture name="badge_ok.j2c" /> <texture name="materials_ui_x_24.png" /> <texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" /> @@ -806,6 +812,7 @@ with the same filename but different name <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/> <texture name="NavBar Separator" file_name="navbar/separator.png"/> + <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/> <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/> <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/> <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/> diff --git a/indra/newview/skins/default/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png Binary files differindex b405a88245..1fa10fde53 100644 --- a/indra/newview/skins/default/textures/windows/first_login_image_left.png +++ b/indra/newview/skins/default/textures/windows/first_login_image_left.png diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png Binary files differindex 22a6dd8a53..d764d846b7 100644 --- a/indra/newview/skins/default/textures/windows/first_login_image_right.png +++ b/indra/newview/skins/default/textures/windows/first_login_image_right.png diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index d3d85de3c3..b0cb1e0592 100644 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">[AMT] L$</panel.string> - <panel left="-415" name="balance_bg" width="205"> + <panel left="-436" name="balance_bg" width="205"> <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="L$ ??"/> <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> <button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/> diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml new file mode 100644 index 0000000000..15c480f144 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml @@ -0,0 +1,351 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="cascading" + legacy_header_height="18" + can_minimize="true" + can_resize="false" + can_close="true" + height="455" + layout="topleft" + name="outfit_snapshot" + single_instance="true" + help_topic="snapshot" + save_rect="true" + save_visibility="false" + title="OUTFIT SNAPSHOT" + width="624" + min_height="455"> + <floater.string + name="unknown"> + unknown + </floater.string> + <string + name="inventory_progress_str"> + Saving to Inventory + </string> + <string + name="inventory_succeeded_str"> + Saved to Inventory! + </string> + <string + name="inventory_failed_str"> + Failed to save to inventory. + </string> + <button + follows="left|top" + height="25" + image_overlay="Refresh_Off" + image_hover_unselected="Toolbar_Middle_Over" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + image_overlay_alignment="left" + imgoverlay_label_space="5" + pad_bottom="0" + halign="left" + layout="topleft" + left="10" + label="REFRESH" + name="new_snapshot_btn" + top_pad="26" + width="167" /> + <button + follows="left|top" + control_name="AdvanceOutfitSnapshot" + invisibility_control="AdvanceOutfitSnapshot" + height="25" + is_toggle="true" + layout="topleft" + image_hover_unselected="Toolbar_Middle_Over" + image_selected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" + image_overlay="Conv_toolbar_expand" + name="retract_btn" + left_pad="1" + top_delta="0" + width="31" /> + <button + follows="left|top" + control_name="AdvanceOutfitSnapshot" + visibility_control="AdvanceOutfitSnapshot" + height="25" + is_toggle="true" + layout="topleft" + image_overlay="Conv_toolbar_collapse" + image_hover_unselected="Toolbar_Middle_Over" + image_selected="Toolbar_Middle_Off" + image_unselected="Toolbar_Middle_Off" + name="extend_btn" + left_delta="0" + top_delta="0" + width="31" /> + <panel + height="154" + layout="topleft" + follows="top|left" + left="0" + name="advanced_options_panel" + top_pad="-6" + width="210"> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="advanced_options_hr" + right="-1" + top_pad="5" + /> + <text + type="string" + length="1" + follows="left|top" + height="13" + layout="topleft" + left="10" + name="layer_type_label" + top_pad="10" + width="100"> + Capture: + </text> + <check_box + label="Interface" + layout="topleft" + left="30" + height="16" + top_pad="8" + width="180" + name="ui_check" /> + <check_box + label="HUDs" + layout="topleft" + height="16" + left="30" + top_pad="1" + width="180" + name="hud_check" /> + <check_box + label="Freeze frame (fullscreen)" + layout="topleft" + height="16" + left="10" + top_pad="1" + width="180" + name="freeze_frame_check" /> + <check_box + label="Auto-refresh" + layout="topleft" + height="16" + left="10" + top_pad="1" + width="180" + name="auto_snapshot_check" /> + <text + type="string" + length="1" + follows="left|top" + height="13" + layout="topleft" + left="10" + name="filter_list_label" + top_pad="10" + width="50"> + Filter: + </text> + <combo_box + control_name="PhotoFilters" + follows="left|right|top" + name="filters_combobox" + tool_tip="Image filters" + top_delta="-3" + left="50" + right="-1" + height="21" + width="135"> + <combo_box.item + label="No Filter" + name="NoFilter" + value="NoFilter" /> + </combo_box> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="advanced_options_hr" + right="-1" + top_pad="7" + /> + </panel> + <panel + class="llpaneloutfitsnapshotinventory" + follows="left|top" + height="230" + layout="topleft" + left="0" + name="panel_outfit_snapshot_inventory" + filename="panel_outfit_snapshot_inventory.xml" + top_pad="10" + width="215" + /> + <view_border + bevel_style="in" + follows="left|top" + height="1" + left="10" + layout="topleft" + name="status_hr" + width="199" + top_pad="-16"/> + <panel + background_visible="false" + follows="left|top" + font="SansSerifLarge" + halign="center" + height="20" + layout="topleft" + left="10" + length="1" + name="succeeded_panel" + width="198" + top_pad="1" + type="string" + visible="false"> + <text + follows="all" + font="SansSerif" + halign="center" + height="18" + layout="topleft" + left="1" + length="1" + name="succeeded_lbl" + right="-1" + text_color="0.2 0.85 0.2 1" + top="4" + translate="false" + type="string"> + Succeeded + </text> + </panel> + <panel + background_visible="false" + follows="left|top" + font="SansSerifLarge" + halign="center" + height="20" + layout="topleft" + left="10" + length="1" + name="failed_panel" + width="198" + top_delta="0" + type="string" + visible="false"> + <text + follows="all" + font="SansSerif" + halign="center" + height="18" + layout="topleft" + left="1" + length="1" + name="failed_lbl" + right="-1" + text_color="0.95 0.4 0.4 1" + top="4" + translate="false" + type="string"> + Failed + </text> + </panel> + <loading_indicator + follows="left|top" + height="24" + layout="topleft" + name="working_indicator" + left="10" + top_delta="0" + visible="false" + width="24" /> + <text + follows="left|top" + font="SansSerifBold" + height="14" + layout="topleft" + left_pad="3" + length="1" + halign="left" + name="working_lbl" + top_delta="5" + translate="false" + type="string" + visible="false" + width="162"> + Working + </text> + <text + follows="left|top" + font="SansSerifBold" + halign="left" + height="18" + layout="topleft" + left="10" + length="1" + name="refresh_lbl" + text_color="0.95 0.4 0.4 1" + top_delta="0" + translate="false" + type="string" + visible="false" + width="130"> + Refresh to save. + </text> + <ui_ctrl + layout="topleft" + name="thumbnail_placeholder" + top="23" + left="215" + width="400" + height="400" + follows="top|left"/> + <view_border + bevel_style="in" + height="21" + layout="topleft" + name="img_info_border" + top_pad="0" + right="-10" + follows="left|top|right" + left_delta="0"/> + <text + type="string" + font="SansSerifSmall" + length="1" + follows="left|top|right" + height="14" + layout="topleft" + left="220" + right="-20" + halign="left" + name="image_res_text" + top_delta="5" + width="200"> + [WIDTH]px (width) x [HEIGHT]px (height) + </text> + <text + follows="right|top" + font="SansSerifSmall" + height="14" + layout="topleft" + left="-65" + length="1" + halign="right" + name="file_size_label" + top_delta="0" + type="string" + width="50"> + [SIZE] KB + </text> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 2bd3aa8bcc..c6b91a8b2f 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -117,7 +117,7 @@ <slider control_name="IndirectMaxComplexity" - tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll" + tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll" follows="left|top" height="16" initial_value="101" diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index af62c7a9bc..225266af86 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -21,14 +21,6 @@ name="screenshot" top="15" width="220" /> - <check_box - height="15" - label="Use this screenshot" - layout="topleft" - left="8" - name="screen_check" - top_pad="-12" - width="116" /> <text type="string" length="1" @@ -39,7 +31,7 @@ layout="topleft" left="10" name="reporter_title" - top_pad="0" + top_pad="-2" width="100"> Reporter: </text> diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index a80440e844..4473ce0cda 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -154,6 +154,136 @@ </button> </layout_panel> <layout_panel + height="22" + layout="topleft" + left_delta="0" + name="debug_controls" + top_delta="0" + auto_resize="false" + width="585"> + <button + image_overlay="Home_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="Web tests home page" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="1" + name="web_test_home_page" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> + </button> + + <button + image_overlay="Video_URL_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="MPEG4 Video Test" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="27" + name="VLC Plugin Test" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/> + </button> + <button + image_overlay="Video_URL_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="MKV Video Test" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="51" + name="VLC Plugin Test" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/> + </button> + <button + image_overlay="Video_URL_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="WebM Video Test" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="75" + name="VLC Plugin Test" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/> + </button> + <button + image_overlay="Video_URL_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="MP3 audio Test" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="99" + name="VLC Plugin Test" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/> + </button> + <button + image_overlay="Video_URL_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + chrome="true" + tool_tip="FLV Test" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="123" + name="VLC Plugin Test" + top="0" + width="22"> + <button.commit_callback + function="WebContent.TestURL" + parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/> + </button> + </layout_panel> + <layout_panel height="40" layout="topleft" left_delta="0" diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 5d05ecf127..550af03683 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -10,6 +10,7 @@ <file>ArialUni.ttf</file> </os> <os name="Mac"> + <file>ヒラギノ角ゴシック W3.ttc</file> <file>ヒラギノ角ゴ Pro W3.otf</file> <file>ヒラギノ角ゴ ProN W3.otf</file> <file>ヒラギノ明朝 ProN W3.ttc</file> diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml index 324ff3eabd..a69585074c 100644 --- a/indra/newview/skins/default/xui/en/inspect_group.xml +++ b/indra/newview/skins/default/xui/en/inspect_group.xml @@ -66,7 +66,7 @@ Fear the moose! Fear it! And the mongoose too! width="220"> L$123 to join </text> - <icon + <group_icon follows="all" height="38" right="-10" diff --git a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml new file mode 100755 index 0000000000..1b08767edc --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Outfit"> + <menu_item_call + label="Wear - Replace Current Outfit" + layout="topleft" + name="wear_replace"> + <on_click + function="Outfit.WearReplace" /> + <on_enable + function="Outfit.OnEnable" + parameter="wear_replace" /> + <on_visible + function="Outfit.OnVisible" + parameter="wear_replace" /> + </menu_item_call> + <menu_item_call + label="Wear - Add to Current Outfit" + layout="topleft" + name="wear_add"> + <on_click + function="Outfit.WearAdd" /> + <on_enable + function="Outfit.OnEnable" + parameter="wear_add" /> + <on_visible + function="Outfit.OnVisible" + parameter="wear_add" /> + </menu_item_call> + <menu_item_call + label="Take Off - Remove from Current Outfit" + layout="topleft" + name="take_off"> + <on_click + function="Outfit.TakeOff" /> + <on_enable + function="Outfit.OnEnable" + parameter="take_off" /> + <on_visible + function="Outfit.OnVisible" + parameter="take_off" /> + </menu_item_call> + <menu_item_call + label="Upload Photo (L$10)" + layout="topleft" + name="upload_photo"> + <on_click + function="Outfit.UploadPhoto" /> + </menu_item_call> + <menu_item_call + label="Select Photo" + layout="topleft" + name="select_photo"> + <on_click + function="Outfit.SelectPhoto" /> + </menu_item_call> + <menu_item_call + label="Take a Snapshot" + layout="topleft" + name="take_snapshot"> + <on_click + function="Outfit.TakeSnapshot" /> + </menu_item_call> + <menu_item_call + label="Remove Photo" + layout="topleft" + name="remove_photo"> + <on_click + function="Outfit.RemovePhoto" /> + <on_visible + function="Outfit.OnVisible" + parameter="remove_photo" /> + </menu_item_call> + <menu_item_separator name="sepatator1" /> + <menu + height="175" + label="New Clothes" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Clothes" + top_pad="514" + width="125"> + <menu_item_call + label="New Shirt" + layout="topleft" + name="New Shirt"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="shirt" /> + </menu_item_call> + <menu_item_call + label="New Pants" + layout="topleft" + name="New Pants"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="pants" /> + </menu_item_call> + <menu_item_call + label="New Shoes" + layout="topleft" + name="New Shoes"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="shoes" /> + </menu_item_call> + <menu_item_call + label="New Socks" + layout="topleft" + name="New Socks"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="socks" /> + </menu_item_call> + <menu_item_call + label="New Jacket" + layout="topleft" + name="New Jacket"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="jacket" /> + </menu_item_call> + <menu_item_call + label="New Skirt" + layout="topleft" + name="New Skirt"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="skirt" /> + </menu_item_call> + <menu_item_call + label="New Gloves" + layout="topleft" + name="New Gloves"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="gloves" /> + </menu_item_call> + <menu_item_call + label="New Undershirt" + layout="topleft" + name="New Undershirt"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="undershirt" /> + </menu_item_call> + <menu_item_call + label="New Underpants" + layout="topleft" + name="New Underpants"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="underpants" /> + </menu_item_call> + <menu_item_call + label="New Alpha" + layout="topleft" + name="New Alpha"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="alpha" /> + </menu_item_call> + <menu_item_call + label="New Physics" + layout="topleft" + name="New Physics"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="physics" /> + </menu_item_call> + <menu_item_call + label="New Tattoo" + layout="topleft" + name="New Tattoo"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="tattoo" /> + </menu_item_call> + </menu> + <menu + height="85" + label="New Body Parts" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Body Parts" + top_pad="514" + width="118"> + <menu_item_call + label="New Shape" + layout="topleft" + name="New Shape"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="shape" /> + </menu_item_call> + <menu_item_call + label="New Skin" + layout="topleft" + name="New Skin"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="skin" /> + </menu_item_call> + <menu_item_call + label="New Hair" + layout="topleft" + name="New Hair"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="hair" /> + </menu_item_call> + <menu_item_call + label="New Eyes" + layout="topleft" + name="New Eyes"> + <menu_item_call.on_click + function="Outfit.Create" + parameter="eyes" /> + </menu_item_call> + </menu> + <menu_item_separator name="sepatator2" /> + <menu_item_call + label="Edit Outfit" + layout="topleft" + name="edit"> + <on_click + function="Outfit.Edit" /> + <on_visible + function="Outfit.OnVisible" + parameter="edit" /> + </menu_item_call> + <menu_item_call + label="Rename Outfit" + layout="topleft" + name="rename"> + <on_click + function="Outfit.Rename" /> + <on_enable + function="Outfit.OnEnable" + parameter="rename" /> + </menu_item_call> + <menu_item_call + label="Delete Outfit" + layout="topleft" + name="delete"> + <on_click + function="Outfit.Delete" /> + <on_visible + function="Outfit.OnVisible" + parameter="delete" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index dcf2da52f1..a39ee5fddd 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -225,11 +225,11 @@ parameter="message_critical" /> </menu_item_call> <menu_item_call - label="Web Content Floater Debug Test" - name="Web Content Floater Debug Test"> + label="Media Browser" + name="Media Browser"> <menu_item_call.on_click function="Advanced.WebContentTest" - parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> + parameter="http://google.com"/> </menu_item_call> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml index 3b8ace6308..7faa4f3d71 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -39,8 +39,35 @@ function="Gear.OnVisible" parameter="take_off" /> </menu_item_call> - - <menu_item_separator name="sepatator1" /> + <menu_item_call + label="Upload Photo (L$10)" + layout="topleft" + name="upload_photo"> + <on_click + function="Gear.UploadPhoto" /> + </menu_item_call> + <menu_item_call + label="Select Photo" + layout="topleft" + name="select_photo"> + <on_click + function="Gear.SelectPhoto" /> + </menu_item_call> + <menu_item_call + label="Take a Snapshot" + layout="topleft" + name="take_snapshot"> + <on_click + function="Gear.TakeSnapshot" /> + </menu_item_call> + <menu_item_call + label="Remove Photo" + layout="topleft" + name="remove_photo"> + <on_click + function="Gear.RemovePhoto" /> + </menu_item_call> + <menu_item_separator name="sepatator1" /> <!-- copied (with minor modifications) from menu_inventory_add.xml --> <!-- *TODO: generate dynamically? --> <menu @@ -234,4 +261,15 @@ function="Gear.OnVisible" parameter="delete" /> </menu_item_call> + <menu_item_separator name="sepatator3" /> + <menu_item_check + label="Sort Folders Always by Name" + layout="topleft" + name="sort_folders_by_name"> + <on_click + function="Gear.SortByName" /> + <on_check + function="CheckControl" + parameter="OutfitGallerySortByName" /> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b189d1038f..8a649a57d1 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3141,30 +3141,13 @@ label="UI" name="UI" tear_off="true"> - <!-- <menu_item_check - label="New Bottom Bar" - name="New Bottom Bar"> - <menu_item_check.on_check - function="CheckControl" - parameter="BottomPanelNew" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="BottomPanelNew" /> - </menu_item_check>--> - <menu_item_call - label="Media Browser Test" - name="Web Browser Test"> - <menu_item_call.on_click - function="Advanced.WebBrowserTest" - parameter="http://secondlife.com/app/search/slurls.html"/> - </menu_item_call> <menu_item_call - label="Web Content Browser" - name="Web Content Browser" - shortcut="control|shift|Z"> + label="Media Browser" + name="Media Browser" + shortcut="control|alt|shift|Z"> <menu_item_call.on_click function="Advanced.WebContentTest" - parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> + parameter="http://google.com"/> </menu_item_call> <menu_item_call label="FB Connect Test" diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml index 44b2727671..75c1de24aa 100644 --- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml +++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml @@ -28,6 +28,13 @@ function="Wearing.Edit" /> </menu_item_call> <menu_item_call + label="Edit" + layout="topleft" + name="edit_item"> + <on_click + function="Wearing.EditItem" /> + </menu_item_call> + <menu_item_call label="Show Original" layout="topleft" name="show_original"> diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 7cb4a6e53b..8d8d546b24 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -130,10 +130,21 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </scheme> - <mimetype name="blank"> + <scheme name="libvlc"> + <label name="libvlc_label"> + LibVLC supported media + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_libvlc + </impl> + </scheme> + <mimetype name="blank"> <label name="blank_label"> - None - </label> @@ -163,7 +174,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/*"> @@ -174,7 +185,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="image/*"> @@ -196,7 +207,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="application/javascript"> @@ -218,7 +229,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_cef </impl> </mimetype> <mimetype name="application/pdf"> @@ -295,7 +306,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_cef </impl> </mimetype> <mimetype name="audio/mpeg"> @@ -306,7 +317,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="audio/x-aiff"> @@ -317,7 +328,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="audio/x-wav"> @@ -328,7 +339,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -438,7 +449,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/mp4"> @@ -449,10 +460,21 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> - <mimetype menu="1" name="video/quicktime"> + <mimetype name="application/octet-stream"> + <label name="video/octet-stream"> + Movie + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_libvlc + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> <label name="video/quicktime_label"> Movie (QuickTime) </label> @@ -460,7 +482,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -471,7 +493,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -482,7 +504,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -493,7 +515,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_cef </impl> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml index 84aeaf3b54..7188b1e699 100644 --- a/indra/newview/skins/default/xui/en/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -130,7 +130,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </scheme> <mimetype name="blank"> @@ -163,7 +163,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/*"> @@ -174,7 +174,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="image/*"> @@ -196,7 +196,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="application/javascript"> @@ -218,7 +218,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="application/pdf"> @@ -295,7 +295,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="audio/mpeg"> @@ -306,7 +306,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="audio/x-aiff"> @@ -317,7 +317,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="audio/x-wav"> @@ -328,7 +328,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -438,7 +438,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/mp4"> @@ -449,7 +449,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype menu="1" name="video/quicktime"> @@ -460,7 +460,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -471,7 +471,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -482,7 +482,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -493,7 +493,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_libvlc </impl> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dfde38bc5f..804235518e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -832,6 +832,13 @@ If you no longer wish to have these abilities granted to this role, disable them </notification> <notification + icon="notify.tga" + name="GroupBanUserOnBanlist" + type="notify"> +Some residents have not been sent an invite due to being banned from the group. + </notification> + + <notification icon="alertmodal.tga" name="AttachmentDrop" type="alertmodal"> @@ -1476,6 +1483,7 @@ Save Changes? icon="alertmodal.tga" name="DeleteNotecard" type="alertmodal"> + <unique/> Delete Notecard? <tag>confirm</tag> <usetemplate @@ -1631,52 +1639,14 @@ Visit [_URL] for more information? <notification icon="alertmodal.tga" - name="IntelOldDriver" + name="OldGPUDriver" type="alertmodal"> There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - Visit [_URL] to check for driver updates? - <tag>confirm</tag> - <url option="0" name="url"> - http://www.intel.com/p/en_US/support/detect/graphics - </url> - <usetemplate - ignoretext="My graphics driver is out of date" - name="okcancelignore" - notext="No" - yestext="Yes"/> - <tag>fail</tag> - </notification> - - <notification - icon="alertmodal.tga" - name="AMDOldDriver" - type="alertmodal"> - There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - - Visit [_URL] to check for driver updates? - <tag>confirm</tag> - <url option="0" name="url"> - http://support.amd.com/us/Pages/AMDSupportHub.aspx - </url> - <usetemplate - ignoretext="My graphics driver is out of date" - name="okcancelignore" - notext="No" - yestext="Yes"/> - <tag>fail</tag> - </notification> - - <notification - icon="alertmodal.tga" - name="NVIDIAOldDriver" - type="alertmodal"> - There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. - - Visit [_URL] to check for driver updates? + Visit [URL] to check for driver updates? <tag>confirm</tag> <url option="0" name="url"> - http://www.nvidia.com/Download/index.aspx?lang=en-us + [URL] </url> <usetemplate ignoretext="My graphics driver is out of date" @@ -1686,7 +1656,6 @@ Visit [_URL] for more information? <tag>fail</tag> </notification> - <notification icon="alertmodal.tga" name="UnknownGPU" @@ -3349,6 +3318,23 @@ Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Renderin <context>AgentComplexityNotice</context> </unique> Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 avatar complexity] is [AGENT_COMPLEXITY]. + <usetemplate + ignoretext="Warn me about my avatar complexity changes" + name="notifyignore"/> + </notification> + + <notification + icon = "notifytip.tga" + name = "HUDComplexityWarning" + type = "notifytip" + log_to_chat = "false"> + <unique combine = "cancel_old"> + <context>HUDComplexityWarning</context> + </unique> + [HUD_REASON], it is likely to negatively affect your performance. + <usetemplate + ignoretext="Warn me when my HUD complexity is too high" + name="notifyignore"/> </notification> <notification @@ -3665,6 +3651,13 @@ Can't add estate owner to estate 'Banned Resident' list. <notification icon="alertmodal.tga" + name="ProblemAddingEstateManagerBanned" + type="alertmodal"> +Unable to add banned resident to estate manager list. + </notification> + + <notification + icon="alertmodal.tga" name="CanNotChangeAppearanceUntilLoaded" type="alertmodal"> Can't change appearance until clothing and shape are loaded. @@ -4059,6 +4052,18 @@ Do you want to open your Web browser to view this content? <notification icon="alertmodal.tga" + name="SystemUIScaleFactorChanged" + type="alertmodal"> +System UI size factor has changed since last run. Do you want to open UI size adjustment settings page? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="WebLaunchJoinNow" type="alertmodal"> Go to your [http://secondlife.com/account/ Dashboard] to manage your account? @@ -4178,6 +4183,14 @@ Leave Group? </notification> <notification + icon="notify.tga" + name="GroupDepart" + type="notify"> +You have left the group '[group_name]'. + <tag>group</tag> + </notification> + + <notification icon="alertmodal.tga" name="OwnerCannotLeaveGroup" type="alertmodal"> @@ -4189,6 +4202,17 @@ Leave Group? </notification> <notification + icon="alertmodal.tga" + name="GroupDepartError" + type="alertmodal"> + Unable to leave group. + <tag>group</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alert.tga" name="ConfirmKick" type="alert"> @@ -5310,6 +5334,17 @@ There are too many prims selected. Please select [MAX_PRIM_COUNT] or fewer prim </notification> <notification + icon="alertmodal.tga" + name="TooManyScriptsSelected" + type="alertmodal"> +Too many scripts in the objects selected. Please select fewer objects and try again + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alertmodal.tga" name="ProblemImportingEstateCovenant" type="alertmodal"> @@ -5728,6 +5763,17 @@ Warning: The 'Pay object' click action has been set, but it will only <notification icon="alertmodal.tga" + name="PaymentBlockedButtonMismatch" + type="alertmodal"> + Payment stopped: the price paid does not match any of the pay buttons set for this object. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="OpenObjectCannotCopy" type="alertmodal"> There are no items in this object that you are allowed to copy. @@ -5830,7 +5876,20 @@ You cannot undo this action. notext="Cancel" yestext="Unlink"/> </notification> - + + <notification + icon="alertmodal.tga" + name="HelpReportAbuseConfirm" + type="alertmodal"> + <unique/> +Thank you for taking the time to inform us of this issue. +We will review your report for possible violations and take +the appropriate action. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + <notification icon="alertmodal.tga" name="HelpReportAbuseSelectCategory" @@ -7339,7 +7398,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th name="TeleportOffered_MaturityExceeded" 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]” @@ -7364,7 +7424,8 @@ This region contains [REGION_CONTENT_MATURITY] content, but your current prefere name="TeleportOffered_MaturityBlocked" log_to_im="true" log_to_chat="false" - type="notifytip"> + type="notifytip" + sound="UISndNewIncomingIMSession"> [NAME_SLURL] has offered to teleport you to their location: “[MESSAGE]” @@ -8804,23 +8865,6 @@ Click and drag anywhere on the world to rotate your view </notification> <notification - name="PopupAttempt" - icon="Popup_Caution" - type="browser"> - A pop-up was prevented from opening. - <form name="form"> - <ignore name="ignore" - control="MediaEnablePopups" - invert_control="true" - text="Enable all pop-ups"/> - <button default="true" - index="0" - name="open" - text="Open pop-up window"/> - </form> - </notification> - - <notification icon="alertmodal.tga" name="SOCKS_NOT_PERMITTED" type="alertmodal"> @@ -9802,6 +9846,14 @@ Can't move object '[OBJECT_NAME]' to <notification icon="alertmodal.tga" + name="NoParcelPermsNoObject" + type="notify"> + <tag>fail</tag> +Copy failed because you lack access to that parcel. + </notification> + + <notification + icon="alertmodal.tga" name="CantMoveObjectRegionVersion" type="notify"> <tag>fail</tag> @@ -9837,6 +9889,17 @@ You don't have permission to modify that object <notification icon="alertmodal.tga" + name="TooMuchObjectInventorySelected" + type="alertmodal"> + <tag>fail</tag> + Too many objects with large inventory are selected. Please select fewer objects and try again. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="CantEnablePhysObjContributesToNav" type="notify"> <tag>fail</tag> @@ -9934,6 +9997,22 @@ Cannot save to object contents: This would modify the attachment permissions. <notification icon="alertmodal.tga" + name="AttachmentHasTooMuchInventory" + type="notify"> + <tag>fail</tag> +Your attachments contain too much inventory to add more. + </notification> + + <notification + icon="alertmodal.tga" + name="IllegalAttachment" + type="notify"> + <tag>fail</tag> +The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead. + </notification> + + <notification + icon="alertmodal.tga" name="TooManyScripts" type="notify"> <tag>fail</tag> @@ -10183,6 +10262,22 @@ You have been teleported by the object '[OBJECT_NAME]' owned by an unknown user. <notification icon="alertmodal.tga" + name="StandDeniedByObject" + type="notify"> + <tag>fail</tag> +'[OBJECT_NAME]' will not allow you to stand at this time. + </notification> + + <notification + icon="alertmodal.tga" + name="ResitDeniedByObject" + type="notify"> + <tag>fail</tag> +'[OBJECT_NAME]' will not allow you to change your seat at this time. + </notification> + + <notification + icon="alertmodal.tga" name="CantCreateObjectRegionFull" type="notify"> <tag>fail</tag> @@ -10972,6 +11067,14 @@ Money transfers to objects are currently disabled in this region. <notification icon="alertmodal.tga" + name="DroppedMoneyTransferRequest" + type="notify"> + <tag>fail</tag> +Unable to make payment due to system load. + </notification> + + <notification + icon="alertmodal.tga" name="CantPayNoAgent" type="notify"> <tag>fail</tag> @@ -11068,4 +11171,16 @@ Cannot create large prims that intersect other players. Please re-try when othe yestext="OK"/> </notification> + + <notification + icon="alert.tga" + name="OutfitPhotoLoadError" + type="alertmodal"> + [REASON] + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml new file mode 100644 index 0000000000..c1272c6bf8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + bg_alpha_color="DkGray" + border="false" + follows="all" + height="430" + name="Outfit Gallery" + layout="topleft" + left="0" + top="0" + width="318"> + <string name="outfit_photo_string"> + Photo of "[OUTFIT_NAME]" outfit + </string> + <string name="no_outfits_msg"> + You don't have any outfits yet. Try [secondlife:///app/search/all/ Search] + </string> + <string name="no_matched_outfits_msg"> + Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]. + </string> + <text + type="string" + clip_partial="false" + follows="left|top" + layout="topleft" + left="13" + name="no_outfits_txt" + top="0" + height="32" + valign="center" + parse_urls="true" + wrap="true"> + Searching... + </text> + <scroll_container + border="true" + bevel_style="none" + follows="all" + height="400" + width="312" + min_width="312" + layout="topleft" + left="4" + top="0" + name="gallery_scroll_panel" + opaque="false" + top_pad="0"> + <!--outfit_gallery_item + layout="topleft" + left="10" + name="preview_outfit1" + height="175" + width="150" + follows="left|top"/--> + <!--layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="0" name="top_gallery_stack" orientation="horizontal"> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + </layout_stack> + <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="190" name="top_gallery_stack" orientation="horizontal"> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + </layout_stack> + <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="380" name="top_gallery_stack" orientation="horizontal"> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel"> + <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/> + </layout_panel> + </layout_stack--> + <!--</panel>--> + </scroll_container> + <panel + background_visible="true" + follows="bottom|left|right" + height="28" + layout="topleft" + left="4" + top_pad="0" + visible="true" + name="bottom_panel" + width="312"> + <menu_button + follows="bottom|left" + tool_tip="Show additional options" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + layout="topleft" + left="0" + name="options_gear_btn" + top="1" + width="31" /> + <icon + follows="bottom|left|right" + height="25" + image_name="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="dummy_icon" + width="243"/> + <button + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + layout="topleft" + left_pad="1" + name="trash_btn" + tool_tip="Delete selected outfit" + width="31"/> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml new file mode 100644 index 0000000000..e3f0f1128b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="false" + background_opaque="false" + bg_alpha_color="FrogGreen" + bg_opaque_color="FrogGreen" + border="false" + bevel_style="none" + follows="left|top" + height="169" + width="150" + name="gallery_item_panel" + layout="topleft" + left="0" + top="0" + > + <string name="worn_string"> + (worn) + </string> + <icon + left="1" + top="0" + layout="topleft" + name="preview_outfit" + height="149" + width="147" + follows="left|top" + visible="true" + image_name="Default_Outfit_Photo" + /> + <panel + background_visible="false" + background_opaque="true" + bg_opaque_color="OutfitGalleryItemSelected" + border="false" + bevel_style="none" + follows="left|top" + left="0" + top="149" + height="25" + width="148" + name="text_bg_panel" + > + <text + read_only="true" + length="1" + follows="left|top" + left="1" + height="10" + layout="topleft" + name="outfit_name" + top="2" + width="150" + use_ellipses="true"> + Summer hipster, Pierce Pierce Pierce Pierce + </text> + <text + read_only="true" + length="1" + follows="left|top" + left="1" + height="10" + layout="topleft" + name="outfit_worn_text" + top="12" + width="150"> + (worn) + </text> + </panel> + +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml new file mode 100644 index 0000000000..800faabc2a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_outfit_snapshot_inventory" + width="490"> + <icon + follows="top|left" + height="18" + image_name="Snapshot_Inventory" + layout="topleft" + left="12" + mouse_opaque="true" + name="title_icon" + top="6" + width="18" /> + <text + follows="top|left|right" + font="SansSerifBold" + height="14" + layout="topleft" + left_pad="12" + length="1" + name="title" + right="-10" + text_color="white" + type="string" + top_delta="3"> + Inventory + </text> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="9" + layout="topleft" + name="hr" + right="-5" + top_pad="5" + /> + <text + follows="top|left" + font="SansSerif" + height="56" + layout="topleft" + left="10" + length="1" + name="hint_lbl" + top_pad="6" + width="200" + type="string" + word_wrap="true"> + Uploading an image to your inventory costs L$[UPLOAD_COST]. + </text> + <button + follows="right|bottom" + height="23" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-5" + top="337" + width="97"> + <button.commit_callback + function="Inventory.SaveOutfitCancel" /> + </button> + <button + follows="left|bottom" + height="23" + label="UPLOAD L$10" + layout="topleft" + left="10" + name="save_btn" + top_delta="0" + width="97"> + <button.commit_callback + function="Inventory.SaveOutfitPhoto" /> + </button> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 405d9513db..ff0714adbb 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -33,6 +33,17 @@ top="8" width="315"> <panel + class="outfit_gallery" + filename="panel_outfit_gallery.xml" + height="520" + name="outfit_gallery_tab" + background_visible="true" + help_topic="outfit_gallery_tab" + follows="all" + label="OUTFIT GALLERY" + layout="topleft" + width="315" /> + <panel class="outfits_list" filename="panel_outfits_list.xml" height="520" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index d85b778db2..42a7974316 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -9,6 +9,26 @@ name="Wearing" top="0" width="312"> +<panel.string + name="no_attachments"> + No attachments worn. + </panel.string> + <accordion + fit_parent="true" + follows="all" + height="400" + layout="topleft" + left="0" + single_expansion="true" + top="0" + name="wearables_accordion" + background_visible="true" + bg_alpha_color="DkGray2" + width="309"> + <accordion_tab + layout="topleft" + name="tab_wearables" + title="Wearables"> <wearable_items_list follows="all" height="400" @@ -20,6 +40,27 @@ top="0" width="309" worn_indication_enabled="false" /> + </accordion_tab> + <accordion_tab + layout="topleft" + name="tab_temp_attachments" + title="Temporary attachments"> + <scroll_list + draw_heading="false" + left="3" + width="309" + height="400" + follows="all" + name="temp_attachments_list"> + <scroll_list.columns + name="icon" + width="15" /> + <scroll_list.columns + name="text" + width="210" /> + </scroll_list> + </accordion_tab> + </accordion> <panel background_visible="true" follows="bottom|left|right" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 4a5117adac..0deb1d03cf 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -138,7 +138,7 @@ initial_value="1" layout="topleft" left_pad="0" - max_val="2.0" + max_val="4.0" min_val="0.75" name="ui_scale_slider" top_pad="-14" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index a9b8e197bc..e002d9dee1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -233,7 +233,7 @@ <slider control_name="IndirectMaxComplexity" - tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll" + tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll" follows="left|top" height="16" initial_value="101" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 0b605cf6f7..c20f9b2c51 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -273,6 +273,18 @@ name="update_willing_to_test" width="400" top_pad="5"/> + <check_box + top_delta="4" + enabled="true" + follows="left|top" + height="14" + control_name="UpdaterShowReleaseNotes" + label="Show Release Notes after update" + left_delta="0" + mouse_opaque="true" + name="update_show_release_notes" + width="400" + top_pad="5"/> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index eb67d07601..068e4420bc 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -374,9 +374,11 @@ layout="topleft" tool_tip="Movie play progress" width="200"> - <slider_bar.commit_callback - function="MediaCtrl.JumpProgress" /> - </slider_bar> + <slider_bar.mouse_down_callback + function="MediaCtrl.MouseDown" /> + <slider_bar.mouse_up_callback + function="MediaCtrl.MouseUp" /> + </slider_bar> </layout_panel> <layout_panel name="skip_back" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b19c6756bc..00237d493a 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -25,7 +25,7 @@ [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([CHANNEL]) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] </string> - <string name="BuildConfig">Build Configuration [BUILD_CONFIG]</string> + <string name="BuildConfig">Build Configuration [BUILD_CONFIG] [ADDRESS_SIZE] bits</string> <string name="AboutPosition"> You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at <nolink>[HOSTNAME]</nolink> ([HOSTIP]) @@ -51,13 +51,14 @@ OpenGL Version: [OPENGL_VERSION] J2C Decoder Version: [J2C_VERSION] Audio Driver Version: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF Version: [LLCEFLIB_VERSION] +LibVLC Version: [LIBVLC_VERSION] Voice Server Version: [VOICE_VERSION] </string> <string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string> <string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string> <string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string> <string name="BuildConfiguration">Build Configuration</string> - + <!-- progress --> <string name="ProgressRestoring">Restoring...</string> <string name="ProgressChangingResolution">Changing resolution...</string> @@ -499,6 +500,7 @@ Please try logging in again in a minute.</string> <string name="TeleportYourAgent">Teleport you</string> <string name="ManageEstateSilently">Manage your estates silently</string> <string name="ChangeYourDefaultAnimations">Change your default animations</string> + <string name="ForceSitAvatar">Force your avatar to sit</string> <string name="NotConnected">Not Connected</string> <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> @@ -2499,6 +2501,15 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f <string name="av_render_most_of">You may not be rendered by most of those around you.</string> <string name="av_render_anyone">You may not be rendered by anyone around you.</string> + <!-- HUD complexity rendering messages, see llavatarrendernotifier. --> + <string name="hud_description_total">Your HUD</string> + <string name="hud_name_with_joint">[OBJ_NAME] (worn on [JNT_NAME])</string> + <string name="hud_render_memory_warning">[HUD_DETAILS] uses a lot of texture memory</string> + <string name="hud_render_cost_warning">[HUD_DETAILS] contains a lot of expensive objects and textures</string> + <string name="hud_render_heavy_textures_warning">[HUD_DETAILS] contains a lot of large textures</string> + <string name="hud_render_cramped_warning">[HUD_DETAILS] contains too many objects</string> + <string name="hud_render_textures_warning">[HUD_DETAILS] contains too many textures</string> + <!-- AgeYearsA = singular, AgeYearsB = plural, AgeYearsC = plural for non-English languages like Russian @@ -2566,7 +2577,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f <string name="SaveComplete">Save complete.</string> <string name="UploadFailed">File upload failed: </string> <string name="ObjectOutOfRange">Script (object out of range)</string> - + <string name="ScriptWasDeleted">Script (deleted from inventory)</string> + <!-- god tools --> <string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string> @@ -2834,6 +2846,12 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh <string name="Multiple Media">Multiple Media</string> <string name="Play Media">Play/Pause Media</string> + <!-- Drivers support/update pages --> + <string name="IntelDriverPage">http://www.intel.com/p/en_US/support/detect/graphics</string> + <string name="NvidiaDriverPage">http://www.nvidia.com/Download/index.aspx?lang=en-us</string> + <string name="AMDDriverPage">http://support.amd.com/us/Pages/AMDSupportHub.aspx</string> + + <!-- OSMessageBox messages --> <string name="MBCmdLineError"> An error was found parsing the command line. @@ -3807,6 +3825,9 @@ Abuse Report</string> <string name="DefaultMimeType">none/none</string> <string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string> + <string name="outfit_photo_load_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please resize or use another image</string> + <string name="outfit_photo_select_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please select another texture</string> + <string name="outfit_photo_verify_dimensions_error">Cannot verify photo dimensions. Please wait until photo size is displayed in picker</string> <!-- language specific white-space characters, delimiters, spacers, item separation symbols --> <string name="sentences_separator" value=" "></string> diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml index 8ea56c5262..8aaa236475 100644 --- a/indra/newview/skins/default/xui/es/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">[AMT] L$</panel.string> - <panel left="-410" name="balance_bg" width="200"> + <panel left="-431" name="balance_bg" width="200"> <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="L$??"/> <button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/> diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml index e2f05a525e..fef0379c2c 100644 --- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">[AMT] L$</panel.string> - <panel left="-405" name="balance_bg" width="195"> + <panel left="-426" name="balance_bg" width="195"> <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="L$ ??"/> <button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/> <button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/> diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml index 83d2ae5bab..295ca8d9f2 100644 --- a/indra/newview/skins/default/xui/it/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> - <panel left="-405" name="balance_bg" width="195"> + <panel left="-426" name="balance_bg" width="195"> <text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ ??"/> <button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/> <button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/> diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml index 2e1446d450..3f3845e491 100644 --- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt])</panel.string> <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> - <panel left="-370" name="balance_bg" width="160"> + <panel left="-391" name="balance_bg" width="160"> <text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$??"/> <button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/> <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く" width="40"/> diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml index cfe52ff404..c35863734f 100644 --- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> - <panel left="-410" name="balance_bg" width="200"> + <panel left="-431" name="balance_bg" width="200"> <text name="balance" tool_tip="Atualizar saldo de L$" value="L$??"/> <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> <button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/> diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml index 630925fa60..49c48ae654 100644 --- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour, datetime, slt]:[min, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> - <panel left="-450" name="balance_bg" width="240"> + <panel left="-471" name="balance_bg" width="240"> <text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$??"/> <button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/> <button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/> diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml index 9e2669ec2b..7c7bfc7e14 100644 --- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml @@ -5,7 +5,7 @@ <panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string> <panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string> <panel.string name="buycurrencylabel">L$ [AMT]</panel.string> - <panel left="-425" name="balance_bg" width="215"> + <panel left="-446" name="balance_bg" width="215"> <text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$??"/> <button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/> <button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/> diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 1b0334498e..b603157ca7 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -136,6 +136,7 @@ void LLGridManager::addSystemGrid(const std::string& label, const std::string& helper, const std::string& login_page, const std::string& update_url_base, + const std::string& web_profile_url, const std::string& login_id) { } diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 6b0be29c2d..f1f69f33f1 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -29,6 +29,13 @@ #include "../llversioninfo.h" +// LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The +// macro expands to the string name of the channel, but without quotes. We +// need to turn it into a quoted string. This macro trick does that. +#define stringize_inner(x) #x +#define stringize_outer(x) stringize_inner(x) +#define ll_viewer_channel stringize_outer(LL_VIEWER_CHANNEL) + namespace tut { struct versioninfo @@ -50,7 +57,7 @@ namespace tut mShortVersion = stream.str(); stream.str(""); - stream << LL_VIEWER_CHANNEL + stream << ll_viewer_channel << " " << mVersion; mVersionAndChannel = stream.str(); @@ -89,7 +96,7 @@ namespace tut LL_VIEWER_VERSION_BUILD); ensure_equals("Channel version", LLVersionInfo::getChannel(), - LL_VIEWER_CHANNEL); + ll_viewer_channel); ensure_equals("Version String", LLVersionInfo::getVersion(), mVersion); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index f3d89bb866..589d74a014 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -287,7 +287,8 @@ class ViewerManifest(LLManifest): random.shuffle(names) return ', '.join(names) -class Windows_i686_Manifest(ViewerManifest): + +class WindowsManifest(ViewerManifest): def final_exe(self): return self.app_name_oneword()+".exe" @@ -338,7 +339,7 @@ class Windows_i686_Manifest(ViewerManifest): print "Doesn't exist:", src def construct(self): - super(Windows_i686_Manifest, self).construct() + super(WindowsManifest, self).construct() pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") @@ -386,10 +387,7 @@ class Windows_i686_Manifest(ViewerManifest): print "Skipping fmodex audio library(assuming other audio engine)" # For textures - if self.args['configuration'].lower() == 'debug': - self.path("openjpegd.dll") - else: - self.path("openjpeg.dll") + self.path("openjpeg.dll") # These need to be installed as a SxS assembly, currently a 'private' assembly. # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx @@ -444,6 +442,11 @@ class Windows_i686_Manifest(ViewerManifest): self.path("media_plugin_cef.dll") self.end_prefix() + # Media plugins - LibVLC + if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_libvlc.dll") + self.end_prefix() + # winmm.dll shim if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""): self.path("winmm.dll") @@ -550,6 +553,12 @@ class Windows_i686_Manifest(ViewerManifest): self.path("zh-TW.pak") self.end_prefix() + if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): + self.path("libvlc.dll") + self.path("libvlccore.dll") + self.path("plugins/") + self.end_prefix() + # pull in the crash logger and updater from other projects # tag:"crash-logger" here as a cue to the exporter self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], @@ -688,7 +697,17 @@ class Windows_i686_Manifest(ViewerManifest): self.package_file = installer_file -class Darwin_i386_Manifest(ViewerManifest): +class Windows_i686_Manifest(WindowsManifest): + # specialize when we must + pass + + +class Windows_x86_64_Manifest(WindowsManifest): + # specialize when we must + pass + + +class DarwinManifest(ViewerManifest): def is_packaging_viewer(self): # darwin requires full app bundle packaging even for debugging. return True @@ -714,7 +733,7 @@ class Darwin_i386_Manifest(ViewerManifest): # most everything goes in the Resources directory if self.prefix(src="", dst="Resources"): - super(Darwin_i386_Manifest, self).construct() + super(DarwinManifest, self).construct() if self.prefix("cursors_mac"): self.path("*.tif") @@ -1041,6 +1060,20 @@ class Darwin_i386_Manifest(ViewerManifest): self.package_file = finalname self.remove(sparsename) + +class Darwin_i386_Manifest(DarwinManifest): + pass + + +class Darwin_i686_Manifest(DarwinManifest): + """alias in case arch is passed as i686 instead of i386""" + pass + + +class Darwin_x86_64_Manifest(DarwinManifest): + pass + + class LinuxManifest(ViewerManifest): def construct(self): super(LinuxManifest, self).construct() @@ -1089,8 +1122,18 @@ class LinuxManifest(ViewerManifest): # plugins if self.prefix(src="", dst="bin/llplugin"): self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so") self.end_prefix("bin/llplugin") + if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): + self.path( "plugins.dat" ) + self.path( "*/*.so" ) + self.end_prefix() + + if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"): + self.path( "libvlc*.so*" ) + self.end_prefix() + # llcommon if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"): print "Skipping llcommon.so (assuming llcommon was linked statically)" @@ -1144,7 +1187,7 @@ class LinuxManifest(ViewerManifest): def strip_binaries(self): if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure class Linux_i686_Manifest(LinuxManifest): def construct(self): |
