From 6abecf1228010d83c2df8d14057950fb51e37320 Mon Sep 17 00:00:00 2001 From: palange Date: Mon, 1 Feb 2010 11:23:30 -0800 Subject: pushing to private repo to move to windows development. --- indra/newview/llappviewer.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index becc30832d..21d908035f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -324,10 +324,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; -std::string gLoginPage; -std::vector gLoginURIs; -static std::string gHelperURI; - LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() -- cgit v1.2.3 From 58f813a136a5a889e01b39e96714af91402321ba Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Tue, 2 Feb 2010 14:45:42 -0800 Subject: merge --- indra/newview/CMakeLists.txt | 38 +-- indra/newview/app_settings/ignorable_dialogs.xml | 15 +- indra/newview/app_settings/settings.xml | 87 +++---- indra/newview/character/avatar_lad.xml | 12 +- indra/newview/llagent.cpp | 27 ++- indra/newview/llagent.h | 1 + indra/newview/llagentwearables.cpp | 286 ++++++++++++++++++++--- indra/newview/llappearancemgr.cpp | 174 ++++++++++++-- indra/newview/llappearancemgr.h | 17 +- indra/newview/llappviewer.cpp | 59 ++--- indra/newview/llavataractions.cpp | 10 +- indra/newview/llavatariconctrl.cpp | 4 +- indra/newview/llavatarlist.cpp | 19 +- indra/newview/llavatarlist.h | 4 + indra/newview/llavatarlistitem.cpp | 266 +++++++++++++-------- indra/newview/llavatarlistitem.h | 71 ++++-- indra/newview/llbottomtray.cpp | 96 ++++++-- indra/newview/llbottomtray.h | 17 +- indra/newview/llcallfloater.cpp | 164 ++++--------- indra/newview/llcallfloater.h | 23 +- indra/newview/llchatbar.cpp | 3 +- indra/newview/llchathistory.cpp | 65 +++--- indra/newview/llchathistory.h | 1 + indra/newview/llchatitemscontainerctrl.cpp | 64 +++-- indra/newview/llchatitemscontainerctrl.h | 1 + indra/newview/llchiclet.cpp | 67 +++++- indra/newview/llchiclet.h | 21 +- indra/newview/llcompilequeue.cpp | 15 +- indra/newview/lldateutil.cpp | 7 +- indra/newview/lldrawpoolbump.cpp | 4 +- indra/newview/lldrawpoolwlsky.cpp | 21 +- indra/newview/lldrawpoolwlsky.h | 2 +- indra/newview/llfasttimerview.cpp | 6 +- indra/newview/llfavoritesbar.cpp | 38 +-- indra/newview/llfavoritesbar.h | 11 +- indra/newview/llfirstuse.cpp | 15 +- indra/newview/llfirstuse.h | 7 + indra/newview/llfloaterabout.cpp | 19 +- indra/newview/llfloaterbulkpermission.cpp | 1 - indra/newview/llfloatercamera.cpp | 25 +- indra/newview/llfloatercamera.h | 4 +- indra/newview/llfloaterchat.cpp | 33 ++- indra/newview/llfloaterchat.h | 2 +- indra/newview/llfloaterchatterbox.cpp | 28 +-- indra/newview/llfloatergesture.cpp | 12 +- indra/newview/llfloatergesture.h | 2 +- indra/newview/llfloatergroups.cpp | 9 +- indra/newview/llfloaterinventory.cpp | 4 +- indra/newview/llfloaterland.cpp | 7 +- indra/newview/llfloaterland.h | 1 - indra/newview/llfloatermediasettings.cpp | 10 +- indra/newview/llfloaterpreference.cpp | 60 ++++- indra/newview/llfloaterpreference.h | 6 +- indra/newview/llfloaterregioninfo.cpp | 7 +- indra/newview/llfloaterscriptlimits.cpp | 101 ++++++-- indra/newview/llfloaterscriptlimits.h | 14 +- indra/newview/llfloatersearch.cpp | 39 ++++ indra/newview/llfloatersettingsdebug.cpp | 2 +- indra/newview/llfloatersnapshot.cpp | 4 +- indra/newview/llfloatertools.cpp | 60 +++-- indra/newview/llfloatervoicedevicesettings.cpp | 38 +-- indra/newview/llfloaterworldmap.cpp | 76 +++--- indra/newview/llfloaterworldmap.h | 5 +- indra/newview/llfolderview.cpp | 36 +-- indra/newview/llfolderview.h | 2 +- indra/newview/llfoldervieweventlistener.h | 1 + indra/newview/llfolderviewitem.cpp | 133 ++++++----- indra/newview/llfolderviewitem.h | 20 +- indra/newview/llgesturemgr.cpp | 10 + indra/newview/llgesturemgr.h | 2 + indra/newview/llgroupactions.cpp | 10 +- indra/newview/llgrouplist.cpp | 5 +- indra/newview/llhudtext.cpp | 6 +- indra/newview/llimfloater.cpp | 130 +++++++---- indra/newview/llimfloater.h | 5 +- indra/newview/llimfloatercontainer.cpp | 11 + indra/newview/llimfloatercontainer.h | 6 +- indra/newview/llimpanel.cpp | 2 +- indra/newview/llimview.cpp | 112 +++++---- indra/newview/llimview.h | 17 +- indra/newview/llinspect.h | 2 +- indra/newview/llinspectavatar.cpp | 103 +++++--- indra/newview/llinspectobject.cpp | 20 +- indra/newview/llinventorybridge.cpp | 143 ++++-------- indra/newview/llinventorybridge.h | 1 + indra/newview/llinventoryfunctions.cpp | 3 +- indra/newview/llinventorymodel.cpp | 106 ++++++++- indra/newview/llinventorymodel.h | 33 +++ indra/newview/llinventoryobserver.cpp | 35 ++- indra/newview/llinventorypanel.cpp | 53 ++--- indra/newview/llinventorypanel.h | 2 +- indra/newview/lllandmarklist.cpp | 7 + indra/newview/lllocationhistory.cpp | 6 + indra/newview/lllogchat.cpp | 4 - indra/newview/llmanip.cpp | 2 +- indra/newview/llmediactrl.cpp | 272 +++++++++++---------- indra/newview/llmediactrl.h | 1 - indra/newview/llmenucommands.cpp | 3 +- indra/newview/llmorphview.cpp | 4 +- indra/newview/llmutelist.cpp | 7 +- indra/newview/llnamebox.cpp | 35 ++- indra/newview/llnamebox.h | 6 + indra/newview/llnamelistctrl.cpp | 80 +++++-- indra/newview/llnamelistctrl.h | 5 +- indra/newview/llnearbychat.cpp | 28 +-- indra/newview/llnearbychatbar.cpp | 252 +++++++++++++++----- indra/newview/llnearbychatbar.h | 47 ++-- indra/newview/llnearbychathandler.cpp | 23 +- indra/newview/llnotificationofferhandler.cpp | 4 +- indra/newview/lloutputmonitorctrl.cpp | 65 +++++- indra/newview/lloutputmonitorctrl.h | 29 ++- indra/newview/llpanelavatar.cpp | 20 +- indra/newview/llpanelclassified.cpp | 15 +- indra/newview/llpanelclassified.h | 1 + indra/newview/llpanelgroup.cpp | 79 ++++++- indra/newview/llpanelgroup.h | 4 + indra/newview/llpanelgroupgeneral.cpp | 11 +- indra/newview/llpanelgroupnotices.cpp | 2 +- indra/newview/llpanelgrouproles.cpp | 61 ++--- indra/newview/llpanelgrouproles.h | 13 +- indra/newview/llpanelhome.cpp | 2 +- indra/newview/llpanelimcontrolpanel.cpp | 9 +- indra/newview/llpanellandaudio.cpp | 62 ++--- indra/newview/llpanellandaudio.h | 4 +- indra/newview/llpanellandmarkinfo.cpp | 7 + indra/newview/llpanellandmarks.cpp | 57 ++++- indra/newview/llpanellandmarks.h | 16 ++ indra/newview/llpanelmaininventory.cpp | 6 +- indra/newview/llpanelobject.cpp | 4 +- indra/newview/llpanelobjectinventory.cpp | 2 +- indra/newview/llpaneloutfitsinventory.cpp | 175 ++++++++++++-- indra/newview/llpaneloutfitsinventory.h | 6 +- indra/newview/llpanelpeople.cpp | 27 ++- indra/newview/llpanelpeople.h | 2 +- indra/newview/llpanelpick.cpp | 100 ++++---- indra/newview/llpanelpick.h | 23 +- indra/newview/llpanelpicks.cpp | 14 +- indra/newview/llpanelpicks.h | 1 + indra/newview/llpanelplaces.cpp | 31 +++ indra/newview/llpanelplaces.h | 6 + indra/newview/llpanelprimmediacontrols.cpp | 120 +++++----- indra/newview/llpanelprimmediacontrols.h | 4 +- indra/newview/llpanelteleporthistory.cpp | 14 +- indra/newview/llpanelvolume.cpp | 4 +- indra/newview/llparticipantlist.cpp | 23 +- indra/newview/llparticipantlist.h | 2 +- indra/newview/llpreviewgesture.cpp | 6 + indra/newview/llpreviewnotecard.cpp | 1 - indra/newview/llpreviewscript.cpp | 1 - 149 files changed, 3417 insertions(+), 1714 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8918fc3018..5373556c20 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -63,8 +63,6 @@ include_directories( ) set(viewer_SOURCE_FILES - llaccordionctrl.cpp - llaccordionctrltab.cpp llagent.cpp llagentaccess.cpp llagentdata.cpp @@ -158,7 +156,6 @@ set(viewer_SOURCE_FILES llfloaterbuycurrency.cpp llfloaterbuyland.cpp llfloatercamera.cpp - llfloaterchat.cpp llfloaterchatterbox.cpp llfloatercolorpicker.cpp llfloatercustomize.cpp @@ -214,7 +211,6 @@ set(viewer_SOURCE_FILES llfloaterurldisplay.cpp llfloaterurlentry.cpp llfloatervoicedevicesettings.cpp - llfloatervolumepulldown.cpp llfloaterwater.cpp llfloaterwhitelistentry.cpp llfloaterwindlight.cpp @@ -252,6 +248,7 @@ set(viewer_SOURCE_FILES llinspectgroup.cpp llinspectobject.cpp llinspectremoteobject.cpp + llinspecttoast.cpp llinventorybridge.cpp llinventoryclipboard.cpp llinventoryfilter.cpp @@ -349,6 +346,7 @@ set(viewer_SOURCE_FILES llpanelshower.cpp llpanelteleporthistory.cpp llpanelvolume.cpp + llpanelvolumepulldown.cpp llparcelselection.cpp llparticipantlist.cpp llpatchvertexarray.cpp @@ -387,6 +385,7 @@ set(viewer_SOURCE_FILES llspatialpartition.cpp llspeakbutton.cpp llspeakers.cpp + llspeakingindicatormanager.cpp llsplitbutton.cpp llsprite.cpp llstartup.cpp @@ -569,8 +568,6 @@ endif (LINUX) set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake - llaccordionctrl.h - llaccordionctrltab.h llagent.h llagentaccess.h llagentdata.h @@ -667,7 +664,6 @@ set(viewer_HEADER_FILES llfloaterbuycurrency.h llfloaterbuyland.h llfloatercamera.h - llfloaterchat.h llfloaterchatterbox.h llfloatercolorpicker.h llfloatercustomize.h @@ -759,6 +755,7 @@ set(viewer_HEADER_FILES llinspectgroup.h llinspectobject.h llinspectremoteobject.h + llinspecttoast.h llinventorybridge.h llinventoryclipboard.h llinventoryfilter.h @@ -852,6 +849,7 @@ set(viewer_HEADER_FILES llpanelshower.h llpanelteleporthistory.h llpanelvolume.h + llpanelvolumepulldown.h llparcelselection.h llparticipantlist.h llpatchvertexarray.h @@ -892,6 +890,7 @@ set(viewer_HEADER_FILES llspatialpartition.h llspeakbutton.h llspeakers.h + llspeakingindicatormanager.h llsplitbutton.h llsprite.h llstartup.h @@ -1406,11 +1405,11 @@ if (WINDOWS) # 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 - ) + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll + ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll + ) endif(USE_GOOGLE_PERFTOOLS) - + set(COPY_INPUT_DEPENDECIES # The following commented dependencies are determined at variably at build time. Can't do this here. @@ -1499,15 +1498,16 @@ if (WINDOWS) --actions=copy --artwork=${ARTWORK_DIR} --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} --grid=${GRID} --source=${CMAKE_CURRENT_SOURCE_DIR} - --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat + --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - stage_third_party_libs - ${COPY_INPUT_DEPENDECIES} + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + stage_third_party_libs + ${COPY_INPUT_DEPENDECIES} COMMENT "Performing viewer_manifest copy" ) @@ -1569,6 +1569,7 @@ if (WINDOWS) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --artwork=${ARTWORK_DIR} --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} @@ -1650,6 +1651,7 @@ if (LINUX) --arch=${ARCH} --artwork=${ARTWORK_DIR} --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged @@ -1695,6 +1697,7 @@ if (DARWIN) --actions=copy --artwork=${ARTWORK_DIR} --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --grid=${GRID} @@ -1715,6 +1718,7 @@ if (DARWIN) ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --grid=${GRID} + --buildtype=${CMAKE_BUILD_TYPE} --configuration=${CMAKE_CFG_INTDIR} --channel=${VIEWER_CHANNEL} --login_channel=${VIEWER_LOGIN_CHANNEL} @@ -1734,6 +1738,7 @@ if (DARWIN) ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --grid=${GRID} + --buildtype=${CMAKE_BUILD_TYPE} --configuration=${CMAKE_CFG_INTDIR} --channel=${VIEWER_CHANNEL} --login_channel=${VIEWER_LOGIN_CHANNEL} @@ -1761,9 +1766,10 @@ if (LL_TESTS) llagentaccess.cpp lldateutil.cpp llmediadataclient.cpp - llviewerhelputil.cpp lllogininstance.cpp + llviewerhelputil.cpp ) + ################################################## # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS ################################################## diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml index ab18febccc..e825f13e82 100644 --- a/indra/newview/app_settings/ignorable_dialogs.xml +++ b/indra/newview/app_settings/ignorable_dialogs.xml @@ -177,21 +177,10 @@ Value 1 - FirstStreamingMusic + FirstStreamingMedia Comment - Enables FirstStreamingMusic warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstStreamingVideo - - Comment - Enables FirstStreamingVideo warning dialog + Enables FirstStreamingMedia warning dialog Persist 1 Type diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e24e1a8605..a4fc095727 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -276,7 +276,7 @@ Value 0.5 - AudioSteamingMedia + AudioStreamingMedia Comment Enable streaming @@ -285,7 +285,7 @@ Type Boolean Value - 0 + 1 AudioStreamingMusic @@ -296,7 +296,7 @@ Type Boolean Value - 0 + 1 AudioStreamingVideo @@ -307,7 +307,7 @@ Type Boolean Value - 0 + 1 AuditTexture @@ -408,6 +408,17 @@ Value 1 + AvalinePhoneSeparator + + Comment + Separator of phone parts to have Avaline numbers human readable in Voice Control Panel + Persist + 1 + Type + String + Value + - + AvatarAxisDeadZone0 Comment @@ -1130,9 +1141,9 @@ Persist 1 Type - Boolean + S32 Value - 1 + 5 CameraAngle @@ -3246,17 +3257,6 @@ Value 0.75 - FolderIndentation - - Comment - Number of pixels to indent subfolders in inventory - Persist - 1 - Type - S32 - Value - 8 - FolderLoadingMessageWaitTime Comment @@ -3596,7 +3596,7 @@ Type String Value - http://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC] + http://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE] HomeSidePanelURL @@ -3607,7 +3607,7 @@ Type String Value - http://lecs.viewer-sidebar.secondlife.com.s3.amazonaws.com/sidebar.html + http://lecs.viewer-sidebar.secondlife.com.s3.amazonaws.com/sidebar.html?p=[AUTH_TOKEN]&lang=[LANGUAGE]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR] SearchURL @@ -3618,7 +3618,7 @@ Type String Value - http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID] + 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] HighResSnapshot @@ -3653,17 +3653,6 @@ Value - IMInChat - - Comment - Copy IM into chat console - Persist - 1 - Type - Boolean - Value - 0 - IMShowTimestamps Comment @@ -4809,6 +4798,17 @@ Value 0 + MyOutfitsAutofill + + Comment + Always autofill My Outfits from library when empty (else happens just once). + Persist + 1 + Type + Boolean + Value + 0 + NearMeRange Comment @@ -5040,6 +5040,18 @@ Value 5 + ToastButtonWidth + + Comment + Default width of buttons in the toast. + Note if required width will be less then this one, a button will be reshaped to default size , otherwise to required + Persist + 1 + Type + S32 + Value + 90 + ChannelBottomPanelMargin Comment @@ -9320,18 +9332,7 @@ S32 Value 2 - - UILineEditorVPad - - Comment - UI Line Editor Vertical Pad - Persist - 1 - Type - S32 - Value - 5 - + UIMaxComboWidth Comment diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ae89eb4413..448e20b382 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -5608,9 +5608,7 @@ + height="512"> + + + @@ -6620,6 +6625,7 @@ render_pass="bump"> local_texture="head_tattoo" /> + diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d2a56f65dd..da0e9238d6 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -43,7 +43,7 @@ #include "llcallingcard.h" #include "llchannelmanager.h" #include "llconsole.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llfloatercamera.h" #include "llfloatercustomize.h" #include "llfloaterreg.h" @@ -514,6 +514,8 @@ void LLAgent::resetView(BOOL reset_camera, BOOL change_camera) } setFocusOnAvatar(TRUE, ANIMATE); + + mCameraFOVZoomFactor = 0.f; } mHUDTargetZoom = 1.f; @@ -2804,6 +2806,7 @@ void LLAgent::endAnimationUpdateUI() gStatusBar->setVisibleForMouselook(true); LLBottomTray::getInstance()->setVisible(TRUE); + LLBottomTray::getInstance()->onMouselookModeOut(); LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE); LLSideTray::getInstance()->updateSidetrayVisibility(); @@ -2812,7 +2815,7 @@ void LLAgent::endAnimationUpdateUI() LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - LLFloaterCamera::toPrevModeIfInAvatarViewMode(); + LLFloaterCamera::onLeavingMouseLook(); // Only pop if we have pushed... if (TRUE == mViewsPushed) @@ -2902,6 +2905,7 @@ void LLAgent::endAnimationUpdateUI() LLNavigationBar::getInstance()->setVisible(FALSE); gStatusBar->setVisibleForMouselook(false); + LLBottomTray::getInstance()->onMouselookModeIn(); LLBottomTray::getInstance()->setVisible(FALSE); LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE); @@ -2915,10 +2919,6 @@ void LLAgent::endAnimationUpdateUI() // JC - Added for always chat in third person option gFocusMgr.setKeyboardFocus(NULL); - //Making sure Camera Controls floater is in the right state - //when entering Mouse Look using wheel scrolling - LLFloaterCamera::updateIfNotInAvatarViewMode(); - LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); mViewsPushed = TRUE; @@ -3588,7 +3588,7 @@ F32 LLAgent::calcCameraFOVZoomFactor() { return 0.f; } - else if (mFocusObject.notNull() && !mFocusObject->isAvatar()) + else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) { // don't FOV zoom on mostly transparent objects LLVector3 focus_offset = mFocusObjectOffset; @@ -5161,6 +5161,11 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO return FALSE; } +BOOL LLAgent::canJoinGroups() const +{ + return mGroups.count() < MAX_AGENT_GROUPS; +} + LLQuaternion LLAgent::getHeadRotation() { if (mAvatarObject.isNull() || !mAvatarObject->mPelvisp || !mAvatarObject->mHeadp) @@ -5694,10 +5699,10 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **) } // Any control taken? If so, might be first time. - if (total_count > 0) - { - LLFirstUse::useOverrideKeys(); - } + //if (total_count > 0) + //{ + //LLFirstUse::useOverrideKeys(); + //} } else { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 2e95dc72be..beede7fbe3 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -972,6 +972,7 @@ public: BOOL setGroupContribution(const LLUUID& group_id, S32 contribution); BOOL setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile); const std::string &getGroupName() const { return mGroupName; } + BOOL canJoinGroups() const; private: std::string mGroupName; LLUUID mGroupID; diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index dc1598aacd..c21cdf9508 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -95,19 +95,38 @@ public: enum ELibraryOutfitFetchStep { LOFS_FOLDER = 0, LOFS_OUTFITS, + LOFS_LIBRARY, + LOFS_IMPORTED, LOFS_CONTENTS }; - LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} + LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) + { + mMyOutfitsID = LLUUID::null; + mClothingID = LLUUID::null; + mLibraryClothingID = LLUUID::null; + mImportedClothingID = LLUUID::null; + mImportedClothingName = "Imported Library Clothing"; + } ~LLLibraryOutfitsFetch() {} - virtual void done(); + virtual void done(); void doneIdle(); + LLUUID mMyOutfitsID; + void importedFolderFetch(); protected: void folderDone(void); void outfitsDone(void); + void libraryDone(void); + void importedFolderDone(void); void contentsDone(void); enum ELibraryOutfitFetchStep mCurrFetchStep; - std::vector< std::pair< LLUUID, std::string > > mOutfits; + typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t; + cloth_folder_vec_t mLibraryClothingFolders; + cloth_folder_vec_t mImportedClothingFolders; bool mOutfitsPopulated; + LLUUID mClothingID; + LLUUID mLibraryClothingID; + LLUUID mImportedClothingID; + std::string mImportedClothingName; }; LLAgentWearables gAgentWearables; @@ -116,6 +135,39 @@ BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; using namespace LLVOAvatarDefines; +// HACK: For EXT-3923: Pants item shows in inventory with skin icon and messes with "current look" +// Some db items are corrupted, have inventory flags = 0, implying wearable type = shape, even though +// wearable type stored in asset is some other value. +// Calling this function whenever a wearable is added to increase visibility if this problem +// turns up in other inventories. +void checkWearableAgainstInventory(LLWearable *wearable) +{ + if (wearable->getItemID().isNull()) + return; + + // Check for wearable type consistent with inventory item wearable type. + LLViewerInventoryItem *item = gInventory.getItem(wearable->getItemID()); + if (item) + { + if (!item->isWearableType()) + { + llwarns << "wearable associated with non-wearable item" << llendl; + } + if (item->getWearableType() != wearable->getType()) + { + llwarns << "type mismatch: wearable " << wearable->getName() + << " has type " << wearable->getType() + << " but inventory item " << item->getName() + << " has type " << item->getWearableType() << llendl; + } + } + else + { + llwarns << "wearable inventory item not found" << wearable->getName() + << " itemID " << wearable->getItemID().asString() << llendl; + } +} + void LLAgentWearables::dump() { llinfos << "LLAgentWearablesDump" << llendl; @@ -657,6 +709,7 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable) { + LLWearable *old_wearable = getWearable(type,index); if (!old_wearable) { @@ -680,6 +733,7 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab wearable_vec[index] = wearable; old_wearable->setLabelUpdated(); wearableUpdated(wearable); + checkWearableAgainstInventory(wearable); } } @@ -695,6 +749,7 @@ U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearabl { mWearableDatas[type].push_back(wearable); wearableUpdated(wearable); + checkWearableAgainstInventory(wearable); return mWearableDatas[type].size()-1; } return MAX_WEARABLES_PER_TYPE; @@ -875,7 +930,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) // then auto-populate outfits from the library into the My Outfits folder. - if (LLInventoryModel::getIsFirstTimeInViewer2()) + if (LLInventoryModel::getIsFirstTimeInViewer2() || gSavedSettings.getBOOL("MyOutfitsAutofill")) { gAgentWearables.populateMyOutfitsFolder(); } @@ -1309,15 +1364,15 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, } } -class LLAutoRenameFolder: public LLInventoryCallback +class LLShowCreatedOutfit: public LLInventoryCallback { public: - LLAutoRenameFolder(LLUUID& folder_id): + LLShowCreatedOutfit(LLUUID& folder_id): mFolderID(folder_id) { } - virtual ~LLAutoRenameFolder() + virtual ~LLShowCreatedOutfit() { LLSD key; LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); @@ -1327,13 +1382,15 @@ public: { outfit_panel->getRootFolder()->clearSelection(); outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE); - outfit_panel->getRootFolder()->setNeedsAutoRename(TRUE); } LLAccordionCtrlTab* tab_outfits = outfit_panel ? outfit_panel->findChild("tab_outfits") : 0; if (tab_outfits && !tab_outfits->getDisplayChildren()) { tab_outfits->changeOpenClose(tab_outfits->getDisplayChildren()); } + + LLAppearanceManager::instance().updateIsDirty(); + LLAppearanceManager::instance().updatePanelOutfitName(""); } virtual void fire(const LLUUID&) @@ -1358,9 +1415,10 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) LLFolderType::FT_OUTFIT, new_folder_name); - LLPointer cb = new LLAutoRenameFolder(folder_id); + LLPointer cb = new LLShowCreatedOutfit(folder_id); LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, cb); - + LLAppearanceManager::instance().createBaseOutfitLink(folder_id, cb); + return folder_id; } @@ -1705,6 +1763,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n mWearableDatas[type].push_back(new_wearable); llinfos << "Added additional wearable for type " << type << " size is now " << mWearableDatas[type].size() << llendl; + checkWearableAgainstInventory(new_wearable); } else { @@ -2088,11 +2147,15 @@ void LLAgentWearables::populateMyOutfitsFolder(void) // Get the complete information on the items in the inventory and // setup an observer that will wait for that to happen. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + outfits->mMyOutfitsID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - folders.push_back(my_outfits_id); + folders.push_back(outfits->mMyOutfitsID); gInventory.addObserver(outfits); outfits->fetchDescendents(folders); + if (outfits->isEverythingComplete()) + { + outfits->done(); + } } void LLLibraryOutfitsFetch::done() @@ -2106,13 +2169,24 @@ void LLLibraryOutfitsFetch::done() void LLLibraryOutfitsFetch::doneIdle() { gInventory.addObserver(this); // Add this back in since it was taken out during ::done() + switch (mCurrFetchStep) { case LOFS_FOLDER: folderDone(); + mCurrFetchStep = LOFS_OUTFITS; break; case LOFS_OUTFITS: outfitsDone(); + mCurrFetchStep = LOFS_LIBRARY; + break; + case LOFS_LIBRARY: + libraryDone(); + mCurrFetchStep = LOFS_IMPORTED; + break; + case LOFS_IMPORTED: + importedFolderDone(); + mCurrFetchStep = LOFS_CONTENTS; break; case LOFS_CONTENTS: contentsDone(); @@ -2134,67 +2208,217 @@ void LLLibraryOutfitsFetch::doneIdle() void LLLibraryOutfitsFetch::folderDone(void) { - // Early out if we already have items in My Outfits. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); + + // Early out if we already have items in My Outfits. if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; return; } - // Get the UUID of the library's clothing folder - const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); + mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); mCompleteFolders.clear(); // Get the complete information on the items in the inventory. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - folders.push_back(library_clothing_id); - mCurrFetchStep = LOFS_OUTFITS; + folders.push_back(mClothingID); + folders.push_back(mLibraryClothingID); fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } void LLLibraryOutfitsFetch::outfitsDone(void) { LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; + // Collect the contents of the Library's Clothing folder + gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + llassert(cat_array.count() > 0); for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); iter != cat_array.end(); ++iter) { const LLViewerInventoryCategory *cat = iter->get(); + + // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits. if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") { + // Get the name of every outfit in the library folders.push_back(cat->getUUID()); - mOutfits.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); } } + + // Collect the contents of your Inventory Clothing folder + cat_array.clear(); + wearable_array.clear(); + gInventory.collectDescendents(mClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + // Check if you already have an "Imported Library Clothing" folder + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + if (cat->getName() == mImportedClothingName) + { + mImportedClothingID = cat->getUUID(); + } + } + mCompleteFolders.clear(); + + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} - mCurrFetchStep = LOFS_CONTENTS; +class LLLibraryOutfitsCopyDone: public LLInventoryCallback +{ +public: + LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): + mFireCount(0), mLibraryOutfitsFetcher(fetcher) + { + } + + virtual ~LLLibraryOutfitsCopyDone() + { + if (mLibraryOutfitsFetcher) + { + gInventory.addObserver(mLibraryOutfitsFetcher); + mLibraryOutfitsFetcher->done(); + } + } + + /* virtual */ void fire(const LLUUID& inv_item) + { + mFireCount++; + } +private: + U32 mFireCount; + LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; +}; + +void LLLibraryOutfitsFetch::libraryDone(void) +{ + // Copy the clothing folders from the library into the imported clothing folder if necessary. + if (mImportedClothingID == LLUUID::null) + { + gInventory.removeObserver(this); + LLPointer copy_waiter = new LLLibraryOutfitsCopyDone(this); + mImportedClothingID = gInventory.createNewCategory(mClothingID, + LLFolderType::FT_NONE, + mImportedClothingName); + + for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); + iter != mLibraryClothingFolders.end(); + ++iter) + { + LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID, + LLFolderType::FT_NONE, + iter->second); + LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter); + } + } + else + { + // Skip straight to fetching the contents of the imported folder + importedFolderFetch(); + } +} + +void LLLibraryOutfitsFetch::importedFolderFetch(void) +{ + // Fetch the contents of the Imported Clothing Folder + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(mImportedClothingID); + + mCompleteFolders.clear(); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } } -void LLLibraryOutfitsFetch::contentsDone(void) +void LLLibraryOutfitsFetch::importedFolderDone(void) { - for(S32 i = 0; i < (S32)mOutfits.size(); ++i) + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + + // Collect the contents of the Imported Clothing folder + gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) + { + const LLViewerInventoryCategory *cat = iter->get(); + + // Get the name of every imported outfit + folders.push_back(cat->getUUID()); + mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + } + + mCompleteFolders.clear(); + fetchDescendents(folders); + if (isEverythingComplete()) + { + done(); + } +} + +void LLLibraryOutfitsFetch::contentsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + + for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + folder_iter != mImportedClothingFolders.end(); + ++folder_iter) { // First, make a folder in the My Outfits directory. - const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLUUID folder_id = gInventory.createNewCategory(parent_id, - LLFolderType::FT_OUTFIT, - mOutfits[i].second); - LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second); + + cat_array.clear(); + wearable_array.clear(); + // Collect the contents of each imported clothing folder, so we can create new outfit links for it + gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); + wearable_iter != wearable_array.end(); + ++wearable_iter) + { + const LLViewerInventoryItem *item = wearable_iter->get(); + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + new_outfit_folder_id, + item->getName(), + LLAssetType::AT_LINK, + NULL); + } } + mOutfitsPopulated = true; } @@ -2236,6 +2460,8 @@ void LLInitialWearablesFetch::processContents() } else { + // if we're constructing the COF from the wearables message, we don't have a proper outfit link + LLAppearanceManager::instance().setOutfitDirty(true); processWearablesMessage(); } delete this; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43b2f34ecd..748d8bdfbf 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -364,7 +364,7 @@ LLUUID LLAppearanceManager::getCOF() } -const LLViewerInventoryItem* LLAppearanceManager::getCurrentOutfitLink() +const LLViewerInventoryItem* LLAppearanceManager::getBaseOutfitLink() { const LLUUID& current_outfit_cat = getCOF(); LLInventoryModel::cat_array_t cat_array; @@ -392,6 +392,21 @@ const LLViewerInventoryItem* LLAppearanceManager::getCurrentOutfitLink() return NULL; } +bool LLAppearanceManager::getBaseOutfitName(std::string& name) +{ + const LLViewerInventoryItem* outfit_link = getBaseOutfitLink(); + if(outfit_link) + { + const LLViewerInventoryCategory *cat = outfit_link->getLinkedCategory(); + if (cat) + { + name = cat->getName(); + return true; + } + } + return false; +} + // Update appearance from outfit folder. void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append) { @@ -444,6 +459,28 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID } } +void LLAppearanceManager::purgeBaseOutfitLink(const LLUUID& category) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(category, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < items.count(); ++i) + { + LLViewerInventoryItem *item = items.get(i); + if (item->getActualType() != LLAssetType::AT_LINK_FOLDER) + continue; + if (item->getIsLinkType()) + { + LLViewerInventoryCategory* catp = item->getLinkedCategory(); + if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + gInventory.purgeObject(item->getUUID()); + } + } + } +} + void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit_links) { LLInventoryModel::cat_array_t cats; @@ -578,17 +615,9 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) linkAll(cof, gest_items, link_waiter); // Add link to outfit if category is an outfit. - LLViewerInventoryCategory* catp = gInventory.getCategory(category); if (!append) { - std::string new_outfit_name = ""; - if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - link_inventory_item(gAgent.getID(), category, cof, catp->getName(), - LLAssetType::AT_LINK_FOLDER, link_waiter); - new_outfit_name = catp->getName(); - } - updatePanelOutfitName(new_outfit_name); + createBaseOutfitLink(category, link_waiter); } } @@ -602,6 +631,23 @@ void LLAppearanceManager::updatePanelOutfitName(const std::string& name) } } +void LLAppearanceManager::createBaseOutfitLink(const LLUUID& category, LLPointer link_waiter) +{ + const LLUUID cof = getCOF(); + LLViewerInventoryCategory* catp = gInventory.getCategory(category); + std::string new_outfit_name = ""; + + purgeBaseOutfitLink(cof); + + if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + link_inventory_item(gAgent.getID(), category, cof, catp->getName(), + LLAssetType::AT_LINK_FOLDER, link_waiter); + new_outfit_name = catp->getName(); + } + + updatePanelOutfitName(new_outfit_name); +} void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append) { @@ -644,6 +690,10 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, void LLAppearanceManager::updateAppearanceFromCOF() { + // update dirty flag to see if the state of the COF matches + // the saved outfit stored as a folder link + updateIsDirty(); + dumpCat(getCOF(),"COF, start"); bool follow_folder_links = true; @@ -693,14 +743,30 @@ void LLAppearanceManager::updateAppearanceFromCOF() LLDynamicArray found_container; for(S32 i = 0; i < wear_items.count(); ++i) { - found = new LLFoundData(wear_items.get(i)->getLinkedUUID(), // Wear the base item, not the link - wear_items.get(i)->getAssetUUID(), - wear_items.get(i)->getName(), - wear_items.get(i)->getType()); - holder->mFoundList.push_front(found); - found_container.put(found); + LLViewerInventoryItem *item = wear_items.get(i); + LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL; + if (item && linked_item) + { + found = new LLFoundData(linked_item->getUUID(), + linked_item->getAssetUUID(), + linked_item->getName(), + linked_item->getType()); + holder->mFoundList.push_front(found); + found_container.put(found); + } + else + { + if (!item) + { + llwarns << "attempt to wear a null item " << llendl; + } + else if (!linked_item) + { + llwarns << "attempt to wear a broken link " << item->getName() << llendl; + } + } } - for(S32 i = 0; i < wear_items.count(); ++i) + for(S32 i = 0; i < found_container.count(); ++i) { holder->append = false; found = found_container.get(i); @@ -959,7 +1025,9 @@ void LLAppearanceManager::addCOFItemLink(const LLInventoryItem *item, bool do_up if (linked_already) { if (do_update) + { LLAppearanceManager::updateAppearanceFromCOF(); + } return; } else @@ -1013,6 +1081,75 @@ void LLAppearanceManager::removeCOFItemLinks(const LLUUID& item_id, bool do_upda } } +void LLAppearanceManager::updateIsDirty() +{ + LLUUID cof = getCOF(); + LLUUID base_outfit; + + // find base outfit link + const LLViewerInventoryItem* base_outfit_item = getBaseOutfitLink(); + LLViewerInventoryCategory* catp = NULL; + if (base_outfit_item && base_outfit_item->getIsLinkType()) + { + catp = base_outfit_item->getLinkedCategory(); + } + if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + base_outfit = catp->getUUID(); + } + + if(base_outfit.isNull()) + { + // no outfit link found, display "unsaved outfit" + mOutfitIsDirty = true; + } + else + { + LLInventoryModel::cat_array_t cof_cats; + LLInventoryModel::item_array_t cof_items; + gInventory.collectDescendents(cof, cof_cats, cof_items, + LLInventoryModel::EXCLUDE_TRASH); + + LLInventoryModel::cat_array_t outfit_cats; + LLInventoryModel::item_array_t outfit_items; + gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items, + LLInventoryModel::EXCLUDE_TRASH); + + if(outfit_items.count() != cof_items.count() -1) + { + // Current outfit folder should have one more item than the outfit folder. + // this one item is the link back to the outfit folder itself. + mOutfitIsDirty = true; + } + else + { + typedef std::set item_set_t; + item_set_t cof_set; + item_set_t outfit_set; + + // sort COF items by UUID + for (S32 i = 0; i < cof_items.count(); ++i) + { + LLViewerInventoryItem *item = cof_items.get(i); + // don't add the base outfit link to the list of objects we're comparing + if(item != base_outfit_item) + { + cof_set.insert(item->getLinkedUUID()); + } + } + + // sort outfit folder by UUID + for (S32 i = 0; i < outfit_items.count(); ++i) + { + LLViewerInventoryItem *item = outfit_items.get(i); + outfit_set.insert(item->getLinkedUUID()); + } + + mOutfitIsDirty = (outfit_set != cof_set); + } + } +} + //#define DUMP_CAT_VERBOSE void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg) @@ -1049,7 +1186,8 @@ void LLAppearanceManager::dumpItemArray(const LLInventoryModel::item_array_t& it } LLAppearanceManager::LLAppearanceManager(): - mAttachmentInvLinkEnabled(false) + mAttachmentInvLinkEnabled(false), + mOutfitIsDirty(false) { } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index b625d42a50..20745b70e4 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -62,11 +62,14 @@ public: LLUUID getCOF(); // Finds the folder link to the currently worn outfit - const LLViewerInventoryItem *getCurrentOutfitLink(); + const LLViewerInventoryItem *getBaseOutfitLink(); + bool getBaseOutfitName(std::string &name); // Update the displayed outfit name in UI. void updatePanelOutfitName(const std::string& name); + void createBaseOutfitLink(const LLUUID& category, LLPointer link_waiter); + void updateAgentWearables(LLWearableHoldingPattern* holder, bool append); // For debugging - could be moved elsewhere. @@ -94,6 +97,16 @@ public: // Add COF link to ensemble folder. void addEnsembleLink(LLInventoryCategory* item, bool do_update = true); + //has the current outfit changed since it was loaded? + bool isOutfitDirty() { return mOutfitIsDirty; } + + // set false if you just loaded the outfit, true otherwise + void setOutfitDirty(bool isDirty) { mOutfitIsDirty = isDirty; } + + // manually compare ouftit folder link to COF to see if outfit has changed. + // should only be necessary to do on initial login. + void updateIsDirty(); + protected: LLAppearanceManager(); ~LLAppearanceManager(); @@ -114,9 +127,11 @@ private: bool follow_folder_links); void purgeCategory(const LLUUID& category, bool keep_outfit_links); + void purgeBaseOutfitLink(const LLUUID& category); std::set mRegisteredAttachments; bool mAttachmentInvLinkEnabled; + bool mOutfitIsDirty; }; #define SUPPORT_ENSEMBLES 0 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 21d908035f..8507c62d27 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -71,7 +71,7 @@ #include "lluicolortable.h" #include "llurldispatcher.h" #include "llurlhistory.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llrender.h" #include "llteleporthistory.h" #include "lllocationhistory.h" @@ -313,6 +313,7 @@ void init_default_trans_args() { default_trans_args.insert("SECOND_LIFE"); // World default_trans_args.insert("APP_NAME"); + default_trans_args.insert("CAPITALIZED_APP_NAME"); default_trans_args.insert("SECOND_LIFE_GRID"); default_trans_args.insert("SUPPORT_SITE"); } @@ -921,7 +922,6 @@ bool LLAppViewer::mainLoop() { LLMemType mt1(LLMemType::MTYPE_MAIN); mMainloopTimeout = new LLWatchdogTimeout(); - // *FIX:Mani - Make this a setting, once new settings exist in this branch. //------------------------------------------- // Run main loop until time to quit @@ -931,12 +931,13 @@ bool LLAppViewer::mainLoop() gServicePump = new LLPumpIO(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); LLCurl::setCAFile(gDirUtilp->getCAFile()); + LLCurl::setSSLVerify(! gSavedSettings.getBOOL("NoVerifySSLCert")); // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. LLVoiceChannel::initClass(); LLVoiceClient::init(gServicePump); - + LLTimer frameTimer,idleTimer; LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); @@ -1371,7 +1372,7 @@ bool LLAppViewer::cleanup() if( gViewerWindow) gViewerWindow->shutdownViews(); - llinfos << "Cleaning up Inevntory" << llendflush; + llinfos << "Cleaning up Inventory" << llendflush; // Cleanup Inventory after the UI since it will delete any remaining observers // (Deleted observers should have already removed themselves) @@ -1473,10 +1474,17 @@ bool LLAppViewer::cleanup() LLUIColorTable::instance().saveUserSettings(); - // PerAccountSettingsFile should be empty if no use has been logged on. + // PerAccountSettingsFile should be empty if no user has been logged on. // *FIX:Mani This should get really saved in a "logoff" mode. - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - llinfos << "Saved settings" << llendflush; + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) + { + llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + llinfos << "Saved settings" << llendflush; + } std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults @@ -1910,26 +1918,25 @@ bool LLAppViewer::initConfiguration() // These are warnings that appear on the first experience of that condition. // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse // for disable/reset ability - LLFirstUse::addConfigVariable("FirstBalanceIncrease"); - LLFirstUse::addConfigVariable("FirstBalanceDecrease"); - LLFirstUse::addConfigVariable("FirstSit"); - LLFirstUse::addConfigVariable("FirstMap"); - LLFirstUse::addConfigVariable("FirstGoTo"); - LLFirstUse::addConfigVariable("FirstBuild"); +// LLFirstUse::addConfigVariable("FirstBalanceIncrease"); +// LLFirstUse::addConfigVariable("FirstBalanceDecrease"); +// LLFirstUse::addConfigVariable("FirstSit"); +// LLFirstUse::addConfigVariable("FirstMap"); +// LLFirstUse::addConfigVariable("FirstGoTo"); +// LLFirstUse::addConfigVariable("FirstBuild"); // LLFirstUse::addConfigVariable("FirstLeftClickNoHit"); - LLFirstUse::addConfigVariable("FirstTeleport"); - LLFirstUse::addConfigVariable("FirstOverrideKeys"); - LLFirstUse::addConfigVariable("FirstAttach"); - LLFirstUse::addConfigVariable("FirstAppearance"); - LLFirstUse::addConfigVariable("FirstInventory"); - LLFirstUse::addConfigVariable("FirstSandbox"); - LLFirstUse::addConfigVariable("FirstFlexible"); - LLFirstUse::addConfigVariable("FirstDebugMenus"); - LLFirstUse::addConfigVariable("FirstStreamingMusic"); - LLFirstUse::addConfigVariable("FirstStreamingVideo"); - LLFirstUse::addConfigVariable("FirstSculptedPrim"); - LLFirstUse::addConfigVariable("FirstVoice"); - LLFirstUse::addConfigVariable("FirstMedia"); +// LLFirstUse::addConfigVariable("FirstTeleport"); +// LLFirstUse::addConfigVariable("FirstOverrideKeys"); +// LLFirstUse::addConfigVariable("FirstAttach"); +// LLFirstUse::addConfigVariable("FirstAppearance"); +// LLFirstUse::addConfigVariable("FirstInventory"); +// LLFirstUse::addConfigVariable("FirstSandbox"); +// LLFirstUse::addConfigVariable("FirstFlexible"); +// LLFirstUse::addConfigVariable("FirstDebugMenus"); +// LLFirstUse::addConfigVariable("FirstStreamingMedia"); +// LLFirstUse::addConfigVariable("FirstSculptedPrim"); +// LLFirstUse::addConfigVariable("FirstVoice"); +// LLFirstUse::addConfigVariable("FirstMedia"); // - read command line settings. LLControlGroupCLP clp; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 2a8c55e5db..40c9bb6afa 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -168,8 +168,10 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee) // static void LLAvatarActions::offerTeleport(const std::vector& ids) { - if (ids.size() > 0) - handle_lure(ids); + if (ids.size() == 0) + return; + + handle_lure(ids); } // static @@ -595,9 +597,11 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri LLSD args; args["TO_NAME"] = target_name; + LLSD payload; + payload["from_id"] = target_id; payload["SESSION_NAME"] = target_name; - payload["SUPPRES_TOST"] = true; + payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipOffered", args, payload); } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 42ae122ff9..87b8d807c4 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -64,7 +64,7 @@ void LLAvatarIconIDCache::load () llinfos << "Loading avatar icon id cache." << llendl; // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename); llifstream file(resolved_filename); if (!file.is_open()) @@ -97,7 +97,7 @@ void LLAvatarIconIDCache::load () void LLAvatarIconIDCache::save () { - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename); // open a file for writing llofstream file (resolved_filename); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 5df73a994e..6784e6693b 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -82,7 +82,7 @@ void LLAvatarList::setSpeakingIndicatorsVisible(bool visible) getItems(items); for( std::vector::const_iterator it = items.begin(); it != items.end(); it++) { - static_cast(*it)->setSpeakingIndicatorVisible(mShowSpeakingIndicator); + static_cast(*it)->showSpeakingIndicator(mShowSpeakingIndicator); } } @@ -320,21 +320,25 @@ boost::signals2::connection LLAvatarList::setRefreshCompleteCallback(const commi return mRefreshCompleteSignal.connect(cb); } +boost::signals2::connection LLAvatarList::setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb) +{ + return mItemDoubleClickSignal.connect(cb); +} + void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); - item->showInfoBtn(true); - item->showSpeakingIndicator(true); item->setName(name); item->setAvatarId(id, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); item->showLastInteractionTime(mShowLastInteractionTime); - item->childSetVisible("info_btn", false); item->setAvatarIconVisible(mShowIcons); item->setShowInfoBtn(mShowInfoBtn); item->setShowProfileBtn(mShowProfileBtn); - item->setSpeakingIndicatorVisible(mShowSpeakingIndicator); + item->showSpeakingIndicator(mShowSpeakingIndicator); + + item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoucleClicked, this, _1, _2, _3, _4)); addItem(item, id, pos); } @@ -403,6 +407,11 @@ void LLAvatarList::updateLastInteractionTimes() } } +void LLAvatarList::onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask) +{ + mItemDoubleClickSignal(ctrl, x, y, mask); +} + bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { const LLAvatarListItem* avatar_item1 = dynamic_cast(item1); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 0d2ce884ae..a58a562378 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -92,6 +92,8 @@ public: boost::signals2::connection setRefreshCompleteCallback(const commit_signal_t::slot_type& cb); + boost::signals2::connection setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb); + protected: void refresh(); @@ -101,6 +103,7 @@ protected: std::vector& vadded, std::vector& vremoved); void updateLastInteractionTimes(); + void onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); private: @@ -120,6 +123,7 @@ private: LLAvatarListItem::ContextMenu* mContextMenu; commit_signal_t mRefreshCompleteSignal; + mouse_signal_t mItemDoubleClickSignal; }; /** Abstract comparator for avatar items */ diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 6945ac6932..66ab32f3e8 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -44,10 +44,10 @@ #include "llbutton.h" bool LLAvatarListItem::sStaticInitialized = false; -S32 LLAvatarListItem::sIconWidth = 0; -S32 LLAvatarListItem::sInfoBtnWidth = 0; -S32 LLAvatarListItem::sProfileBtnWidth = 0; -S32 LLAvatarListItem::sSpeakingIndicatorWidth = 0; +S32 LLAvatarListItem::sLeftPadding = 0; +S32 LLAvatarListItem::sRightNamePadding = 0; +S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT]; + LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) : LLPanel(), @@ -91,43 +91,25 @@ BOOL LLAvatarListItem::postBuild() mProfileBtn->setVisible(false); mProfileBtn->setClickedCallback(boost::bind(&LLAvatarListItem::onProfileBtnClick, this)); - // Remember avatar icon width including its padding from the name text box, - // so that we can hide and show the icon again later. if (!sStaticInitialized) { - sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft; - sInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight; - sProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight; - sSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight; + // Remember children widths including their padding from the next sibling, + // so that we can hide and show them again later. + initChildrenWidths(this); sStaticInitialized = true; } -/* - if(!p.buttons.profile) - { - delete mProfile; - mProfile = NULL; - - LLRect rect; - - rect.setLeftTopAndSize(mName->getRect().mLeft, mName->getRect().mTop, mName->getRect().getWidth() + 30, mName->getRect().getHeight()); - mName->setRect(rect); - - if(mLocator) - { - rect.setLeftTopAndSize(mLocator->getRect().mLeft + 30, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight()); - mLocator->setRect(rect); - } + return TRUE; +} - if(mInfo) - { - rect.setLeftTopAndSize(mInfo->getRect().mLeft + 30, mInfo->getRect().mTop, mInfo->getRect().getWidth(), mInfo->getRect().getHeight()); - mInfo->setRect(rect); - } +S32 LLAvatarListItem::notifyParent(const LLSD& info) +{ + if (info.has("visibility_changed")) + { + updateChildren(); } -*/ - return TRUE; + return 0; } void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask) @@ -137,6 +119,8 @@ void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask) mProfileBtn->setVisible(mShowProfileBtn); LLPanel::onMouseEnter(x, y, mask); + + updateChildren(); } void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask) @@ -146,6 +130,8 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask) mProfileBtn->setVisible(false); LLPanel::onMouseLeave(x, y, mask); + + updateChildren(); } // virtual, called by LLAvatarTracker @@ -215,12 +201,8 @@ void LLAvatarListItem::showLastInteractionTime(bool show) if (show) return; - LLRect name_rect = mAvatarName->getRect(); - LLRect time_rect = mLastInteractionTime->getRect(); - mLastInteractionTime->setVisible(false); - name_rect.mRight += (time_rect.mRight - name_rect.mRight); - mAvatarName->setRect(name_rect); + updateChildren(); } void LLAvatarListItem::setLastInteractionTime(U32 secs_since) @@ -234,12 +216,6 @@ void LLAvatarListItem::setShowInfoBtn(bool show) if(mShowInfoBtn == show) return; mShowInfoBtn = show; - S32 width_delta = show ? - sInfoBtnWidth : sInfoBtnWidth; - - //Translating speaking indicator - mSpeakingIndicator->translate(width_delta, 0); - //Reshaping avatar name - mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight()); } void LLAvatarListItem::setShowProfileBtn(bool show) @@ -248,24 +224,17 @@ void LLAvatarListItem::setShowProfileBtn(bool show) if(mShowProfileBtn == show) return; mShowProfileBtn = show; - S32 width_delta = show ? - sProfileBtnWidth : sProfileBtnWidth; - - //Translating speaking indicator - mSpeakingIndicator->translate(width_delta, 0); - //Reshaping avatar name - mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight()); } -void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible) +void LLAvatarListItem::showSpeakingIndicator(bool visible) { // Already done? Then do nothing. if (mSpeakingIndicator->getVisible() == (BOOL)visible) return; - mSpeakingIndicator->setVisible(visible); - S32 width_delta = visible ? - sSpeakingIndicatorWidth : sSpeakingIndicatorWidth; - - //Reshaping avatar name - mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight()); +// Disabled to not contradict with SpeakingIndicatorManager functionality. EXT-3976 +// probably this method should be totally removed. +// mSpeakingIndicator->setVisible(visible); +// updateChildren(); } void LLAvatarListItem::setAvatarIconVisible(bool visible) @@ -276,36 +245,12 @@ void LLAvatarListItem::setAvatarIconVisible(bool visible) // Show/hide avatar icon. mAvatarIcon->setVisible(visible); - - // Move the avatar name horizontally by icon size + its distance from the avatar name. - LLRect name_rect = mAvatarName->getRect(); - name_rect.mLeft += visible ? sIconWidth : -sIconWidth; - mAvatarName->setRect(name_rect); + updateChildren(); } void LLAvatarListItem::onInfoBtnClick() { LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mAvatarId)); - - /* TODO fix positioning of inspector - localPointToScreen(mXPos, mYPos, &mXPos, &mYPos); - - - LLRect rect; - - // *TODO Vadim: rewrite this. "+= -" looks weird. - S32 delta = mYPos - inspector->getRect().getHeight(); - if(delta < 0) - { - mYPos += -delta; - } - - rect.setLeftTopAndSize(mXPos, mYPos, - inspector->getRect().getWidth(), inspector->getRect().getHeight()); - inspector->setRect(rect); - inspector->setFrontmost(true); - inspector->setVisible(true); - */ } void LLAvatarListItem::onProfileBtnClick() @@ -313,6 +258,21 @@ void LLAvatarListItem::onProfileBtnClick() LLAvatarActions::showProfile(mAvatarId); } +BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if(mInfoBtn->getRect().pointInRect(x, y)) + { + onInfoBtnClick(); + return TRUE; + } + if(mProfileBtn->getRect().pointInRect(x, y)) + { + onProfileBtnClick(); + return TRUE; + } + return LLPanel::handleDoubleClick(x, y, mask); +} + void LLAvatarListItem::setValue( const LLSD& value ) { if (!value.isMap()) return;; @@ -344,21 +304,6 @@ void LLAvatarListItem::onNameCache(const std::string& first_name, const std::str setName(name); } -void LLAvatarListItem::reshapeAvatarName() -{ - S32 width_delta = 0; - width_delta += mShowProfileBtn ? sProfileBtnWidth : 0; - width_delta += mSpeakingIndicator->getVisible() ? sSpeakingIndicatorWidth : 0; - width_delta += mAvatarIcon->getVisible() ? sIconWidth : 0; - width_delta += mShowInfoBtn ? sInfoBtnWidth : 0; - width_delta += mLastInteractionTime->getVisible() ? mLastInteractionTime->getRect().getWidth() : 0; - - S32 height = mAvatarName->getRect().getHeight(); - S32 width = getRect().getWidth() - width_delta; - - mAvatarName->reshape(width, height); -} - // Convert given number of seconds to a string like "23 minutes", "15 hours" or "3 years", // taking i18n into account. The format string to use is taken from the panel XML. std::string LLAvatarListItem::formatSeconds(U32 secs) @@ -492,4 +437,133 @@ LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap() return item_icon_color_map; } +// static +void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) +{ + //profile btn width + padding + S32 profile_btn_width = avatar_item->getRect().getWidth() - avatar_item->mProfileBtn->getRect().mLeft; + + //info btn width + padding + S32 info_btn_width = avatar_item->mProfileBtn->getRect().mLeft - avatar_item->mInfoBtn->getRect().mLeft; + + //speaking indicator width + padding + S32 speaking_indicator_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mSpeakingIndicator->getRect().mLeft; + + // last interaction time textbox width + padding + S32 last_interaction_time_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; + + // icon width + padding + S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; + + sLeftPadding = avatar_item->mAvatarIcon->getRect().mLeft; + sRightNamePadding = avatar_item->mLastInteractionTime->getRect().mLeft - avatar_item->mAvatarName->getRect().mRight; + + S32 index = ALIC_COUNT; + sChildrenWidths[--index] = icon_width; + sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space" + sChildrenWidths[--index] = last_interaction_time_width; + sChildrenWidths[--index] = speaking_indicator_width; + sChildrenWidths[--index] = info_btn_width; + sChildrenWidths[--index] = profile_btn_width; +} + +void LLAvatarListItem::updateChildren() +{ + LL_DEBUGS("AvatarItemReshape") << LL_ENDL; + LL_DEBUGS("AvatarItemReshape") << "Updating for: " << getAvatarName() << LL_ENDL; + + S32 name_new_width = getRect().getWidth(); + S32 ctrl_new_left = name_new_width; + S32 name_new_left = sLeftPadding; + + // iterate through all children and set them into correct position depend on each child visibility + // assume that child indexes are in back order: the first in Enum is the last (right) in the item + // iterate & set child views starting from right to left + for (S32 i = 0; i < ALIC_COUNT; ++i) + { + // skip "name" textbox, it will be processed out of loop later + if (ALIC_NAME == i) continue; + + LLView* control = getItemChildView((EAvatarListItemChildIndex)i); + + LL_DEBUGS("AvatarItemReshape") << "Processing control: " << control->getName() << LL_ENDL; + // skip invisible views + if (!control->getVisible()) continue; + + S32 ctrl_width = sChildrenWidths[i]; // including space between current & left controls + + // decrease available for + name_new_width -= ctrl_width; + LL_DEBUGS("AvatarItemReshape") << "width: " << ctrl_width << ", name_new_width: " << name_new_width << LL_ENDL; + + LLRect control_rect = control->getRect(); + LL_DEBUGS("AvatarItemReshape") << "rect before: " << control_rect << LL_ENDL; + + if (ALIC_ICON == i) + { + // assume that this is the last iteration, + // so it is not necessary to save "ctrl_new_left" value calculated on previous iterations + ctrl_new_left = sLeftPadding; + name_new_left = ctrl_new_left + ctrl_width; + } + else + { + ctrl_new_left -= ctrl_width; + } + + LL_DEBUGS("AvatarItemReshape") << "ctrl_new_left: " << ctrl_new_left << LL_ENDL; + + control_rect.setLeftTopAndSize( + ctrl_new_left, + control_rect.mTop, + control_rect.getWidth(), + control_rect.getHeight()); + + LL_DEBUGS("AvatarItemReshape") << "rect after: " << control_rect << LL_ENDL; + control->setShape(control_rect); + } + + // set size and position of the "name" child + LLView* name_view = getItemChildView(ALIC_NAME); + LLRect name_view_rect = name_view->getRect(); + LL_DEBUGS("AvatarItemReshape") << "name rect before: " << name_view_rect << LL_ENDL; + + // apply paddings + name_new_width -= sLeftPadding; + name_new_width -= sRightNamePadding; + + name_view_rect.setLeftTopAndSize( + name_new_left, + name_view_rect.mTop, + name_new_width, + name_view_rect.getHeight()); + + name_view->setShape(name_view_rect); + + LL_DEBUGS("AvatarItemReshape") << "name rect after: " << name_view_rect << LL_ENDL; +} + +LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_index) +{ + LLView* child_view = mAvatarName; + if (child_view_index < 0 || ALIC_COUNT <= child_view_index) + { + LL_WARNS("AvatarItemReshape") << "Child view index is out of range: " << child_view_index << LL_ENDL; + return child_view; + } + switch (child_view_index) + { + case ALIC_ICON: child_view = mAvatarIcon; break; + case ALIC_NAME: child_view = mAvatarName; break; + case ALIC_INTERACTION_TIME: child_view = mLastInteractionTime; break; + case ALIC_SPEAKER_INDICATOR: child_view = mSpeakingIndicator; break; + case ALIC_INFO_BUTTON: child_view = mInfoBtn; break; + case ALIC_PROFILE_BUTTON: child_view = mProfileBtn; break; + default: + LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL; + } + + return child_view; +} + // EOF diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 96097bc9b5..479a4833cb 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -74,6 +74,11 @@ public: virtual ~LLAvatarListItem(); virtual BOOL postBuild(); + + /** + * Processes notification from speaker indicator to update children when indicator's visibility is changed. + */ + virtual S32 notifyParent(const LLSD& info); virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual void onMouseEnter(S32 x, S32 y, MASK mask); virtual void setValue(const LLSD& value); @@ -88,7 +93,8 @@ public: //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly void setShowProfileBtn(bool show); void setShowInfoBtn(bool show); - void setSpeakingIndicatorVisible(bool visible); + void showSpeakingIndicator(bool show); + void showLastInteractionTime(bool show); void setAvatarIconVisible(bool visible); const LLUUID& getAvatarId() const; @@ -97,16 +103,7 @@ public: void onInfoBtnClick(); void onProfileBtnClick(); - void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); } - void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); } - void showLastInteractionTime(bool show); - - /** - * This method was added to fix EXT-2364 (Items in group/ad-hoc IM participant list (avatar names) should be reshaped when adding/removing the "(Moderator)" label) - * But this is a *HACK. The real reason of it was in incorrect logic while hiding profile/info/speaker buttons - * *TODO: new reshape method should be provided in lieu of this one to be called when visibility if those buttons is changed - */ - void reshapeAvatarName(); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); protected: /** @@ -124,6 +121,23 @@ private: E_UNKNOWN, } EOnlineStatus; + /** + * Enumeration of item elements in order from right to left. + * + * updateChildren() assumes that indexes are in the such order to process avatar icon easier. + * + * @see updateChildren() + */ + typedef enum e_avatar_item_child { + ALIC_PROFILE_BUTTON, + ALIC_INFO_BUTTON, + ALIC_SPEAKER_INDICATOR, + ALIC_INTERACTION_TIME, + ALIC_NAME, + ALIC_ICON, + ALIC_COUNT, + } EAvatarListItemChildIndex; + void setNameInternal(const std::string& name, const std::string& highlight); void onNameCache(const std::string& first_name, const std::string& last_name); @@ -135,6 +149,26 @@ private: typedef std::map icon_color_map_t; static icon_color_map_t& getItemIconColorMap(); + /** + * Initializes widths of all children to use them while changing visibility of any of them. + * + * @see updateChildren() + */ + static void initChildrenWidths(LLAvatarListItem* self); + + /** + * Updates position and rectangle of visible children to fit all available item's width. + */ + void updateChildren(); + + /** + * Gets child view specified by index. + * + * This method implemented via switch by all EAvatarListItemChildIndex values. + * It is used to not store children in array or vector to avoid of increasing memory usage. + */ + LLView* getItemChildView(EAvatarListItemChildIndex child_index); + LLTextBox* mAvatarName; LLTextBox* mLastInteractionTime; LLStyle::Params mAvatarNameStyle; @@ -151,10 +185,17 @@ private: bool mShowProfileBtn; static bool sStaticInitialized; // this variable is introduced to improve code readability - static S32 sIconWidth; // icon width + padding - static S32 sInfoBtnWidth; //info btn width + padding - static S32 sProfileBtnWidth; //profile btn width + padding - static S32 sSpeakingIndicatorWidth; //speaking indicator width + padding + static S32 sLeftPadding; // padding to first left visible child (icon or name) + static S32 sRightNamePadding; // right padding from name to next visible child + + /** + * Contains widths of each child specified by EAvatarListItemChildIndex + * including padding to the next right one. + * + * @see initChildrenWidths() + */ + static S32 sChildrenWidths[ALIC_COUNT]; + }; #endif //LL_LLAVATARLISTITEM_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 976b312509..bd68d52868 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -48,10 +48,20 @@ #include "llsyswellwindow.h" #include "llfloatercamera.h" #include "lltexteditor.h" +#include "llnotifications.h" // Build time optimization, generate extern template once in .cpp file template class LLBottomTray* LLSingleton::getInstance(); +namespace +{ + const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; + const std::string& PANEL_CHATBAR_NAME = "chat_bar"; + const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; + const std::string& PANEL_CAMERA_NAME = "cam_panel"; + const std::string& PANEL_GESTURE_NAME = "gesture_panel"; +} + LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), mSpeakPanel(NULL), @@ -161,6 +171,9 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam { chiclet->setIMSessionName(name); chiclet->setOtherParticipantId(other_participant_id); + + LLIMFloater::onIMChicletCreated(session_id); + } else { @@ -233,6 +246,61 @@ void LLBottomTray::onFocusLost() } } +void LLBottomTray::savePanelsShape() +{ + mSavedShapeList.clear(); + for (child_list_const_iter_t + child_it = mToolbarStack->beginChild(), + child_it_end = mToolbarStack->endChild(); + child_it != child_it_end; ++child_it) + { + mSavedShapeList.push_back( (*child_it)->getRect() ); + } +} + +void LLBottomTray::restorePanelsShape() +{ + if (mSavedShapeList.size() != mToolbarStack->getChildCount()) + return; + int i = 0; + for (child_list_const_iter_t + child_it = mToolbarStack->beginChild(), + child_it_end = mToolbarStack->endChild(); + child_it != child_it_end; ++child_it) + { + (*child_it)->setShape(mSavedShapeList[i++]); + } +} + +void LLBottomTray::onMouselookModeOut() +{ + // Apply the saved settings when we are not in mouselook mode, see EXT-3988. + { + setTrayButtonVisibleIfPossible (RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"),false); + } + // HACK: To avoid usage the LLLayoutStack logic of resizing, we force the updateLayout + // and then restore children saved shapes. See EXT-4309. + BOOL saved_anim = mToolbarStack->getAnimate(); + mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); + // Disable animation to prevent layout updating in several frames. + mToolbarStack->setAnimate(FALSE); + // Force the updating of layout to reset panels collapse factor. + mToolbarStack->updateLayout(); + // Restore animate state. + mToolbarStack->setAnimate(saved_anim); + // Restore saved shapes. + restorePanelsShape(); +} + +void LLBottomTray::onMouselookModeIn() +{ + savePanelsShape(); + mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE); +} + //virtual // setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode. // If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true), @@ -251,8 +319,10 @@ void LLBottomTray::setVisible(BOOL visible) { LLView* viewp = *child_it; std::string name = viewp->getName(); - - if ("chat_bar" == name || "movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name || "gesture_panel" == name) + + // Chat bar and gesture button are shown even in mouselook mode. + // But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988. + if ("chat_bar" == name || "gesture_panel" == name || (visibility && ("movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name))) continue; else { @@ -260,6 +330,11 @@ void LLBottomTray::setVisible(BOOL visible) } } } + + if(visible) + gFloaterView->setSnapOffsetBottom(getRect().getHeight()); + else + gFloaterView->setSnapOffsetBottom(0); } void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) @@ -324,15 +399,6 @@ void LLBottomTray::showSnapshotButton(BOOL visible) setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible); } -namespace -{ - const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - const std::string& PANEL_CHATBAR_NAME = "chat_bar"; - const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; - const std::string& PANEL_CAMERA_NAME = "cam_panel"; - const std::string& PANEL_GESTURE_NAME = "gesture_panel"; -} - BOOL LLBottomTray::postBuild() { @@ -1005,7 +1071,7 @@ void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool vis panel->setVisible(visible); } -void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible) +void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification) { bool can_be_set = true; @@ -1045,7 +1111,11 @@ void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type { // mark this button to show it while future bottom tray extending mResizeState |= shown_object_type; - LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown"); + if ( raise_notification ) + LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown", + LLSD(), + LLSD(), + LLNotificationFunctorRegistry::instance().DONOTHING); } } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 9be0e5810f..562ee56912 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -92,7 +92,10 @@ public: void showMoveButton(BOOL visible); void showCameraButton(BOOL visible); void showSnapshotButton(BOOL visible); - + + void onMouselookModeIn(); + void onMouselookModeOut(); + /** * Creates IM Chiclet based on session type (IM chat or Group chat) */ @@ -167,7 +170,14 @@ private: * - if hidden via context menu button should be shown but there is no enough room for now * it will be shown while extending. */ - void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible); + void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification = true); + + /** + * Save and restore children shapes. + * Used to avoid the LLLayoutStack resizing logic between mouse look mode switching. + */ + void savePanelsShape(); + void restorePanelsShape(); MASK mResizeState; @@ -177,6 +187,9 @@ private: typedef std::map state_object_width_map_t; state_object_width_map_t mObjectDefaultWidthMap; + typedef std::vector shape_list_t; + shape_list_t mSavedShapeList; + protected: LLBottomTray(const LLSD& key = LLSD()); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index a402f59fa1..f346a4b8c2 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -47,11 +47,13 @@ #include "llfloaterreg.h" #include "llparticipantlist.h" #include "llspeakers.h" +#include "lltextutil.h" #include "lltransientfloatermgr.h" #include "llviewerwindow.h" #include "llvoicechannel.h" static void get_voice_participants_uuids(std::vector& speakers_uuids); +void reshape_floater(LLCallFloater* floater, S32 delta_height); class LLNonAvatarCaller : public LLAvatarListItem { @@ -76,6 +78,12 @@ public: return rv; } + void setName(const std::string& name) + { + const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name); + LLAvatarListItem::setName(formatted_phone); + } + void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); } }; @@ -217,16 +225,6 @@ void LLCallFloater::onChange() } } -S32 LLCallFloater::notifyParent(const LLSD& info) -{ - if("size_changes" == info["action"]) - { - reshapeToFitContent(); - return 1; - } - return LLDockableFloater::notifyParent(info); -} - ////////////////////////////////////////////////////////////////////////// /// PRIVATE SECTION ////////////////////////////////////////////////////////////////////////// @@ -270,6 +268,11 @@ void LLCallFloater::updateSession() case IM_NOTHING_SPECIAL: case IM_SESSION_P2P_INVITE: mVoiceType = VC_PEER_TO_PEER; + + if (!im_session->mOtherParticipantIsAvatar) + { + mVoiceType = VC_PEER_TO_PEER_AVALINE; + } break; case IM_SESSION_CONFERENCE_START: case IM_SESSION_GROUP_START: @@ -302,8 +305,8 @@ void LLCallFloater::updateSession() //hide "Leave Call" button for nearby chat bool is_local_chat = mVoiceType == VC_LOCAL_CHAT; - childSetVisible("leave_call_btn", !is_local_chat); - + childSetVisible("leave_call_btn_panel", !is_local_chat); + refreshParticipantList(); updateAgentModeratorState(); @@ -321,16 +324,13 @@ void LLCallFloater::updateSession() void LLCallFloater::refreshParticipantList() { - bool non_avatar_caller = false; - if (VC_PEER_TO_PEER == mVoiceType) + bool non_avatar_caller = VC_PEER_TO_PEER_AVALINE == mVoiceType; + + if (non_avatar_caller) { LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID()); - non_avatar_caller = !session->mOtherParticipantIsAvatar; - if (non_avatar_caller) - { - mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID); - mNonAvatarCaller->setName(session->mName); - } + mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID); + mNonAvatarCaller->setName(session->mName); } mNonAvatarCaller->setVisible(non_avatar_caller); @@ -390,9 +390,17 @@ void LLCallFloater::updateTitle() title = getString("title_nearby"); break; case VC_PEER_TO_PEER: + case VC_PEER_TO_PEER_AVALINE: { + title = voice_channel->getSessionName(); + + if (VC_PEER_TO_PEER_AVALINE == mVoiceType) + { + title = LLTextUtil::formatPhoneNumber(title); + } + LLStringUtil::format_map_t args; - args["[NAME]"] = voice_channel->getSessionName(); + args["[NAME]"] = title; title = getString("title_peer_2_peer", args); } break; @@ -706,13 +714,28 @@ void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id) bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id) { - if (mVoiceType != VC_LOCAL_CHAT) - return true; + bool is_valid = true; + switch (mVoiceType) + { + case VC_LOCAL_CHAT: + { + // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). + std::vector speakers; + get_voice_participants_uuids(speakers); + is_valid = std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); + } + break; + case VC_GROUP_CHAT: + // if participant had left this call before do not allow add her again. See EXT-4216. + // but if she Join she will be added into the list from the LLCallFloater::onChange() + is_valid = STATE_LEFT != getState(speaker_id); + break; + default: + // do nothing. required for Linux build + break; + } - // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). - std::vector speakers; - get_voice_participants_uuids(speakers); - return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); + return is_valid; } void LLCallFloater::connectToChannel(LLVoiceChannel* channel) @@ -765,91 +788,4 @@ void LLCallFloater::reset() mSpeakerManager = NULL; } -void reshape_floater(LLCallFloater* floater, S32 delta_height) -{ - // Try to update floater top side if it is docked(to bottom bar). - // Try to update floater bottom side or top side if it is un-docked. - // If world rect is too small, floater will not be reshaped at all. - - LLRect floater_rect = floater->getRect(); - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); - - // floater is docked to bottom bar - if(floater->isDocked()) - { - // can update floater top side - if(floater_rect.mTop + delta_height < world_rect.mTop) - { - floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height, - floater_rect.mRight, floater_rect.mBottom); - } - } - // floater is un-docked - else - { - // can update floater bottom side - if( floater_rect.mBottom - delta_height >= world_rect.mBottom ) - { - floater_rect.set(floater_rect.mLeft, floater_rect.mTop, - floater_rect.mRight, floater_rect.mBottom - delta_height); - } - // could not update floater bottom side, check if we can update floater top side - else if( floater_rect.mTop + delta_height < world_rect.mTop ) - { - floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height, - floater_rect.mRight, floater_rect.mBottom); - } - } - - floater->reshape(floater_rect.getWidth(), floater_rect.getHeight()); - floater->setRect(floater_rect); -} - -void LLCallFloater::reshapeToFitContent() -{ - const S32 ITEM_HEIGHT = getParticipantItemHeight(); - static const S32 MAX_VISIBLE_ITEMS = getMaxVisibleItems(); - - static S32 items_pad = mAvatarList->getItemsPad(); - S32 list_height = mAvatarList->getRect().getHeight(); - S32 items_height = mAvatarList->getItemsRect().getHeight(); - if(items_height <= 0) - { - // make "no one near" text visible - items_height = ITEM_HEIGHT + items_pad; - } - S32 max_list_height = MAX_VISIBLE_ITEMS * ITEM_HEIGHT + items_pad * (MAX_VISIBLE_ITEMS - 1); - max_list_height += 2* mAvatarList->getBorderWidth(); - - S32 delta = items_height - list_height; - // too many items, don't reshape floater anymore, let scroll bar appear. - if(items_height > max_list_height) - { - delta = max_list_height - list_height; - } - - reshape_floater(this, delta); -} - -S32 LLCallFloater::getParticipantItemHeight() -{ - std::vector items; - mAvatarList->getItems(items); - if(items.size() > 0) - { - return items[0]->getRect().getHeight(); - } - else - { - return getChild("non_avatar_caller")->getRect().getHeight(); - } -} - -S32 LLCallFloater::getMaxVisibleItems() -{ - S32 value = 5; // default value, in case convertToS32() fails. - LLStringUtil::convertToS32(getString("max_visible_items"), value); - return value; -} - //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 8aba93fc43..096594aaa2 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -75,11 +75,6 @@ public: */ /*virtual*/ void onChange(); - /** - * Will reshape floater when participant list size changes - */ - /*virtual*/ S32 notifyParent(const LLSD& info); - static void sOnCurrentChannelChanged(const LLUUID& session_id); private: @@ -88,7 +83,8 @@ private: VC_LOCAL_CHAT, VC_GROUP_CHAT, VC_AD_HOC_CHAT, - VC_PEER_TO_PEER + VC_PEER_TO_PEER, + VC_PEER_TO_PEER_AVALINE }EVoiceControls; typedef enum e_speaker_state @@ -220,21 +216,6 @@ private: */ void reset(); - /** - * Reshapes floater to fit participant list height - */ - void reshapeToFitContent(); - - /** - * Returns height of participant list item - */ - S32 getParticipantItemHeight(); - - /** - * Returns predefined max visible participants. - */ - S32 getMaxVisibleItems(); - private: speaker_state_map_t mSpeakerStateMap; LLSpeakerMgr* mSpeakerManager; diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 442dc660cd..b32a955038 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -48,7 +48,6 @@ #include "llcombobox.h" #include "llcommandhandler.h" // secondlife:///app/chat/ support #include "llviewercontrol.h" -#include "llfloaterchat.h" #include "llgesturemgr.h" #include "llkeyboard.h" #include "lllineeditor.h" @@ -548,7 +547,7 @@ void LLChatBar::onInputEditorFocusLost() // static void LLChatBar::onInputEditorGainFocus() { - LLFloaterChat::setHistoryCursorAndScrollToEnd(); + //LLFloaterChat::setHistoryCursorAndScrollToEnd(); } void LLChatBar::onClickSay( LLUICtrl* ctrl ) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 21cadda6e3..a46cd84b60 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -499,7 +499,24 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ style_params.font.name(font_name); style_params.font.size(font_size); style_params.font.style(input_append_params.font.style); - + + std::string prefix = chat.mText.substr(0, 4); + + //IRC styled /me messages. + bool irc_me = prefix == "/me " || prefix == "/me'"; + + // Delimiter after a name in header copy/past and in plain text mode + std::string delimiter = (chat.mChatType != CHAT_TYPE_SHOUT && chat.mChatType != CHAT_TYPE_WHISPER) + ? ": " + : " "; + + // Don't add any delimiter after name in irc styled messages + if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) + { + delimiter = LLStringUtil::null; + style_params.font.style = "ITALIC"; + } + if (use_plain_text_chat_history) { mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params); @@ -512,11 +529,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ LLStyle::Params link_params(style_params); link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); // Convert the name to a hotlink and add to message. - mEditor->appendText(chat.mFromName + ": ", false, link_params); + mEditor->appendText(chat.mFromName + delimiter, false, link_params); } else { - mEditor->appendText(chat.mFromName + ": ", false, style_params); + mEditor->appendText(chat.mFromName + delimiter, false, style_params); } } } @@ -560,39 +577,25 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); - std::string header_text = "[" + chat.mTimeStr + "] "; + std::string widget_associated_text = "\n[" + chat.mTimeStr + "] "; if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM) - header_text += chat.mFromName + ": "; + widget_associated_text += chat.mFromName + delimiter; - mEditor->appendWidget(p, header_text, false); + mEditor->appendWidget(p, widget_associated_text, false); mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; } - //Handle IRC styled /me messages. - std::string prefix = chat.mText.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") - { - style_params.font.style = "ITALIC"; - if (chat.mFromName.size() > 0) - mEditor->appendText(chat.mFromName + " ", TRUE, style_params); - // Ensure that message ends with NewLine, to avoid losing of new lines - // while copy/paste from text chat. See EXT-3263. - mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); - } - else + std::string message = irc_me ? chat.mText.substr(3) : chat.mText; + mEditor->appendText(message, FALSE, style_params); + mEditor->blockUndo(); + + // automatically scroll to end when receiving chat from myself + if (chat.mFromID == gAgentID) { - std::string message(chat.mText); - if ( message.size() > 0 && !LLStringOps::isSpace(message[message.size() - 1]) ) - { - // Ensure that message ends with NewLine, to avoid losing of new lines - // while copy/paste from text chat. See EXT-3263. - message += NEW_LINE; - } - mEditor->appendText(message, FALSE, style_params); + mEditor->setCursorAndScrollToEnd(); } - mEditor->blockUndo(); } void LLChatHistory::draw() @@ -606,3 +609,11 @@ void LLChatHistory::draw() LLUICtrl::draw(); } +void LLChatHistory::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + bool is_scrolled_to_end = mEditor->scrolledToEnd(); + LLUICtrl::reshape( width, height, called_from_parent ); + // update scroll + if (is_scrolled_to_end) + mEditor->setCursorAndScrollToEnd(); +} diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 260015e2dc..f2d403f639 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -119,6 +119,7 @@ class LLChatHistory : public LLUICtrl */ void appendMessage(const LLChat& chat, const bool use_plain_text_chat_history = false, const LLStyle::Params& input_append_params = LLStyle::Params()); /*virtual*/ void clear(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); private: std::string mLastFromName; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 92df281307..f7f7ee83af 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -168,30 +168,30 @@ void LLNearbyChatToastPanel::init(LLSD& notification) msg_text->setText(std::string("")); - std::string str_sender; - - if(gAgentID != mFromID) + if ( notification["chat_style"].asInteger() != CHAT_STYLE_IRC ) + { + std::string str_sender; + str_sender = fromName; - else - str_sender = LLTrans::getString("You"); - str_sender+=" "; + str_sender+=" "; - //append user name - { - LLStyle::Params style_params_name; + //append user name + { + LLStyle::Params style_params_name; - LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor"); + LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor"); - style_params_name.color(userNameColor); - - std::string font_name = LLFontGL::nameFromFont(messageFont); - std::string font_style_size = LLFontGL::sizeFromFont(messageFont); - style_params_name.font.name(font_name); - style_params_name.font.size(font_style_size); - - msg_text->appendText(str_sender, FALSE, style_params_name); - + style_params_name.color(userNameColor); + + std::string font_name = LLFontGL::nameFromFont(messageFont); + std::string font_style_size = LLFontGL::sizeFromFont(messageFont); + style_params_name.font.name(font_name); + style_params_name.font.size(font_style_size); + + msg_text->appendText(str_sender, FALSE, style_params_name); + + } } //append text @@ -252,11 +252,33 @@ void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask) } BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask) +{ + return LLPanel::handleMouseDown(x,y,mask); +} + +BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) { if(mSourceType != CHAT_SOURCE_AGENT) - return LLPanel::handleMouseDown(x,y,mask); + return LLPanel::handleMouseUp(x,y,mask); + + LLChatMsgBox* text_box = getChild("msg_text", false); + S32 local_x = x - text_box->getRect().mLeft; + S32 local_y = y - text_box->getRect().mBottom; + + //if text_box process mouse up (ussually this is click on url) - we didn't show nearby_chat. + if (text_box->pointInView(local_x, local_y) ) + { + if (text_box->handleMouseUp(local_x,local_y,mask) == TRUE) + return TRUE; + else + { + LLFloaterReg::showInstance("nearby_chat",LLSD()); + return FALSE; + } + } + LLFloaterReg::showInstance("nearby_chat",LLSD()); - return LLPanel::handleMouseDown(x,y,mask); + return LLPanel::handleMouseUp(x,y,mask); } void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 0a85c52401..f4b8655054 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -68,6 +68,7 @@ public: void onMouseLeave (S32 x, S32 y, MASK mask); void onMouseEnter (S32 x, S32 y, MASK mask); BOOL handleMouseDown (S32 x, S32 y, MASK mask); + BOOL handleMouseUp (S32 x, S32 y, MASK mask); virtual BOOL postBuild(); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index dc2e22f899..8da207f887 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -47,6 +47,7 @@ #include "llnotificationsutil.h" #include "lloutputmonitorctrl.h" #include "llscriptfloater.h" +#include "llspeakers.h" #include "lltextbox.h" #include "llvoiceclient.h" #include "llgroupmgr.h" @@ -453,6 +454,7 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) , mNewMessagesIcon(NULL) , mSpeakerCtrl(NULL) , mCounterCtrl(NULL) +, mChicletButton(NULL) { enableCounterControl(p.enable_counter); } @@ -540,6 +542,11 @@ void LLIMChiclet::toggleSpeakerControl() void LLIMChiclet::setCounter(S32 counter) { + if (mCounterCtrl->getCounter() == counter) + { + return; + } + mCounterCtrl->setCounter(counter); setShowCounter(counter); setShowNewMessagesIcon(counter); @@ -571,6 +578,11 @@ void LLIMChiclet::onMouseDown() setCounter(0); } +void LLIMChiclet::setToggleState(bool toggle) +{ + mChicletButton->setToggleState(toggle); +} + BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask) { onMouseDown(); @@ -629,6 +641,7 @@ LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) LLIMP2PChiclet::Params::Params() : avatar_icon("avatar_icon") +, chiclet_button("chiclet_button") , unread_notifications("unread_notifications") , speaker("speaker") , new_message_icon("new_message_icon") @@ -641,6 +654,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create(button_params); + addChild(mChicletButton); + LLIconCtrl::Params new_msg_params = p.new_message_icon; mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); addChild(mNewMessagesIcon); @@ -755,6 +772,7 @@ void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) LLAdHocChiclet::Params::Params() : avatar_icon("avatar_icon") +, chiclet_button("chiclet_button") , unread_notifications("unread_notifications") , speaker("speaker") , new_message_icon("new_message_icon") @@ -768,6 +786,10 @@ LLAdHocChiclet::LLAdHocChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create(button_params); + addChild(mChicletButton); + LLIconCtrl::Params new_msg_params = p.new_message_icon; mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); addChild(mNewMessagesIcon); @@ -882,6 +904,7 @@ BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) LLIMGroupChiclet::Params::Params() : group_icon("group_icon") +, chiclet_button("chiclet_button") , unread_notifications("unread_notifications") , speaker("speaker") , new_message_icon("new_message_icon") @@ -895,6 +918,10 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create(button_params); + addChild(mChicletButton); + LLIconCtrl::Params new_msg_params = p.new_message_icon; mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); addChild(mNewMessagesIcon); @@ -1267,10 +1294,12 @@ void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it) { - mScrollArea->removeChild(*it); + LLChiclet* chiclet = *it; + mScrollArea->removeChild(chiclet); mChicletList.erase(it); arrange(); + chiclet->die(); } void LLChicletPanel::removeChiclet(S32 index) @@ -1409,6 +1438,32 @@ S32 LLChicletPanel::notifyParent(const LLSD& info) return LLPanel::notifyParent(info); } +void LLChicletPanel::setChicletToggleState(const LLUUID& session_id, bool toggle) +{ + if(session_id.isNull()) + { + llwarns << "Null Session ID" << llendl; + } + + // toggle off all chiclets, except specified + S32 size = getChicletCount(); + for(int n = 0; n < size; ++n) + { + LLIMChiclet* chiclet = getChiclet(n); + if(chiclet && chiclet->getSessionId() != session_id) + { + chiclet->setToggleState(false); + } + } + + // toggle specified chiclet + LLIMChiclet* chiclet = findChiclet(session_id); + if(chiclet) + { + chiclet->setToggleState(toggle); + } +} + void LLChicletPanel::arrange() { if(mChicletList.empty()) @@ -1801,6 +1856,7 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) LLScriptChiclet::Params::Params() : icon("icon") + , chiclet_button("chiclet_button") , new_message_icon("new_message_icon") { } @@ -1809,6 +1865,10 @@ LLScriptChiclet::LLScriptChiclet(const Params&p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) { + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create(button_params); + addChild(mChicletButton); + LLIconCtrl::Params new_msg_params = p.new_message_icon; mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); addChild(mNewMessagesIcon); @@ -1857,6 +1917,7 @@ static const std::string INVENTORY_USER_OFFER ("UserGiveItem"); LLInvOfferChiclet::Params::Params() : icon("icon") + , chiclet_button("chiclet_button") , new_message_icon("new_message_icon") { } @@ -1865,6 +1926,10 @@ LLInvOfferChiclet::LLInvOfferChiclet(const Params&p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) { + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create(button_params); + addChild(mChicletButton); + LLIconCtrl::Params new_msg_params = p.new_message_icon; mNewMessagesIcon = LLUICtrlFactory::create(new_msg_params); addChild(mNewMessagesIcon); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 3665e4d093..bb4846aa57 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -325,7 +325,7 @@ public: }; - /*virtual*/ ~LLIMChiclet() {}; + virtual ~LLIMChiclet() {}; /** * Sets IM session name. This name will be displayed in chiclet tooltip. @@ -422,6 +422,8 @@ public: */ virtual void onMouseDown(); + virtual void setToggleState(bool toggle); + protected: LLIMChiclet(const LLIMChiclet::Params& p); @@ -438,7 +440,7 @@ protected: LLIconCtrl* mNewMessagesIcon; LLChicletNotificationCounterCtrl* mCounterCtrl; LLChicletSpeakerCtrl* mSpeakerCtrl; - + LLButton* mChicletButton; /** the id of another participant, either an avatar id or a group id*/ LLUUID mOtherParticipantId; @@ -473,6 +475,8 @@ class LLIMP2PChiclet : public LLIMChiclet public: struct Params : public LLInitParam::Block { + Optional chiclet_button; + Optional avatar_icon; Optional unread_notifications; @@ -538,6 +542,8 @@ class LLAdHocChiclet : public LLIMChiclet public: struct Params : public LLInitParam::Block { + Optional chiclet_button; + Optional avatar_icon; Optional unread_notifications; @@ -614,6 +620,8 @@ public: struct Params : public LLInitParam::Block { + Optional chiclet_button; + Optional icon; Optional new_message_icon; @@ -656,6 +664,8 @@ public: struct Params : public LLInitParam::Block { + Optional chiclet_button; + Optional icon; Optional new_message_icon; @@ -697,6 +707,8 @@ public: struct Params : public LLInitParam::Block { + Optional chiclet_button; + Optional group_icon; Optional unread_notifications; @@ -1040,6 +1052,11 @@ public: S32 notifyParent(const LLSD& info); + /** + * Toggle chiclet by session id ON and toggle OFF all other chiclets. + */ + void setChicletToggleState(const LLUUID& session_id, bool toggle); + protected: LLChicletPanel(const Params&p); friend class LLUICtrlFactory; diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index eb9a2fec2f..47f1b7c9f5 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -59,7 +59,6 @@ #include "llbutton.h" #include "lldir.h" -#include "llfloaterchat.h" #include "llnotificationsutil.h" #include "llviewerstats.h" #include "llvfile.h" @@ -447,14 +446,20 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { - LLChat chat(LLTrans::getString("CompileQueueScriptNotFound")); - LLFloaterChat::addChat(chat); + //TODO* CHAT: how to show this? + //LLSD args; + //args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound); + //LLNotificationsUtil::add("SystemMessage", args); + buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mScriptName; } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLChat chat(LLTrans::getString("CompileQueueInsufficientPermDownload")); - LLFloaterChat::addChat(chat); + //TODO* CHAT: how to show this? + //LLSD args; + //args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound); + //LLNotificationsUtil::add("SystemMessage", args); + buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mScriptName; } else diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp index 10b7935caf..abb2fdeb9a 100644 --- a/indra/newview/lldateutil.cpp +++ b/indra/newview/lldateutil.cpp @@ -44,15 +44,18 @@ static S32 DAYS_PER_MONTH_LEAP[] = static S32 days_from_month(S32 year, S32 month) { + llassert_always(1 <= month); + llassert_always(month <= 12); + if (year % 4 == 0 && year % 100 != 0) { // leap year - return DAYS_PER_MONTH_LEAP[month]; + return DAYS_PER_MONTH_LEAP[month - 1]; } else { - return DAYS_PER_MONTH_NOLEAP[month]; + return DAYS_PER_MONTH_NOLEAP[month - 1]; } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 5f845c3721..03a8b108e2 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1149,14 +1149,14 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if (!LLPipeline::sRenderDeferred) { bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - bump->createGLTexture(bump->getDiscardLevel(), dst_image); + bump->createGLTexture(0, dst_image); } else { LLPointer nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); generateNormalMapFromAlpha(src, nrm_image); bump->setExplicitFormat(GL_RGBA, GL_RGBA); - bump->createGLTexture(bump->getDiscardLevel(), nrm_image); + bump->createGLTexture(0, nrm_image); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index c14ca2473b..c7cd77cb65 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -159,15 +159,10 @@ void LLDrawPoolWLSky::renderStars(void) const // *NOTE: have to have bound the cloud noise texture already since register // combiners blending below requires something to be bound // and we might as well only bind once. - //gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gPipeline.disableLights(); - - if (!LLPipeline::sReflectionRender) - { - glPointSize(2.f); - } - + // *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid // clamping and allow the star_alpha param to brighten the stars. bool error; @@ -175,16 +170,20 @@ void LLDrawPoolWLSky::renderStars(void) const star_alpha.mV[3] = LLWLParamManager::instance()->mCurParams.getFloat("star_brightness", error) / 2.f; llassert_always(!error); + gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex()); + + gGL.pushMatrix(); + glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); // gl_FragColor.rgb = gl_Color.rgb; // gl_FragColor.a = gl_Color.a * star_alpha.a; - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_PREV_ALPHA, LLTexUnit::TBS_CONST_ALPHA); + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); gSky.mVOWLSkyp->drawStars(); - glPointSize(1.f); - + gGL.popMatrix(); + // and disable the combiner states gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index 7ff760ac39..9059f6382f 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -43,7 +43,7 @@ public: static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0; static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_COLOR; + LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; LLDrawPoolWLSky(void); /*virtual*/ ~LLDrawPoolWLSky(); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index effa57b1ef..4fa97e789b 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -314,7 +314,7 @@ void LLFastTimerView::draw() S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; S32 texth, textw; - LLPointer box_imagep = LLUI::getUIImage("rounded_square.tga"); + LLPointer box_imagep = LLUI::getUIImage("Rounded_Square"); // Draw the window background gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -323,7 +323,9 @@ void LLFastTimerView::draw() S32 xleft = margin; S32 ytop = margin; - mAverageCyclesPerTimer = llround(lerp((F32)mAverageCyclesPerTimer, (F32)(LLFastTimer::sTimerCycles / (U64)LLFastTimer::sTimerCalls), 0.1f)); + mAverageCyclesPerTimer = LLFastTimer::sTimerCalls == 0 + ? 0 + : llround(lerp((F32)mAverageCyclesPerTimer, (F32)(LLFastTimer::sTimerCycles / (U64)LLFastTimer::sTimerCalls), 0.1f)); LLFastTimer::sTimerCycles = 0; LLFastTimer::sTimerCalls = 0; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 6ae6b4877a..fb94657278 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -483,6 +483,10 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (drop) { + if (mItems.empty()) + { + setLandingTab(NULL); + } handleNewFavoriteDragAndDrop(item, favorites_id, x, y); showDragMarker(FALSE); } @@ -508,14 +512,14 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) if (dest) { - updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId()); + LLInventoryModel::updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId()); } else { mItems.push_back(gInventory.getItem(mDragItemId)); } - saveItemsOrder(mItems); + gInventory.saveItemsOrder(mItems); LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get(); @@ -644,7 +648,7 @@ LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode() bool success = LLUICtrlFactory::getLayeredXMLNode("favorites_bar_button.xml", buttonXMLNode); if (!success) { - llwarns << "Unable to read xml file with button for Favorites Bar: favorites_bar_button.xml" << llendl; + llwarns << "Failed to create Favorites Bar button from favorites_bar_button.xml" << llendl; buttonXMLNode = NULL; } return buttonXMLNode; @@ -1193,25 +1197,6 @@ BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array return result; } -void LLFavoritesBarCtrl::saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - } - - gInventory.notifyObservers(); -} - LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) { LLInventoryModel::item_array_t::iterator result = items.end(); @@ -1228,15 +1213,6 @@ LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLIn return result; } -void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem) { LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId); diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 9ac734baff..40dd551eef 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -126,16 +126,7 @@ private: // checks if the current order of the favorites items must be saved BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items); - // saves current order of the favorites items - void saveItemsOrder(LLInventoryModel::item_array_t& items); - - /* - * changes favorites items order by insertion of the item identified by srcItemId - * BEFORE the item identified by destItemId. both items must exist in items array. - */ - void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId); - - /* + /** * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId. * this function assumes that an item identified by insertedItemId doesn't exist in items array. */ diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index 7fd0e070be..b3fdf60b11 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -45,6 +45,7 @@ #include "llappviewer.h" #include "lltracker.h" +/* // static std::set LLFirstUse::sConfigVariables; @@ -75,7 +76,8 @@ void LLFirstUse::resetFirstUse() gWarningSettings.setBOOL(*iter, TRUE); } } - +*/ +/* // Called whenever the viewer detects that your balance went up void LLFirstUse::useBalanceIncrease(S32 delta) @@ -145,6 +147,8 @@ void LLFirstUse::useBuild() LLNotificationsUtil::add("FirstBuild"); } } + + */ /* // static void LLFirstUse::useLeftClickNoHit() @@ -157,6 +161,7 @@ void LLFirstUse::useLeftClickNoHit() } } */ +/* // static void LLFirstUse::useTeleport() { @@ -171,7 +176,7 @@ void LLFirstUse::useTeleport() } } } - +*/ // static void LLFirstUse::useOverrideKeys() { @@ -187,7 +192,7 @@ void LLFirstUse::useOverrideKeys() } } } - +/* // static void LLFirstUse::useAttach() { @@ -216,6 +221,7 @@ void LLFirstUse::useInventory() } } +*/ // static void LLFirstUse::useSandbox() @@ -230,7 +236,7 @@ void LLFirstUse::useSandbox() LLNotificationsUtil::add("FirstSandbox", args); } } - +/* // static void LLFirstUse::useFlexible() { @@ -277,3 +283,4 @@ void LLFirstUse::useMedia() //LLNotificationsUtil::add("FirstMedia"); } } +*/ diff --git a/indra/newview/llfirstuse.h b/indra/newview/llfirstuse.h index 7b4f9f516f..3c7551f6cb 100644 --- a/indra/newview/llfirstuse.h +++ b/indra/newview/llfirstuse.h @@ -79,6 +79,7 @@ object or from inventory. class LLFirstUse { public: +/* // Add a config variable to be reset on resetFirstUse() static void addConfigVariable(const std::string& var); @@ -97,11 +98,16 @@ public: static void useBuild(); // static void useLeftClickNoHit(); static void useTeleport(); +*/ static void useOverrideKeys(); +/* static void useAttach(); static void useAppearance(); static void useInventory(); + */ static void useSandbox(); + +/* static void useFlexible(); static void useDebugMenus(); static void useSculptedPrim(); @@ -109,6 +115,7 @@ public: protected: static std::set sConfigVariables; +*/ }; #endif diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index e80499688e..ef69f39ad2 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -167,20 +167,21 @@ BOOL LLFloaterAbout::postBuild() // Now build the various pieces support << getString("AboutHeader", args); - if (info.has("COMPILER")) - { - support << "\n\n" << getString("AboutCompiler", args); - } if (info.has("REGION")) { support << "\n\n" << getString("AboutPosition", args); } support << "\n\n" << getString("AboutSystem", args); + support << "\n"; if (info.has("GRAPHICS_DRIVER_VERSION")) { - support << "\n\n" << getString("AboutDriver", args); + support << "\n" << getString("AboutDriver", args); + } + support << "\n" << getString("AboutLibs", args); + if (info.has("COMPILER")) + { + support << "\n" << getString("AboutCompiler", args); } - support << "\n\n" << getString("AboutLibs", args); if (info.has("PACKETS_IN")) { support << '\n' << getString("AboutTraffic", args); @@ -193,11 +194,11 @@ BOOL LLFloaterAbout::postBuild() support_widget->blockUndo(); // Fix views - support_widget->setCursorPos(0); support_widget->setEnabled(FALSE); + support_widget->startOfDoc(); - credits_widget->setCursorPos(0); credits_widget->setEnabled(FALSE); + credits_widget->startOfDoc(); return TRUE; } @@ -268,7 +269,7 @@ LLSD LLFloaterAbout::getInfo() info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : LLTrans::getString("NotConnected"); // TODO: Implement media plugin version query - info["QT_WEBKIT_VERSION"] = "4.5.2 (version number hard-coded)"; + info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)"; if (gPacketsIn > 0) { diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 538b44c056..5c3a54e34b 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -48,7 +48,6 @@ #include "llresmgr.h" #include "llbutton.h" #include "lldir.h" -#include "llfloaterchat.h" #include "llviewerstats.h" #include "lluictrlfactory.h" #include "llselectmgr.h" diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index 764aff68c9..9496e94780 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -144,6 +144,11 @@ void LLPanelCameraZoom::onSliderValueChanged() mSavedSliderVal = val; } +void activate_camera_tool() +{ + LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); +}; + // // Member functions // @@ -151,7 +156,7 @@ void LLPanelCameraZoom::onSliderValueChanged() /*static*/ bool LLFloaterCamera::inFreeCameraMode() { LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance(); - if (floater_camera && floater_camera->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA) + if (floater_camera && floater_camera->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA && gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) { return true; } @@ -177,27 +182,17 @@ void LLFloaterCamera::update() } -/*static*/ void LLFloaterCamera::updateIfNotInAvatarViewMode() -{ - LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance(); - if (floater_camera && !floater_camera->inAvatarViewMode()) - { - floater_camera->update(); - } -} - - void LLFloaterCamera::toPrevMode() { switchMode(mPrevMode); } -/*static*/ void LLFloaterCamera::toPrevModeIfInAvatarViewMode() +/*static*/ void LLFloaterCamera::onLeavingMouseLook() { LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance(); - if (floater_camera && floater_camera->inAvatarViewMode()) + if (floater_camera && floater_camera->inFreeCameraMode()) { - floater_camera->toPrevMode(); + activate_camera_tool(); } } @@ -325,7 +320,7 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode) break; case CAMERA_CTRL_MODE_FREE_CAMERA: - LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); + activate_camera_tool(); break; case CAMERA_CTRL_MODE_AVATAR_VIEW: diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 5d44b4944d..45d5e9a845 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -61,7 +61,7 @@ public: /* callback for camera presets changing */ static void onClickCameraPresets(const LLSD& param); - static void toPrevModeIfInAvatarViewMode(); + static void onLeavingMouseLook(); /** resets current camera mode to orbit mode */ static void resetCameraMode(); @@ -69,8 +69,6 @@ public: /* determines actual mode and updates ui */ void update(); - static void updateIfNotInAvatarViewMode(); - virtual void onOpen(const LLSD& key); virtual void onClose(bool app_quitting); diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index b9e0f928f1..cdb9b8edb8 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -37,8 +37,6 @@ #include "llviewerprecompiledheaders.h" -#include "llfloaterchat.h" - // project include #include "llagent.h" #include "llappviewer.h" @@ -190,7 +188,14 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) { if (log_to_file && (gSavedPerAccountSettings.getBOOL("LogChat"))) { - LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText); + if (chat.mChatType != CHAT_TYPE_WHISPER && chat.mChatType != CHAT_TYPE_SHOUT) + { + LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText); + } + else + { + LLLogChat::saveHistory("chat", "", chat.mFromID, chat.mFromName + " " + chat.mText); + } } LLColor4 color = get_text_color(chat); @@ -306,27 +311,17 @@ void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data) } // Put a line of chat in all the right places -void LLFloaterChat::addChat(const LLChat& chat, BOOL from_instant_message, BOOL local_agent) +void LLFloaterChat::addChat(const LLChat& chat, BOOL local_agent) { triggerAlerts(chat.mText); // Add the sender to the list of people with which we've recently interacted. - if(chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID.notNull()) - LLRecentPeople::instance().add(chat.mFromID); + // this is not the best place to add _all_ messages to recent list + // comment this for now, may remove later on code cleanup + //if(chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID.notNull()) + // LLRecentPeople::instance().add(chat.mFromID); - bool add_chat = true; - bool log_chat = true; - if(from_instant_message) - { - if (!gSavedSettings.getBOOL("IMInChat")) - add_chat = false; - //log_chat = false; -} - - if (add_chat) - { - addChatHistory(chat, log_chat); - } + addChatHistory(chat, true); } // Moved from lltextparser.cpp to break llui/llaudio library dependency. diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index 84fc199bfa..4437a0a5c2 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -61,7 +61,7 @@ public: // *TODO:Skinning - move these to LLChat (or LLViewerChat?) // Add chat to console and history list. // Color based on source, type, distance. - static void addChat(const LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE); + static void addChat(const LLChat& chat, BOOL local_agent = FALSE); // Add chat to history alone. static void addChatHistory(const LLChat& chat, bool log_to_file = true); diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index 9108cfb72b..84b423399e 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -38,7 +38,6 @@ #include "llfloaterreg.h" #include "llfloaterchatterbox.h" #include "lluictrlfactory.h" -#include "llfloaterchat.h" #include "llfloaterfriends.h" #include "llfloatergroups.h" #include "llviewercontrol.h" @@ -134,22 +133,6 @@ BOOL LLFloaterChatterBox::postBuild() addFloater(LLFloaterMyFriends::getInstance(), TRUE); } - if (gSavedSettings.getBOOL("ChatHistoryTornOff")) - { - LLFloaterChat* floater_chat = LLFloaterChat::getInstance(); - if(floater_chat) - { - // add then remove to set up relationship for re-attach - addFloater(floater_chat, FALSE); - removeFloater(floater_chat); - // reparent to floater view - gFloaterView->addChild(floater_chat); - } - } - else - { - addFloater(LLFloaterChat::getInstance(), FALSE); - } mTabContainer->lockTabs(); return TRUE; } @@ -230,8 +213,6 @@ void LLFloaterChatterBox::onOpen(const LLSD& key) //*TODO:Skinning show the session id associated with key if (key.asString() == "local") { - LLFloaterChat* chat = LLFloaterReg::findTypedInstance("chat"); - chat->openFloater(); } else if (key.isDefined()) { @@ -245,12 +226,6 @@ void LLFloaterChatterBox::onOpen(const LLSD& key) void LLFloaterChatterBox::onVisibilityChange ( const LLSD& new_visibility ) { - // HACK: potentially need to toggle console - LLFloaterChat* instance = LLFloaterChat::getInstance(); - if(instance) - { - instance->updateConsoleVisibility(); - } } void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) @@ -349,8 +324,7 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() } if (LLVoiceChannelProximal::getInstance() == LLVoiceChannel::getCurrentVoiceChannel()) { - // show near me tab if in proximal channel - return LLFloaterChat::getInstance(); + return NULL; } else { diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 5072bc8c82..de65c6f876 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -110,7 +110,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key) mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this)); - mCommitCallbackRegistrar.add("Gesture.Action.CopyPast", boost::bind(&LLFloaterGesture::onCopyPastAction, this, _2)); + mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2)); mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this)); mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2)); @@ -245,6 +245,7 @@ void LLFloaterGesture::refreshAll() void LLFloaterGesture::buildGestureList() { + S32 scroll_pos = mGestureList->getScrollPos(); std::vector selected_items; getSelectedIds(selected_items); LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL; @@ -274,13 +275,14 @@ void LLFloaterGesture::buildGestureList() } } } + // attempt to preserve scroll position through re-builds - // since we do re-build any time anything dirties + // since we do re-build whenever something gets dirty for(std::vector::iterator it = selected_items.begin(); it != selected_items.end(); it++) { mGestureList->selectByID(*it); } - mGestureList->scrollToShowSelected(); + mGestureList->setScrollPos(scroll_pos); } void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list ) @@ -415,7 +417,7 @@ void LLFloaterGesture::onClickPlay() LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <refresh(); mPanelMedia->refresh(); mPanelAccess->refresh(); + mPanelCovenant->refresh(); } @@ -2795,12 +2796,6 @@ LLPanelLandCovenant::~LLPanelLandCovenant() { } -BOOL LLPanelLandCovenant::postBuild() -{ - refresh(); - return TRUE; -} - // virtual void LLPanelLandCovenant::refresh() { diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index d7d02ba1a3..a4785e8f5b 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -391,7 +391,6 @@ class LLPanelLandCovenant public: LLPanelLandCovenant(LLSafeHandle& parcelp); virtual ~LLPanelLandCovenant(); - virtual BOOL postBuild(); void refresh(); static void updateCovenantText(const std::string& string); static void updateEstateName(const std::string& name); diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index 5cfd56193e..976af121ae 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -192,6 +192,9 @@ void LLFloaterMediaSettings::initValues( const LLSD& media_settings, bool editab sInstance->mPanelMediaSettingsGeneral->getValues( sInstance->mInitialValues ); sInstance->mPanelMediaSettingsSecurity->getValues( sInstance->mInitialValues ); sInstance->mPanelMediaSettingsPermissions->getValues( sInstance->mInitialValues ); + + sInstance->mApplyBtn->setEnabled(editable); + sInstance->mOKBtn->setEnabled(editable); } //////////////////////////////////////////////////////////////////////////////// @@ -266,8 +269,11 @@ const std::string LLFloaterMediaSettings::getHomeUrl() // virtual void LLFloaterMediaSettings::draw() { - // Set the enabled state of the "Apply" button if values changed - childSetEnabled( "Apply", haveValuesChanged() ); + if (NULL != mApplyBtn) + { + // Set the enabled state of the "Apply" button if values changed + mApplyBtn->setEnabled( haveValuesChanged() ); + } LLFloater::draw(); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 11dd48056c..fc036cb354 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -51,7 +51,7 @@ #include "lldirpicker.h" #include "llfeaturemanager.h" #include "llfocusmgr.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llfloaterreg.h" #include "llfloaterabout.h" #include "llfloaterhardwaresettings.h" @@ -185,8 +185,8 @@ void handleNameTagOptionChanged(const LLSD& newvalue); viewer_media_t get_web_media(); bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response); -bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); -bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); +//bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); +//bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); @@ -236,7 +236,7 @@ void handleNameTagOptionChanged(const LLSD& newvalue) } } -bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater) +/*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option && floater ) @@ -244,7 +244,7 @@ bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFlo if ( floater ) { floater->setAllIgnored(); - LLFirstUse::disableFirstUse(); + // LLFirstUse::disableFirstUse(); floater->buildPopupLists(); } } @@ -259,13 +259,13 @@ bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFl if ( floater ) { floater->resetAllIgnored(); - LLFirstUse::resetFirstUse(); + //LLFirstUse::resetFirstUse(); floater->buildPopupLists(); } } return false; } - +*/ void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator) { @@ -313,8 +313,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this)); mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this)); mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this)); - mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this)); - mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this)); +// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this)); +// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this)); mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this)); mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); @@ -325,6 +325,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); mCommitCallbackRegistrar.add("Pref.AutoDetectAspect", boost::bind(&LLFloaterPreference::onCommitAutoDetectAspect, this)); + mCommitCallbackRegistrar.add("Pref.ParcelMediaAutoPlayEnable", boost::bind(&LLFloaterPreference::onCommitParcelMediaAutoPlayEnable, this)); + mCommitCallbackRegistrar.add("Pref.MediaEnabled", boost::bind(&LLFloaterPreference::onCommitMediaEnabled, this)); mCommitCallbackRegistrar.add("Pref.onSelectAspectRatio", boost::bind(&LLFloaterPreference::onKeystrokeAspectRatio, this)); mCommitCallbackRegistrar.add("Pref.QualityPerformance", boost::bind(&LLFloaterPreference::onChangeQuality, this, _2)); mCommitCallbackRegistrar.add("Pref.applyUIColor", boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2)); @@ -601,8 +603,8 @@ void LLFloaterPreference::onBtnOK() apply(); closeFloater(false); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); LLUIColorTable::instance().saveUserSettings(); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults gCrashSettings.saveToFile(crash_settings_filename, FALSE); @@ -986,6 +988,27 @@ void LLFloaterPreference::onCommitAutoDetectAspect() } } +void LLFloaterPreference::onCommitParcelMediaAutoPlayEnable() +{ + BOOL autoplay = getChild("autoplay_enabled")->get(); + + gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, autoplay); + + lldebugs << "autoplay now = " << int(autoplay) << llendl; +} + +void LLFloaterPreference::onCommitMediaEnabled() +{ + LLCheckBoxCtrl *media_enabled_ctrl = getChild("media_enabled"); + bool enabled = media_enabled_ctrl->get(); + gSavedSettings.setBOOL("AudioStreamingVideo", enabled); + gSavedSettings.setBOOL("AudioStreamingMusic", enabled); + gSavedSettings.setBOOL("AudioStreamingMedia", enabled); + media_enabled_ctrl->setTentative(false); + // Update enabled state of the "autoplay" checkbox + getChild("autoplay_enabled")->setEnabled(enabled); +} + void LLFloaterPreference::refresh() { LLPanel::refresh(); @@ -1050,7 +1073,7 @@ void LLFloaterPreference::onClickSetMiddleMouse() // update the control right away since we no longer wait for apply getChild("modifier_combo")->onCommit(); } - +/* void LLFloaterPreference::onClickSkipDialogs() { LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, this)); @@ -1060,6 +1083,7 @@ void LLFloaterPreference::onClickResetDialogs() { LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, this)); } + */ void LLFloaterPreference::onClickEnablePopup() { @@ -1399,6 +1423,20 @@ BOOL LLPanelPreference::postBuild() refresh(); } + //////////////////////PanelPrivacy /////////////////// + if(hasChild("media_enabled")) + { + bool video_enabled = gSavedSettings.getBOOL("AudioStreamingVideo"); + bool music_enabled = gSavedSettings.getBOOL("AudioStreamingMusic"); + bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); + bool enabled = video_enabled || music_enabled || media_enabled; + + LLCheckBoxCtrl *media_enabled_ctrl = getChild("media_enabled"); + media_enabled_ctrl->set(enabled); + media_enabled_ctrl->setTentative(!(video_enabled == music_enabled == media_enabled)); + getChild("autoplay_enabled")->setEnabled(enabled); + } + apply(); return true; } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 74a53d673c..6f382620ee 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -110,8 +110,8 @@ public: void onClickSetKey(); void setKey(KEY key); void onClickSetMiddleMouse(); - void onClickSkipDialogs(); - void onClickResetDialogs(); +// void onClickSkipDialogs(); +// void onClickResetDialogs(); void onClickEnablePopup(); void onClickDisablePopup(); void resetAllIgnored(); @@ -132,6 +132,8 @@ public: // void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); void onCommitAutoDetectAspect(); + void onCommitParcelMediaAutoPlayEnable(); + void onCommitMediaEnabled(); void applyResolution(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index c4b87c1b2d..03ff2cc370 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -406,6 +406,11 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region) { + if (!region) + { + return; + } + // call refresh from region on all panels std::for_each( mInfoPanels.begin(), @@ -1598,7 +1603,7 @@ std::string all_estates_text() } else if (region && region->getOwner() == gAgent.getID()) { - return LLTrans::getString("AllEstatesYouOwn"); + return LLTrans::getString("RegionInfoAllEstatesYouOwn"); } else if (region && region->isEstateManager()) { diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 3042fbc6ec..0964ad7f91 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -64,6 +64,8 @@ // summary which only shows available & correct information #define USE_SIMPLE_SUMMARY +const S32 SIZE_OF_ONE_KB = 1024; + LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed) : LLFloater(seed) { @@ -130,7 +132,6 @@ void LLFloaterScriptLimits::refresh() } } - ///---------------------------------------------------------------------------- // Base class for panels ///---------------------------------------------------------------------------- @@ -331,6 +332,57 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<("scripts_list"); + std::vector::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + + // fill in the url's tab if needed, all urls must have memory so we can do it all here + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild("script_limits_region_urls_panel"); + + LLScrollListCtrl *list = panel->getChild("scripts_list"); + std::vector::iterator id_itor; + for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor) + { + LLSD element = *id_itor; + if(element["owner_id"].asUUID() == id) + { + LLScrollListItem* item = list->getItem(element["id"].asUUID()); + + if(item) + { + item->getColumn(2)->setValue(LLSD(name)); + element["columns"][2]["value"] = name; + } + } + } + } +} + void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) { LLScrollListCtrl *list = getChild("scripts_list"); @@ -345,22 +397,40 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; + std::vector names_requested; + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); - + LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); for(S32 j = 0; j < number_objects; j++) { - S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024; + S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; total_size += size; std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + + BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf); + if(!name_is_cached) + { + if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end()) + { + names_requested.push_back(owner_id); + gCacheName->get(owner_id, TRUE, + boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache, + this, _1, _2, _3)); + } + } LLSD element; element["id"] = task_id; + element["owner_id"] = owner_id; element["columns"][0]["column"] = "size"; element["columns"][0]["value"] = llformat("%d", size); element["columns"][0]["font"] = "SANSSERIF"; @@ -368,18 +438,18 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; - list->addElement(element); - mObjectListIDs.push_back(task_id); + list->addElement(element, ADD_SORTED); + mObjectListItems.push_back(element); total_objects++; } } - + mParcelMemoryUsed =total_size; mGotParcelMemoryUsed = TRUE; populateParcelMemoryText(); @@ -556,7 +626,7 @@ void LLPanelScriptLimitsRegionMemory::clearList() childSetValue("memory_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -728,7 +798,7 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) S32 total_objects = 0; S32 total_size = 0; - + for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); @@ -744,6 +814,10 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID(); + + std::string owner_buf; + gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field LLSD element; @@ -755,14 +829,14 @@ void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) element["columns"][1]["value"] = name_buf; element["columns"][1]["font"] = "SANSSERIF"; element["columns"][2]["column"] = "owner"; - element["columns"][2]["value"] = ""; + element["columns"][2]["value"] = owner_buf; element["columns"][2]["font"] = "SANSSERIF"; element["columns"][3]["column"] = "location"; element["columns"][3]["value"] = parcel_name; element["columns"][3]["font"] = "SANSSERIF"; list->addElement(element); - mObjectListIDs.push_back(task_id); + mObjectListItems.push_back(element); total_objects++; } } @@ -868,7 +942,7 @@ void LLPanelScriptLimitsRegionURLs::clearList() childSetValue("urls_used", LLSD(msg_empty_string)); childSetValue("parcels_listed", LLSD(msg_empty_string)); - mObjectListIDs.clear(); + mObjectListItems.clear(); } // static @@ -982,7 +1056,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) S32 size = 0; if(content["attachments"][i]["objects"][j]["resources"].has("memory")) { - size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger(); + size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB; } S32 urls = 0; if(content["attachments"][i]["objects"][j]["resources"].has("urls")) @@ -1059,3 +1133,4 @@ void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata) return; } } + diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index 88239136e3..7e2b536eb6 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -54,12 +54,12 @@ public: // from LLPanel virtual void refresh(); - + private: - + LLFloaterScriptLimits(const LLSD& seed); ~LLFloaterScriptLimits(); - + protected: LLTabContainer* mTab; @@ -167,13 +167,17 @@ public: private: + void onNameCache( const LLUUID& id, + const std::string& first_name, + const std::string& last_name); + LLUUID mParcelId; BOOL mGotParcelMemoryUsed; BOOL mGotParcelMemoryMax; S32 mParcelMemoryMax; S32 mParcelMemoryUsed; - std::vector mObjectListIDs; + std::vector mObjectListItems; protected: @@ -218,7 +222,7 @@ private: S32 mParcelURLsMax; S32 mParcelURLsUsed; - std::vector mObjectListIDs; + std::vector mObjectListItems; protected: diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index c6d9fee630..a7401fdb6f 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -32,6 +32,9 @@ */ #include "llviewerprecompiledheaders.h" + +#include "llcommandhandler.h" +#include "llfloaterreg.h" #include "llfloatersearch.h" #include "llmediactrl.h" #include "lllogininstance.h" @@ -41,6 +44,42 @@ #include "llviewercontrol.h" #include "llweb.h" +// support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps +class LLSearchHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + { + const size_t parts = tokens.size(); + + // get the (optional) category for the search + std::string category; + if (parts > 0) + { + category = tokens[0].asString(); + } + + // get the (optional) search string + std::string search_text; + if (parts > 1) + { + search_text = tokens[1].asString(); + } + + // create the LLSD arguments for the search floater + LLSD args; + args["category"] = category; + args["id"] = LLURI::unescape(search_text); + + // open the search floater and perform the requested search + LLFloaterReg::showInstance("search", args); + return true; + } +}; +LLSearchHandler gSearchHandler; + LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), LLViewerMediaObserver(), diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 8979575ef7..a6ffa5ec09 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -34,7 +34,7 @@ #include "llfloatersettingsdebug.h" #include "llfloater.h" #include "lluictrlfactory.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llcombobox.h" #include "llspinctrl.h" #include "llcolorswatch.h" diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index f53b62e490..afb58c9407 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -2078,8 +2078,10 @@ void LLFloaterSnapshot::draw() { if(previewp->getThumbnailImage()) { + LLRect thumbnail_rect = getChild("thumbnail_placeholder")->getRect(); + S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ; - S32 offset_y = getRect().getHeight() - 205 + (90 - previewp->getThumbnailHeight()) / 2 ; + S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ; glMatrixMode(GL_MODELVIEW); gl_draw_scaled_image(offset_x, offset_y, diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index babef5b63d..241497aeaf 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1134,7 +1134,8 @@ void LLFloaterTools::getMediaState() } // XXX DISABLE this for now, because when the fetch finally // does come in, the state of this floater doesn't properly - // update. This needs more thought. + // update. Re-selecting fixes the problem, but there is + // contention as to whether this is a sufficient solution. // if (object->isMediaDataBeingFetched()) // { // LL_INFOS("LLFloaterTools: media") @@ -1221,10 +1222,10 @@ void LLFloaterTools::getMediaState() mNeedMediaTitle = false; } - childSetEnabled("media_tex", bool_has_media & editable); - childSetEnabled( "edit_media", bool_has_media & editable ); - childSetEnabled( "delete_media", bool_has_media & editable ); - childSetEnabled( "add_media", ( ! bool_has_media ) & editable ); + childSetEnabled("media_tex", bool_has_media && editable); + childSetEnabled( "edit_media", bool_has_media && LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo && editable ); + childSetEnabled( "delete_media", bool_has_media && editable ); + childSetEnabled( "add_media", ( ! bool_has_media ) && editable ); // TODO: display a list of all media on the face - use 'identical' flag } else // not all face has media but at least one does. @@ -1252,7 +1253,7 @@ void LLFloaterTools::getMediaState() } childSetEnabled("media_tex", TRUE); - childSetEnabled( "edit_media", TRUE); + childSetEnabled( "edit_media", LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo); childSetEnabled( "delete_media", TRUE); childSetEnabled( "add_media", FALSE ); } @@ -1269,18 +1270,15 @@ void LLFloaterTools::getMediaState() // called when a user wants to add media to a prim or prim face void LLFloaterTools::onClickBtnAddMedia() { - // check for the edit tool and now many faces are selected - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if((tool != LLToolFace::getInstance()) || LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) + // check if multiple faces are selected + if(LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) { - LLNotificationsUtil::add("MultipleFacesSelected",LLSD(), LLSD(), multipleFacesSelectedConfirm); - + LLNotificationsUtil::add("MultipleFacesSelected", LLSD(), LLSD(), multipleFacesSelectedConfirm); } else { onClickBtnEditMedia(); } - } // static @@ -1423,7 +1421,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getControls(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_controls(default_media_data); identical = selected_objects->getSelectedTEValue( &func_controls, value_u8 ); @@ -1446,7 +1444,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getFirstClickInteract(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_first_click(default_media_data); identical = selected_objects->getSelectedTEValue( &func_first_click, value_bool ); @@ -1469,7 +1467,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getHomeURL(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_home_url(default_media_data); identical = selected_objects->getSelectedTEValue( &func_home_url, value_str ); @@ -1492,7 +1490,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getCurrentURL(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_current_url(default_media_data); identical = selected_objects->getSelectedTEValue( &func_current_url, value_str ); @@ -1516,7 +1514,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getAutoZoom(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_auto_zoom(default_media_data); identical = selected_objects->getSelectedTEValue( &func_auto_zoom, value_bool ); @@ -1539,7 +1537,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getAutoPlay(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_auto_play(default_media_data); identical = selected_objects->getSelectedTEValue( &func_auto_play, value_bool ); @@ -1563,7 +1561,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getAutoScale();; }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_auto_scale(default_media_data); identical = selected_objects->getSelectedTEValue( &func_auto_scale, value_bool ); @@ -1586,7 +1584,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getAutoLoop(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_auto_loop(default_media_data); identical = selected_objects->getSelectedTEValue( &func_auto_loop, value_bool ); @@ -1609,7 +1607,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getWidthPixels(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_width_pixels(default_media_data); identical = selected_objects->getSelectedTEValue( &func_width_pixels, value_int ); @@ -1632,7 +1630,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getHeightPixels(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_height_pixels(default_media_data); identical = selected_objects->getSelectedTEValue( &func_height_pixels, value_int ); @@ -1655,7 +1653,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getAltImageEnable(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_enable_alt_image(default_media_data); identical = selected_objects->getSelectedTEValue( &func_enable_alt_image, value_bool ); @@ -1678,7 +1676,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_owner_interact(default_media_data); identical = selected_objects->getSelectedTEValue( &func_perms_owner_interact, value_bool ); @@ -1701,7 +1699,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_owner_control(default_media_data); identical = selected_objects ->getSelectedTEValue( &func_perms_owner_control, value_bool ); @@ -1724,7 +1722,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_group_interact(default_media_data); identical = selected_objects->getSelectedTEValue( &func_perms_group_interact, value_bool ); @@ -1747,7 +1745,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_group_control(default_media_data); identical = selected_objects->getSelectedTEValue( &func_perms_group_control, value_bool ); @@ -1770,7 +1768,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_anyone_interact(default_media_data); identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_perms_anyone_interact, value_bool ); @@ -1793,7 +1791,7 @@ void LLFloaterTools::updateMediaSettings() return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE ); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_perms_anyone_control(default_media_data); identical = selected_objects->getSelectedTEValue( &func_perms_anyone_control, value_bool ); @@ -1816,7 +1814,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getWhiteListEnable(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_whitelist_enable(default_media_data); identical = selected_objects->getSelectedTEValue( &func_whitelist_enable, value_bool ); @@ -1839,7 +1837,7 @@ void LLFloaterTools::updateMediaSettings() return mMediaEntry.getWhiteList(); }; - const LLMediaEntry & mMediaEntry; + const LLMediaEntry &mMediaEntry; } func_whitelist_urls(default_media_data); identical = selected_objects->getSelectedTEValue( &func_whitelist_urls, value_vector_str ); diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp index 43024a4bd0..638c9f1b8c 100644 --- a/indra/newview/llfloatervoicedevicesettings.cpp +++ b/indra/newview/llfloatervoicedevicesettings.cpp @@ -110,32 +110,33 @@ void LLPanelVoiceDeviceSettings::draw() LLPanel::draw(); - F32 voice_power = gVoiceClient->tuningGetEnergy(); - S32 discrete_power = 0; - - if (!is_in_tuning_mode) - { - discrete_power = 0; - } - else - { - discrete_power = llmin(4, llfloor((voice_power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 4.f)); - } - if (is_in_tuning_mode) { - for(S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++) + const S32 num_bars = 5; + F32 voice_power = gVoiceClient->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL; + S32 discrete_power = llmin(num_bars, llfloor(voice_power * (F32)num_bars + 0.1f)); + + for(S32 power_bar_idx = 0; power_bar_idx < num_bars; power_bar_idx++) { std::string view_name = llformat("%s%d", "bar", power_bar_idx); LLView* bar_view = getChild(view_name); if (bar_view) { + gl_rect_2d(bar_view->getRect(), LLColor4::grey, TRUE); + + LLColor4 color; if (power_bar_idx < discrete_power) { - LLColor4 color = (power_bar_idx >= 3) ? LLUIColorTable::instance().getColor("OverdrivenColor") : LLUIColorTable::instance().getColor("SpeakingColor"); - gl_rect_2d(bar_view->getRect(), color, TRUE); + color = (power_bar_idx >= 3) ? LLUIColorTable::instance().getColor("OverdrivenColor") : LLUIColorTable::instance().getColor("SpeakingColor"); + } + else + { + color = LLUIColorTable::instance().getColor("PanelFocusBackgroundColor"); } - gl_rect_2d(bar_view->getRect(), LLColor4::grey, FALSE); + + LLRect color_rect = bar_view->getRect(); + color_rect.stretch(-1); + gl_rect_2d(color_rect, color, TRUE); } } } @@ -276,7 +277,10 @@ void LLPanelVoiceDeviceSettings::initialize() void LLPanelVoiceDeviceSettings::cleanup() { - gVoiceClient->tuningStop(); + if (gVoiceClient) + { + gVoiceClient->tuningStop(); + } LLVoiceChannel::resume(); } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 98f9171237..f4d4ea3553 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -47,7 +47,7 @@ #include "llviewercontrol.h" #include "llcommandhandler.h" #include "lldraghandle.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llfloaterreg.h" // getTypedInstance() #include "llfocusmgr.h" #include "llinventorymodel.h" @@ -100,8 +100,6 @@ enum EPanDirection // Values in pixels per region static const F32 ZOOM_MAX = 128.f; -static const F32 SIM_COORD_DEFAULT = 128.f; - //--------------------------------------------------------------------------- // Globals //--------------------------------------------------------------------------- @@ -118,9 +116,12 @@ public: { if (params.size() == 0) { - return false; + // support the secondlife:///app/worldmap SLapp + LLFloaterReg::showInstance("world_map", "center"); + return true; } + // support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp const std::string region_name = params[0].asString(); S32 x = (params.size() > 1) ? params[1].asInteger() : 128; S32 y = (params.size() > 2) ? params[2].asInteger() : 128; @@ -189,7 +190,8 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) mInventory(NULL), mInventoryObserver(NULL), mFriendObserver(NULL), - mCompletingRegionName(""), + mCompletingRegionName(), + mCompletingRegionPos(), mWaitingForTracker(FALSE), mIsClosing(FALSE), mSetToUserPosition(TRUE), @@ -205,7 +207,6 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this)); mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this)); mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this)); - mCommitCallbackRegistrar.add("WMap.CommitLocation", boost::bind(&LLFloaterWorldMap::onCommitLocation, this)); mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this)); mCommitCallbackRegistrar.add("WMap.Teleport", boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this)); mCommitCallbackRegistrar.add("WMap.ShowTarget", boost::bind(&LLFloaterWorldMap::onShowTargetBtn, this)); @@ -316,7 +317,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) adjustZoomSliderBounds(); // Could be first show - LLFirstUse::useMap(); + //LLFirstUse::useMap(); // Start speculative download of landmarks const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); @@ -664,10 +665,6 @@ void LLFloaterWorldMap::updateLocation() S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); S32 agent_z = llround( (F32)agentPos.mdV[VZ] ); - childSetValue("spin x", LLSD(agent_x) ); - childSetValue("spin y", LLSD(agent_y) ); - childSetValue("spin z", LLSD(agent_z) ); - // Set the current SLURL mSLURL = LLSLURL::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z); } @@ -699,9 +696,6 @@ void LLFloaterWorldMap::updateLocation() F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); - childSetValue("spin x", LLSD(region_x) ); - childSetValue("spin y", LLSD(region_y) ); - childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) ); // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL if ( gotSimName ) @@ -733,9 +727,11 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 { // fill in UI based on URL gFloaterWorldMap->childSetValue("location", region_name); - childSetValue("spin x", LLSD((F32)x_coord)); - childSetValue("spin y", LLSD((F32)y_coord)); - childSetValue("spin z", LLSD((F32)z_coord)); + + // Save local coords to highlight position after region global + // position is returned. + gFloaterWorldMap->mCompletingRegionPos.set( + (F32)x_coord, (F32)y_coord, (F32)z_coord); // pass sim name to combo box gFloaterWorldMap->mCompletingRegionName = region_name; @@ -899,18 +895,6 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { list->operateOnAll(LLCtrlListInterface::OP_DELETE); } - if (!childHasKeyboardFocus("spin x")) - { - childSetValue("spin x", SIM_COORD_DEFAULT); - } - if (!childHasKeyboardFocus("spin y")) - { - childSetValue("spin y", SIM_COORD_DEFAULT); - } - if (!childHasKeyboardFocus("spin z")) - { - childSetValue("spin z", 0); - } LLWorldMap::getInstance()->cancelTracking(); mCompletingRegionName = ""; } @@ -1466,21 +1450,6 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) } } -void LLFloaterWorldMap::onCommitLocation() -{ - LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); - if ( LLTracker::TRACKING_LOCATION == tracking_status) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - F64 local_x = childGetValue("spin x"); - F64 local_y = childGetValue("spin y"); - F64 local_z = childGetValue("spin z"); - pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x; - pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y; - pos_global.mdV[VZ] = local_z; - trackLocation(pos_global); - } -} void LLFloaterWorldMap::onCommitSearchResult() { @@ -1503,12 +1472,19 @@ void LLFloaterWorldMap::onCommitSearchResult() if (info->isName(sim_name)) { LLVector3d pos_global = info->getGlobalOrigin(); - F64 local_x = childGetValue("spin x"); - F64 local_y = childGetValue("spin y"); - F64 local_z = childGetValue("spin z"); - pos_global.mdV[VX] += local_x; - pos_global.mdV[VY] += local_y; - pos_global.mdV[VZ] = local_z; + + const F64 SIM_COORD_DEFAULT = 128.0; + LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f); + + // Did this value come from a trackURL() request? + if (!mCompletingRegionPos.isExactlyZero()) + { + pos_local = mCompletingRegionPos; + mCompletingRegionPos.clear(); + } + pos_global.mdV[VX] += (F64)pos_local.mV[VX]; + pos_global.mdV[VY] += (F64)pos_local.mV[VY]; + pos_global.mdV[VZ] = (F64)pos_local.mV[VZ]; childSetValue("location", sim_name); trackLocation(pos_global); diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 7feebb583d..00f5e788fb 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -148,7 +148,6 @@ protected: void updateSearchEnabled(); void onLocationFocusChanged( LLFocusableElement* ctrl ); void onLocationCommit(); - void onCommitLocation(); void onCommitSearchResult(); void cacheLandmarkPosition(); @@ -170,6 +169,10 @@ private: LLFriendObserver* mFriendObserver; std::string mCompletingRegionName; + // Local position from trackURL() request, used to select final + // position once region lookup complete. + LLVector3 mCompletingRegionPos; + std::string mLastRegionName; BOOL mWaitingForTracker; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 112b23d2df..a63fb73032 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -78,7 +78,7 @@ ///---------------------------------------------------------------------------- const S32 RENAME_WIDTH_PAD = 4; -const S32 RENAME_HEIGHT_PAD = 2; +const S32 RENAME_HEIGHT_PAD = 1; const S32 AUTO_OPEN_STACK_DEPTH = 16; const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + LLFolderViewItem::ICON_PAD @@ -206,7 +206,9 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; - static LLUICachedControl indentation("FolderIndentation", 0); + const LLFolderViewItem::Params& item_params = + LLUICtrlFactory::getDefaultParams(); + S32 indentation = item_params.folder_indentation(); mIndentation = -indentation; // children start at indentation 0 gIdleCallbacks.addFunction(idle, this); @@ -395,7 +397,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen getRoot()->getFilter()->getShowFolderState(); S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0; + S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0; S32 target_height = running_height; S32 parent_item_height = getRect().getHeight(); @@ -569,6 +571,8 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) { + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + if( selection == this ) { return FALSE; @@ -596,8 +600,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, llassert(mSelectedItems.size() <= 1); - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - return rv; } @@ -820,10 +822,11 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -BOOL LLFolderView::getSelectionList(std::set &selection) +BOOL LLFolderView::getSelectionList(std::set &selection) const { - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) { selection.insert((*item_it)->getListener()->getUUID()); } @@ -866,8 +869,8 @@ void LLFolderView::draw() { std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); - sSmallFont->renderUTF8(current_filter_string, 0, 2, - getRect().getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), + LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, + getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } @@ -1882,8 +1885,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); - // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder - S32 max_height_to_show = mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); // get portion of item that we want to see... LLRect item_local_rect = LLRect(item->getIndentation(), @@ -2218,10 +2221,9 @@ void LLFolderView::updateRenamerPosition() { if(mRenameItem) { - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + mRenameItem->getIndentation(); - S32 y = llfloor(mRenameItem->getRect().getHeight() - font->getLineHeight()-2); + // See also LLFolderViewItem::draw() + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; mRenameItem->localPointToScreen( x, y, &x, &y ); screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); @@ -2233,7 +2235,7 @@ void LLFolderView::updateRenamerPosition() } S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = llfloor(font->getLineHeight() + RENAME_HEIGHT_PAD); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; mRenamer->reshape( width, height, TRUE ); } } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 2598af4df4..89e1865e35 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -162,7 +162,7 @@ public: virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray& items); - virtual BOOL getSelectionList(std::set &selection); + virtual BOOL getSelectionList(std::set &selection) const; // make sure if ancestor is selected, descendents are not void sanitizeSelection(); diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 473d0be912..d6c4459e6f 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -62,6 +62,7 @@ public: virtual PermissionMask getPermissionMask() const = 0; virtual LLFolderType::EType getPreferredType() const = 0; virtual LLPointer getIcon() const = 0; + virtual LLPointer getOpenIcon() const { return getIcon(); } virtual LLFontGL::StyleFlags getLabelStyle() const = 0; virtual std::string getLabelSuffix() const = 0; virtual void openItem( void ) = 0; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 9d54aafd67..4b48626b22 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -51,11 +51,10 @@ /// Class LLFolderViewItem ///---------------------------------------------------------------------------- +static LLDefaultChildRegistry::Register r("folder_view_item"); + // statics std::map LLFolderViewItem::sFonts; // map of styles to fonts -const LLFontGL* LLFolderViewItem::sSmallFont = NULL; -LLUIImagePtr LLFolderViewItem::sArrowImage; -LLUIImagePtr LLFolderViewItem::sBoxImage; // only integers can be initialized in header const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; @@ -84,33 +83,34 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) //static void LLFolderViewItem::initClass() { - sSmallFont = LLFontGL::getFontMonospace(); - sArrowImage = LLUI::getUIImage("folder_arrow.tga"); - sBoxImage = LLUI::getUIImage("rounded_square.tga"); } //static void LLFolderViewItem::cleanupClass() { sFonts.clear(); - sArrowImage = NULL; - sBoxImage = NULL; } // NOTE: Optimize this, we call it a *lot* when opening a large inventory LLFolderViewItem::Params::Params() -: icon("icon"), - folder_arrow_image("folder_arrow_image", LLUI::getUIImage("folder_arrow.tga")), - selection_image("selection_image", LLUI::getUIImage("rounded_square.tga")) +: icon(), + icon_open(), + root(), + listener(), + folder_arrow_image("folder_arrow_image"), + folder_indentation("folder_indentation"), + selection_image("selection_image"), + item_height("item_height"), + item_top_pad("item_top_pad"), + creation_date() { mouse_opaque(true); follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); - // JAMESDEBUG tab_stop(false); } // Default constructor -LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) +LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), @@ -121,6 +121,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) mLabelStyle( LLFontGL::NORMAL ), mHasVisibleChildren(FALSE), mIndentation(0), + mItemHeight(p.item_height), mNumDescendantsSelected(0), mPassedFilter(FALSE), mLastFilterGeneration(-1), @@ -134,8 +135,6 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) mIcon(p.icon), mIconOpen(p.icon_open), mListener(p.listener), - mArrowImage(p.folder_arrow_image), - mBoxImage(p.selection_image), mHidden(false), mShowLoadStatus(false) { @@ -392,10 +391,11 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* roo // makes sure that this view and it's children are the right size. S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) { - static LLUICachedControl indentation("FolderIndentation", 0); + const Params& p = LLUICtrlFactory::getDefaultParams(); + S32 indentation = p.folder_indentation(); + // Only indent deeper items in hierarchy mIndentation = (getParentFolder() - && getParentFolder()->getParentFolder() - && getParentFolder()->getParentFolder()->getParentFolder()) + && getParentFolder()->getParentFolder() ) ? mParentFolder->getIndentation() + indentation : 0; if (mLabelWidthDirty) @@ -421,9 +421,10 @@ S32 LLFolderViewItem::getItemHeight() { if (mHidden) return 0; - S32 icon_height = mIcon->getHeight(); - S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); - return llmax( icon_height, label_height ) + ICON_PAD; + //S32 icon_height = mIcon->getHeight(); + //S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); + //return llmax( icon_height, label_height ) + ICON_PAD; + return mItemHeight; } void LLFolderViewItem::filter( LLInventoryFilter& filter) @@ -829,11 +830,16 @@ void LLFolderViewItem::draw() static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); + static LLUIColor sFocusOutlineColor = + LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemSuffixColor", DEFAULT_WHITE); static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + const Params& default_params = LLUICtrlFactory::getDefaultParams(); + const S32 TOP_PAD = default_params.item_top_pad; + bool possibly_has_children = false; bool up_to_date = mListener && mListener->isUpToDate(); if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... @@ -843,13 +849,13 @@ void LLFolderViewItem::draw() } if(/*mControlLabel[0] != '\0' && */possibly_has_children) { - if (sArrowImage) - { - gl_draw_scaled_rotated_image(mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, sArrowImage->getImage(), sFgColor); - } + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); } + // See also LLFolderView::updateRenamerPosition() F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); LLFontGL* font = getLabelFontForStyle(mLabelStyle); @@ -857,6 +863,10 @@ void LLFolderViewItem::draw() // If we have keyboard focus, draw selection filled BOOL show_context = getRoot()->getShowSelectionContext(); BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); + const S32 FOCUS_LEFT = 1; + S32 focus_top = getRect().getHeight(); + S32 focus_bottom = getRect().getHeight() - mItemHeight; + bool folder_open = (getRect().getHeight() > mItemHeight + 4); // always render "current" item, only render other selected items if // mShowSingleSelection is FALSE @@ -864,7 +874,6 @@ void LLFolderViewItem::draw() { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLColor4 bg_color = sHighlightBgColor; - //const S32 TRAILING_PAD = 5; // It just looks better with this. if (!mIsCurSelection) { // do time-based fade of extra objects @@ -882,35 +891,35 @@ void LLFolderViewItem::draw() } gl_rect_2d( - 0, - getRect().getHeight(), + FOCUS_LEFT, + focus_top, getRect().getWidth() - 2, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), + focus_bottom, bg_color, filled); if (mIsCurSelection) { gl_rect_2d( - 0, - getRect().getHeight(), + FOCUS_LEFT, + focus_top, getRect().getWidth() - 2, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), - sHighlightFgColor, FALSE); + focus_bottom, + sFocusOutlineColor, FALSE); } - if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 4) + if (folder_open) { gl_rect_2d( - 0, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4, + FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect getRect().getWidth() - 2, - 2, - sHighlightFgColor, FALSE); + 0, + sFocusOutlineColor, FALSE); if (show_context) { gl_rect_2d( - 0, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4, + FOCUS_LEFT, + focus_bottom + 1, getRect().getWidth() - 2, - 2, + 0, sHighlightBgColor, TRUE); } } @@ -919,32 +928,32 @@ void LLFolderViewItem::draw() { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gl_rect_2d( - 0, - getRect().getHeight(), + FOCUS_LEFT, + focus_top, getRect().getWidth() - 2, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD), + focus_bottom, sHighlightBgColor, FALSE); - - if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 2) + if (folder_open) { gl_rect_2d( - 0, - llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2, + FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect getRect().getWidth() - 2, - 2, + 0, sHighlightBgColor, FALSE); } mDragAndDropTarget = FALSE; } + S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; // First case is used for open folders if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) { - mIconOpen->draw(mIndentation + ARROW_SIZE + TEXT_PAD, getRect().getHeight() - mIcon->getHeight()); + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); } else if(mIcon) { - mIcon->draw(mIndentation + ARROW_SIZE + TEXT_PAD, getRect().getHeight() - mIcon->getHeight()); + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); } if (!mLabel.empty()) @@ -953,7 +962,7 @@ void LLFolderViewItem::draw() BOOL debug_filters = getRoot()->getDebugFilters(); LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); F32 right_x; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; if (debug_filters) { @@ -963,7 +972,8 @@ void LLFolderViewItem::draw() } LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); - sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, + LLFontGL::getFontMonospace()->renderUTF8( + mStatusText, 0, text_left, y, filter_color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); text_left = right_x; @@ -1004,7 +1014,7 @@ void LLFolderViewItem::draw() S32_MAX, S32_MAX, &right_x, FALSE ); } - if (sBoxImage.notNull() && mStringMatchOffset != std::string::npos) + if (mStringMatchOffset != std::string::npos) { // don't draw backgrounds for zero-length strings S32 filter_string_length = getRoot()->getFilterSubString().size(); @@ -1013,14 +1023,15 @@ void LLFolderViewItem::draw() std::string combined_string = mLabel + mLabelSuffix; S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3); - S32 top = getRect().getHeight(); - + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; + + LLUIImage* box_image = default_params.selection_image; LLRect box_rect(left, top, right, bottom); - sBoxImage->draw(box_rect, sFilterBGColor); + box_image->draw(box_rect, sFilterBGColor); F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD; - font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, filter_string_length, S32_MAX, &right_x, FALSE ); } diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 6f8c738a59..be8e73a5a9 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -101,7 +101,10 @@ public: Optional listener; Optional folder_arrow_image; + Optional folder_indentation; // pixels Optional selection_image; + Optional item_height; // pixels + Optional item_top_pad; // pixels Optional creation_date; //UTC seconds @@ -110,7 +113,7 @@ public: // layout constants static const S32 LEFT_PAD = 5; - // LEFT_INDENTATION is set via settings.xml FolderIndentation + // LEFT_INDENTATION is set via folder_indentation above static const S32 ICON_PAD = 2; static const S32 ICON_WIDTH = 16; static const S32 TEXT_PAD = 1; @@ -127,11 +130,7 @@ protected: friend class LLUICtrlFactory; friend class LLFolderViewEventListener; - LLFolderViewItem(Params p = LLFolderViewItem::Params()); - - static const LLFontGL* sSmallFont; - static LLUIImagePtr sArrowImage; - static LLUIImagePtr sBoxImage; + LLFolderViewItem(const Params& p); std::string mLabel; std::string mSearchableLabel; @@ -150,6 +149,7 @@ protected: LLUIImagePtr mIconOpen; BOOL mHasVisibleChildren; S32 mIndentation; + S32 mItemHeight; S32 mNumDescendantsSelected; BOOL mPassedFilter; S32 mLastFilterGeneration; @@ -157,8 +157,6 @@ protected: F32 mControlLabelRotation; LLFolderView* mRoot; BOOL mDragAndDropTarget; - LLUIImagePtr mArrowImage; - LLUIImagePtr mBoxImage; BOOL mIsLoading; LLTimer mTimeSinceRequestStart; bool mHidden; @@ -237,7 +235,7 @@ public: virtual void recursiveDeselect(BOOL deselect_self); // gets multiple-element selection - virtual BOOL getSelectionList(std::set &selection){return TRUE;} + virtual BOOL getSelectionList(std::set &selection) const {return TRUE;} // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); @@ -304,7 +302,7 @@ public: // Show children (unfortunate that this is called "open") virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() { return FALSE; } + virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor ); @@ -499,7 +497,7 @@ public: virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); // Get the current state of the folder. - virtual BOOL isOpen() { return mIsOpen; } + virtual BOOL isOpen() const { return mIsOpen; } // special case if an object is dropped on the child. BOOL handleDragAndDropFromChild(MASK mask, diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index df7aa9eabf..82293b4aa0 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -417,6 +417,16 @@ BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id) return gesture->mPlaying; } +BOOL LLGestureManager::isGesturePlaying(LLMultiGesture* gesture) +{ + if(!gesture) + { + return FALSE; + } + + return gesture->mPlaying; +} + void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index e80eea9ae9..c562587c6f 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -103,6 +103,8 @@ public: BOOL isGesturePlaying(const LLUUID& item_id); + BOOL isGesturePlaying(LLMultiGesture* gesture); + const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being // previewed. diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 7dd8ea694e..d6e2bb0445 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -146,6 +146,12 @@ void LLGroupActions::startCall(const LLUUID& group_id) // static void LLGroupActions::join(const LLUUID& group_id) { + if (!gAgent.canJoinGroups()) + { + LLNotificationsUtil::add("JoinedTooManyGroups"); + return; + } + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -226,7 +232,9 @@ void LLGroupActions::activate(const LLUUID& group_id) static bool isGroupUIVisible() { - LLPanel* panel = LLSideTray::getInstance()->findChild("panel_group_info_sidetray"); + static LLPanel* panel = 0; + if(!panel) + panel = LLSideTray::getInstance()->findChild("panel_group_info_sidetray"); if(!panel) return false; return panel->isInVisibleChain(); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 3ca459a403..e75d35bea4 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -210,7 +210,6 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL item->setGroupID(id); item->setName(name, mNameFilter); item->setGroupIconID(icon_id); -// item->setContextMenu(mContextMenu); item->childSetVisible("info_btn", false); item->childSetVisible("profile_btn", false); @@ -268,8 +267,9 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) LLUUID selected_group_id = getSelectedUUID(); bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected + // each group including "none" can be activated if (userdata.asString() == "activate") - return real_group_selected && gAgent.getGroupID() != selected_group_id; + return gAgent.getGroupID() != selected_group_id; return real_group_selected; } @@ -283,7 +283,6 @@ LLGroupListItem::LLGroupListItem() mGroupIcon(NULL), mGroupNameBox(NULL), mInfoBtn(NULL), -//mContextMenu(NULL), //TODO: mGroupID(LLUUID::null) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_list_item.xml"); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 0b5da40be4..8ad94b957d 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -287,7 +287,7 @@ void LLHUDText::renderText(BOOL for_select) mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); // *TODO: cache this image - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); // *TODO: make this a per-text setting LLColor4 bg_color = LLUIColorTable::instance().getColor("BackgroundChatColor"); @@ -606,7 +606,7 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo U32 line_length = 0; do { - S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), TRUE); + S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE); mTextSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), style, color)); line_length += segment_length; } @@ -642,7 +642,7 @@ void LLHUDText::setLabel(const LLWString &wlabel) U32 line_length = 0; do { - S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), TRUE); + S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE); mLabelSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor)); line_length += segment_length; } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 259f629bdd..e06e0c94ec 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -42,7 +42,6 @@ #include "llbottomtray.h" #include "llchannelmanager.h" #include "llchiclet.h" -#include "llfloaterchat.h" #include "llfloaterreg.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" @@ -59,6 +58,7 @@ #include "llinventorymodel.h" #include "llrootview.h" +#include "llspeakers.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) @@ -115,11 +115,21 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); + + LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); } void LLIMFloater::onFocusReceived() { LLIMModel::getInstance()->setActiveSessionID(mSessionID); + + // return focus to the input field when active tab in the multitab container is clicked. + if (isChatMultiTab() && mInputEditor) + { + mInputEditor->setFocus(TRUE); + } + + LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true); } // virtual @@ -341,13 +351,15 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata) void LLIMFloater::onSlide() { - LLPanel* im_control_panel = getChild("panel_im_control_panel"); - im_control_panel->setVisible(!im_control_panel->getVisible()); + mControlPanel->setVisible(!mControlPanel->getVisible()); + + gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getVisible()); - gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible()); + getChild("slide_left_btn")->setVisible(mControlPanel->getVisible()); + getChild("slide_right_btn")->setVisible(!mControlPanel->getVisible()); - getChild("slide_left_btn")->setVisible(im_control_panel->getVisible()); - getChild("slide_right_btn")->setVisible(!im_control_panel->getVisible()); + LLLayoutStack* stack = getChild("im_panels"); + if (stack) stack->setAnimate(true); } //static @@ -355,35 +367,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { if (!gIMMgr->hasSession(session_id)) return NULL; - // we should make sure all related chiclets are in place when the session is a voice call - // chiclets come firts, then comes IM window - if (gIMMgr->isVoiceCall(session_id)) - { - LLIMModel* im_model = LLIMModel::getInstance(); - LLBottomTray* b_tray = LLBottomTray::getInstance(); - - //*TODO hide that into Bottom tray - if (!b_tray->getChicletPanel()->findChiclet(session_id)) - { - LLIMChiclet* chiclet = b_tray->createIMChiclet(session_id); - if(chiclet) - { - chiclet->setIMSessionName(im_model->getName(session_id)); - chiclet->setOtherParticipantId(im_model->getOtherParticipantID(session_id)); - } - } - - LLIMWellWindow::getInstance()->addIMRow(session_id); - } - - bool not_existed = true; - - if(isChatMultiTab()) - { - LLIMFloater* target_floater = findInstance(session_id); - not_existed = NULL == target_floater; - } - else + if(!isChatMultiTab()) { //hide all LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); @@ -398,19 +382,33 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } } - LLIMFloater* floater = LLFloaterReg::showTypedInstance("impanel", session_id); + bool exist = findInstance(session_id); + + LLIMFloater* floater = getInstance(session_id); + if (!floater) return NULL; if(isChatMultiTab()) { + LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); + // do not add existed floaters to avoid adding torn off instances - if (not_existed) + if (!exist) { // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; + + if (floater_container) + { + floater_container->addFloater(floater, TRUE, i_pt); + } + } - LLIMFloaterContainer* floater_container = LLFloaterReg::showTypedInstance("im_container"); - floater_container->addFloater(floater, TRUE, i_pt); + if (floater_container) + { + //selecting the panel resets a chiclet's counter + floater_container->selectFloater(floater); + floater_container->setVisible(TRUE); } } else @@ -437,8 +435,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } // window is positioned, now we can show it. - floater->setVisible(true); } + floater->setVisible(TRUE); return floater; } @@ -478,16 +476,6 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) } } -void LLIMFloater::setTornOff(bool torn_off) -{ - // When IM Floater isn't torn off, "close" button should be hidden. - // This call will just disables it, since there is a hack in LLFloater::updateButton, - // which prevents hiding of close button in that case. - setCanClose(torn_off); - - LLTransientDockableFloater::setTornOff(torn_off); -} - void LLIMFloater::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = dynamic_cast @@ -508,6 +496,15 @@ void LLIMFloater::setVisible(BOOL visible) updateMessages(); mInputEditor->setFocus(TRUE); } + + if(!visible) + { + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(mSessionID); + if(chiclet) + { + chiclet->setToggleState(false); + } + } } //static @@ -542,6 +539,11 @@ LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) return LLFloaterReg::findTypedInstance("impanel", session_id); } +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +{ + return LLFloaterReg::getTypedInstance("impanel", session_id); +} + void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) { mSessionInitialized = true; @@ -589,7 +591,7 @@ void LLIMFloater::updateMessages() std::string time = msg["time"].asString(); LLUUID from_id = msg["from_id"].asUUID(); - std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You"); + std::string from = msg["from"].asString(); std::string message = msg["message"].asString(); LLChat chat; @@ -618,6 +620,15 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); } + + // when IM Floater is a part of the multitab container LLTabContainer set focus to the first + // child on tab button's mouse up. This leads input field lost focus. See EXT-3852. + if (isChatMultiTab()) + { + // So, clear control captured mouse to prevent LLTabContainer set focus on the panel's first child. + // do not pass self->mInputEditor, this leads to have "Edit Text" mouse pointer wherever it is. + gFocusMgr.setMouseCapture(NULL); + } } // static @@ -1011,3 +1022,20 @@ void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) floater->removeTypingIndicator(); } + +void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) +{ + + if (isChatMultiTab()) + { + LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + if (!im_box) return; + + if (LLIMFloater::findInstance(session_id)) return; + + LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); + + im_box->addFloater(new_tab, FALSE, LLTabContainer::END); + } + +} diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index bc7a43e852..d9db385d06 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -64,7 +64,6 @@ public: // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); - /*virtual*/ void setTornOff(bool torn_off); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); @@ -75,6 +74,8 @@ public: static LLIMFloater* findInstance(const LLUUID& session_id); + static LLIMFloater* getInstance(const LLUUID& session_id); + void sessionInitReplyReceived(const LLUUID& im_session_id); // get new messages from LLIMModel @@ -113,6 +114,8 @@ public: //used as a callback on receiving new IM message static void sRemoveTypingIndicator(const LLSD& data); + static void onIMChicletCreated(const LLUUID& session_id); + private: // process focus events to set a currently active session /* virtual */ void onFocusLost(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 2d7333f7e4..6cc985aef4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -34,6 +34,7 @@ #include "llviewerprecompiledheaders.h" #include "llimfloatercontainer.h" +#include "llfloaterreg.h" // // LLIMFloaterContainer @@ -93,4 +94,14 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, } } +LLIMFloaterContainer* LLIMFloaterContainer::findInstance() +{ + return LLFloaterReg::findTypedInstance("im_container"); +} + +LLIMFloaterContainer* LLIMFloaterContainer::getInstance() +{ + return LLFloaterReg::getTypedInstance("im_container"); +} + // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index ead7cf4730..d4a542dfc2 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -52,7 +52,11 @@ public: LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); static LLFloater* getCurrentVoiceFloater(); - + + static LLIMFloaterContainer* findInstance(); + + static LLIMFloaterContainer* getInstance(); + protected: LLFloater* mActiveVoiceFloater; diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 029ddbaf2c..4bdf5f42dc 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -40,6 +40,7 @@ #include "llfontgl.h" #include "llrect.h" #include "llerror.h" +#include "llmultifloater.h" #include "llstring.h" #include "message.h" #include "lltextbox.h" @@ -59,7 +60,6 @@ #include "llinventory.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" -#include "llfloaterchat.h" #include "lliconctrl.h" #include "llkeyboard.h" #include "lllineeditor.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 40227539d0..ff20a55358 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -42,46 +42,30 @@ #include "llhttpclient.h" #include "llsdutil_math.h" #include "llstring.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llagent.h" +#include "llagentui.h" +#include "llappviewer.h" #include "llavatariconctrl.h" #include "llbottomtray.h" #include "llcallingcard.h" #include "llchat.h" -#include "llchiclet.h" -#include "llresmgr.h" -#include "llfloaterchat.h" #include "llfloaterchatterbox.h" -#include "llavataractions.h" -#include "llhttpnode.h" #include "llimfloater.h" -#include "llimpanel.h" #include "llgroupiconctrl.h" -#include "llresizebar.h" -#include "lltabcontainer.h" -#include "llviewercontrol.h" -#include "llfloater.h" #include "llmutelist.h" -#include "llresizehandle.h" -#include "llkeyboard.h" -#include "llui.h" -#include "llviewermenu.h" -#include "llcallingcard.h" -#include "lltoolbar.h" +#include "llrecentpeople.h" #include "llviewermessage.h" #include "llviewerwindow.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnearbychat.h" -#include "llviewerregion.h" -#include "llvoicechannel.h" -#include "lltrans.h" -#include "llrecentpeople.h" -#include "llsyswellwindow.h" +#include "llspeakers.h" //for LLIMSpeakerMgr +#include "lltextutil.h" +#include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llagentui.h" const static std::string IM_TIME("time"); const static std::string IM_TEXT("message"); @@ -92,6 +76,7 @@ const static std::string NO_SESSION("(IM Session Doesn't Exist)"); const static std::string ADHOC_NAME_SUFFIX(" Conference"); std::string LLCallDialogManager::sPreviousSessionlName = ""; +LLIMModel::LLIMSession::SType LLCallDialogManager::sPreviousSessionType = LLIMModel::LLIMSession::P2P_SESSION; std::string LLCallDialogManager::sCurrentSessionlName = ""; LLIMModel::LLIMSession* LLCallDialogManager::sSession = NULL; LLVoiceChannel::EState LLCallDialogManager::sOldState = LLVoiceChannel::STATE_READY; @@ -178,6 +163,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type) { mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id); + mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID); // check if it was AVALINE call if (!mOtherParticipantIsAvatar) @@ -208,7 +194,10 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); // All participants will be added to the list of people we've recently interacted with. - mSpeakers->addListener(&LLRecentPeople::instance(), "add"); + + // we need to add only _active_ speakers...so comment this. + // may delete this later on cleanup + //mSpeakers->addListener(&LLRecentPeople::instance(), "add"); //we need to wait for session initialization for outgoing ad-hoc and group chat session //correct session id for initiated ad-hoc chat will be received from the server @@ -224,7 +213,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& { mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID); mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID); - mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID); } if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) @@ -675,6 +663,12 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file); if (!session) return false; + //good place to add some1 to recent list + //other places may be called from message history. + if( !from_id.isNull() && + ( session->isP2PSessionType() || session->isAdHocSessionType() ) ) + LLRecentPeople::instance().add(from_id); + // notify listeners LLSD arg; arg["session_id"] = session_id; @@ -781,7 +775,7 @@ LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const LLIMSession* session = findIMSession(session_id); if (!session) { - llwarns << "session " << session_id << "does not exist " << llendl; + llwarns << "session " << session_id << " does not exist " << llendl; return NULL; } @@ -1360,8 +1354,15 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id) sCurrentSessionlName = ""; // Empty string results in "Nearby Voice Chat" after substitution return; } + + if (sSession) + { + // store previous session type to process Avaline calls in dialogs + sPreviousSessionType = sSession->mSessionType; + } + sSession = session; - sSession->mVoiceChannel->setStateChangedCallback(LLCallDialogManager::onVoiceChannelStateChanged); + sSession->mVoiceChannel->setStateChangedCallback(boost::bind(LLCallDialogManager::onVoiceChannelStateChanged, _1, _2, _3)); if(sCurrentSessionlName != session->mName) { sPreviousSessionlName = sCurrentSessionlName; @@ -1378,6 +1379,7 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id) mCallDialogPayload["session_name"] = sSession->mName; mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID; mCallDialogPayload["old_channel_name"] = sPreviousSessionlName; + mCallDialogPayload["old_session_type"] = sPreviousSessionType; mCallDialogPayload["state"] = LLVoiceChannel::STATE_CALL_STARTED; mCallDialogPayload["disconnected_channel_name"] = sSession->mName; mCallDialogPayload["session_type"] = sSession->mSessionType; @@ -1407,6 +1409,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat mCallDialogPayload["session_name"] = sSession->mName; mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID; mCallDialogPayload["old_channel_name"] = sPreviousSessionlName; + mCallDialogPayload["old_session_type"] = sPreviousSessionType; mCallDialogPayload["state"] = new_state; mCallDialogPayload["disconnected_channel_name"] = sSession->mName; mCallDialogPayload["session_type"] = sSession->mSessionType; @@ -1421,6 +1424,11 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat } break; + case LLVoiceChannel::STATE_HUNG_UP: + // this state is coming before session is changed, so, put it into payload map + mCallDialogPayload["old_session_type"] = sSession->mSessionType; + break; + case LLVoiceChannel::STATE_CONNECTED : ocd = LLFloaterReg::findTypedInstance("outgoing_call", LLOutgoingCallDialog::OCD_KEY); if (ocd) @@ -1561,7 +1569,15 @@ void LLOutgoingCallDialog::show(const LLSD& key) // tell the user which voice channel they are leaving if (!mPayload["old_channel_name"].asString().empty()) { - childSetTextArg("leaving", "[CURRENT_CHAT]", mPayload["old_channel_name"].asString()); + bool was_avaline_call = LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["old_session_type"].asInteger(); + + std::string old_caller_name = mPayload["old_channel_name"].asString(); + if (was_avaline_call) + { + old_caller_name = LLTextUtil::formatPhoneNumber(old_caller_name); + } + + childSetTextArg("leaving", "[CURRENT_CHAT]", old_caller_name); } else { @@ -1570,15 +1586,28 @@ void LLOutgoingCallDialog::show(const LLSD& key) if (!mPayload["disconnected_channel_name"].asString().empty()) { - childSetTextArg("nearby", "[VOICE_CHANNEL_NAME]", mPayload["disconnected_channel_name"].asString()); + std::string channel_name = mPayload["disconnected_channel_name"].asString(); + if (LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["session_type"].asInteger()) + { + channel_name = LLTextUtil::formatPhoneNumber(channel_name); + } + childSetTextArg("nearby", "[VOICE_CHANNEL_NAME]", channel_name); childSetTextArg("nearby_P2P", "[VOICE_CHANNEL_NAME]", mPayload["disconnected_channel_name"].asString()); } std::string callee_name = mPayload["session_name"].asString(); + + LLUUID session_id = mPayload["session_id"].asUUID(); + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); + if (callee_name == "anonymous") { callee_name = getString("anonymous"); } + else if (!is_avatar) + { + callee_name = LLTextUtil::formatPhoneNumber(callee_name); + } setTitle(callee_name); @@ -1728,16 +1757,21 @@ BOOL LLIncomingCallDialog::postBuild() call_type = getString(mPayload["notify_box_type"]); } + + // check to see if this is an Avaline call + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); + childSetVisible("Start IM", is_avatar); // no IM for avaline + if (caller_name == "anonymous") { caller_name = getString("anonymous"); } - - setTitle(caller_name + " " + call_type); + else if (!is_avatar) + { + caller_name = LLTextUtil::formatPhoneNumber(caller_name); + } - // check to see if this is an Avaline call - bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); - childSetVisible("Start IM", is_avatar); // no IM for avaline + setTitle(caller_name + " " + call_type); LLUICtrl* caller_name_widget = getChild("caller name"); caller_name_widget->setValue(caller_name + " " + call_type); @@ -1805,7 +1839,7 @@ void LLIncomingCallDialog::onStartIM(void* user_data) void LLIncomingCallDialog::processCallResponse(S32 response) { - if (!gIMMgr) + if (!gIMMgr || gDisconnected) return; LLUUID session_id = mPayload["session_id"].asUUID(); @@ -2185,7 +2219,6 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloaterChat::addChatHistory(chat); LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); if(nearby_chat) @@ -2353,7 +2386,9 @@ LLUUID LLIMMgr::addSession( //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions if (!new_session) return session_id; - noteOfflineUsers(session_id, floater, ids); + //Per Plan's suggestion commented "explicit offline status warning" out to make Dessie happier (see EXT-3609) + //*TODO After February 2010 remove this commented out line if no one will be missing that warning + //noteOfflineUsers(session_id, floater, ids); // Only warn for regular IMs - not group IMs if( dialog == IM_NOTHING_SPECIAL ) @@ -3085,9 +3120,6 @@ public: ll_vector3_from_sd(message_params["position"]), true); - chat.mText = std::string("IM: ") + name + separator_string + saved + message; - LLFloaterChat::addChat(chat, TRUE, is_this_agent); - //K now we want to accept the invitation std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 11860d0efb..a226d66b12 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -33,22 +33,19 @@ #ifndef LL_LLIMVIEW_H #define LL_LLIMVIEW_H -#include "lldarray.h" -#include "lldockablefloater.h" -#include "llspeakers.h" //for LLIMSpeakerMgr -#include "llimpanel.h" //for voice channels -#include "llmodaldialog.h" #include "lldockablefloater.h" #include "llinstantmessage.h" -#include "lluuid.h" -#include "llmultifloater.h" + #include "lllogchat.h" +#include "llvoicechannel.h" class LLFloaterChatterBox; class LLUUID; class LLFloaterIMPanel; class LLFriendObserver; class LLCallDialogManager; +class LLIMSpeakerMgr; + class LLIMModel : public LLSingleton { @@ -78,6 +75,11 @@ public: bool isP2P(); bool isOtherParticipantAvaline(); + bool isP2PSessionType() const { return mSessionType == P2P_SESSION;} + bool isAdHocSessionType() const { return mSessionType == ADHOC_SESSION;} + bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;} + bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;} + LLUUID mSessionID; std::string mName; EInstantMessage mType; @@ -475,6 +477,7 @@ public: protected: static std::string sPreviousSessionlName; + static LLIMModel::LLIMSession::SType sPreviousSessionType; static std::string sCurrentSessionlName; static LLIMModel::LLIMSession* sSession; static LLVoiceChannel::EState sOldState; diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h index 731e99534b..a1cb9cd71c 100644 --- a/indra/newview/llinspect.h +++ b/indra/newview/llinspect.h @@ -55,7 +55,7 @@ public: /// Inspectors close themselves when they lose focus /*virtual*/ void onFocusLost(); -private: +protected: LLFrameTimer mCloseTimer; LLFrameTimer mOpenTimer; }; diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index dae980feb1..0374a1d25b 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -93,6 +93,10 @@ public: // Update view based on information from avatar properties processor void processAvatarData(LLAvatarData* data); + // override the inspector mouse leave so timer is only paused if + // gear menu is not open + /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); + private: // Make network requests for all the data to display in this view. // Used on construction and if avatar id changes. @@ -112,6 +116,7 @@ private: void onClickAddFriend(); void onClickViewProfile(); void onClickIM(); + void onClickCall(); void onClickTeleport(); void onClickInviteToGroup(); void onClickPay(); @@ -204,6 +209,7 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) mCommitCallbackRegistrar.add("InspectAvatar.AddFriend", boost::bind(&LLInspectAvatar::onClickAddFriend, this)); mCommitCallbackRegistrar.add("InspectAvatar.IM", boost::bind(&LLInspectAvatar::onClickIM, this)); + mCommitCallbackRegistrar.add("InspectAvatar.Call", boost::bind(&LLInspectAvatar::onClickCall, this)); mCommitCallbackRegistrar.add("InspectAvatar.Teleport", boost::bind(&LLInspectAvatar::onClickTeleport, this)); mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup", boost::bind(&LLInspectAvatar::onClickInviteToGroup, this)); mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this)); @@ -257,8 +263,6 @@ BOOL LLInspectAvatar::postBuild(void) } - - // Multiple calls to showInstance("inspect_avatar", foo) will provide different // LLSD for foo, which we will catch here. //virtual @@ -274,7 +278,7 @@ void LLInspectAvatar::onOpen(const LLSD& data) getChild("gear_self_btn")->setVisible(self); getChild("gear_btn")->setVisible(!self); - + // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned // See LLToolTipMgr::createToolTip @@ -382,11 +386,25 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) mPropertiesRequest = NULL; } +// For the avatar inspector, we only want to unpause the fade timer +// if neither the gear menu or self gear menu are open +void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLMenuGL* gear_menu = getChild("gear_btn")->getMenu(); + LLMenuGL* gear_menu_self = getChild("gear_self_btn")->getMenu(); + if ( !(gear_menu && gear_menu->getVisible()) && + !(gear_menu_self && gear_menu_self->getVisible())) + { + mOpenTimer.unpause(); + } +} + void LLInspectAvatar::updateModeratorPanel() { bool enable_moderator_panel = false; - if (LLVoiceChannel::getCurrentVoiceChannel()) + if (LLVoiceChannel::getCurrentVoiceChannel() && + mAvatarID != gAgent.getID()) { LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); @@ -400,6 +418,7 @@ void LLInspectAvatar::updateModeratorPanel() LLPointer selected_speakerp = speaker_mgr->findSpeaker(mAvatarID); if(speaker_mgr->isVoiceActive() && selected_speakerp && + selected_speakerp->isInVoiceChannel() && ((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike())) { getChild("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice); @@ -497,42 +516,58 @@ void LLInspectAvatar::toggleSelectedVoice(bool enabled) void LLInspectAvatar::updateVolumeSlider() { - // By convention, we only display and toggle voice mutes, not all mutes - bool is_muted = LLMuteList::getInstance()-> - isMuted(mAvatarID, LLMute::flagVoiceChat); - bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID); - LLUICtrl* mute_btn = getChild("mute_btn"); - mute_btn->setEnabled( voice_enabled ); - mute_btn->setValue( is_muted ); + bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID); - LLUICtrl* volume_slider = getChild("volume_slider"); - volume_slider->setEnabled( voice_enabled && !is_muted ); - const F32 DEFAULT_VOLUME = 0.5f; - F32 volume; - if (is_muted) + // Do not display volume slider and mute button if it + // is ourself or we are not in a voice channel together + if (!voice_enabled || (mAvatarID == gAgent.getID())) { - // it's clearer to display their volume as zero - volume = 0.f; + getChild("mute_btn")->setVisible(false); + getChild("volume_slider")->setVisible(false); } - else if (!voice_enabled) - { - // use nominal value rather than 0 - volume = DEFAULT_VOLUME; - } - else + + else { - // actual volume - volume = gVoiceClient->getUserVolume(mAvatarID); + getChild("mute_btn")->setVisible(true); + getChild("volume_slider")->setVisible(true); - // *HACK: Voice client doesn't have any data until user actually - // says something. - if (volume == 0.f) + // By convention, we only display and toggle voice mutes, not all mutes + bool is_muted = LLMuteList::getInstance()-> + isMuted(mAvatarID, LLMute::flagVoiceChat); + + LLUICtrl* mute_btn = getChild("mute_btn"); + + bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden"); + + mute_btn->setEnabled( !is_linden); + mute_btn->setValue( is_muted ); + + LLUICtrl* volume_slider = getChild("volume_slider"); + volume_slider->setEnabled( !is_muted ); + + const F32 DEFAULT_VOLUME = 0.5f; + F32 volume; + if (is_muted) { - volume = DEFAULT_VOLUME; + // it's clearer to display their volume as zero + volume = 0.f; } + else + { + // actual volume + volume = gVoiceClient->getUserVolume(mAvatarID); + + // *HACK: Voice client doesn't have any data until user actually + // says something. + if (volume == 0.f) + { + volume = DEFAULT_VOLUME; + } + } + volume_slider->setValue( (F64)volume ); } - volume_slider->setValue( (F64)volume ); + } void LLInspectAvatar::onClickMuteVolume() @@ -611,6 +646,12 @@ void LLInspectAvatar::onClickIM() closeFloater(); } +void LLInspectAvatar::onClickCall() +{ + LLAvatarActions::startCall(mAvatarID); + closeFloater(); +} + void LLInspectAvatar::onClickTeleport() { LLAvatarActions::offerTeleport(mAvatarID); diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index cb35a287e9..dd313c528d 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -41,6 +41,7 @@ #include "llslurl.h" #include "llviewermenu.h" // handle_object_touch(), handle_buy() #include "llviewermedia.h" +#include "llviewermediafocus.h" #include "llviewerobjectlist.h" // to select the requested object // Linden libraries @@ -82,6 +83,10 @@ public: // Release the selection and do other cleanup /*virtual*/ void onClose(bool app_quitting); + // override the inspector mouse leave so timer is only paused if + // gear menu is not open + /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); + private: // Refresh displayed data with information from selection manager void update(); @@ -181,7 +186,6 @@ BOOL LLInspectObject::postBuild(void) return TRUE; } - // Multiple calls to showInstance("inspect_avatar", foo) will provide different // LLSD for foo, which we will catch here. //virtual @@ -214,6 +218,10 @@ void LLInspectObject::onOpen(const LLSD& data) LLViewerObject* obj = gObjectList.findObject( mObjectID ); if (obj) { + // Media focus and this code fight over the select manager. + // Make sure any media is unfocused before changing the selection here. + LLViewerMediaFocus::getInstance()->clearFocus(); + LLSelectMgr::instance().deselectAll(); mObjectSelection = LLSelectMgr::instance().selectObjectAndFamily(obj); @@ -562,6 +570,16 @@ void LLInspectObject::updateSecureBrowsing() getChild("secure_browsing")->setVisible(is_secure_browsing); } +// For the object inspector, only unpause the fade timer +// if the gear menu is not open +void LLInspectObject::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLMenuGL* gear_menu = getChild("gear_btn")->getMenu(); + if ( !(gear_menu && gear_menu->getVisible())) + { + mOpenTimer.unpause(); + } +} void LLInspectObject::onClickBuy() { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d70221b22a..099f863dc9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2074,7 +2074,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model { if ("open" == action) { - openItem(); + LLFolderViewFolder *f = dynamic_cast(folder->getItemByID(mUUID)); + if (f) + { + f->setOpen(TRUE); + } + return; } else if ("paste" == action) @@ -2228,9 +2233,22 @@ LLUIImagePtr LLFolderBridge::getIcon() const LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) { // we only have one folder image now + if (preferred_type == LLFolderType::FT_OUTFIT) + { + return LLUI::getUIImage("Inv_LookFolderClosed"); + } return LLUI::getUIImage("Inv_FolderClosed"); } +LLUIImagePtr LLFolderBridge::getOpenIcon() const +{ + if (getPreferredType() == LLFolderType::FT_OUTFIT) + { + return LLUI::getUIImage("Inv_LookFolderOpen"); + } + return LLUI::getUIImage("Inv_FolderOpen"); +} + BOOL LLFolderBridge::renameItem(const std::string& new_name) { if(!isItemRenameable()) @@ -2430,7 +2448,7 @@ void LLFolderBridge::folderOptionsMenu() const LLInventoryCategory* category = model->getCategory(mUUID); LLFolderType::EType type = category->getPreferredType(); - const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type); + const bool is_system_folder = category && LLFolderType::lookupIsProtectedType(type); // BAP change once we're no longer treating regular categories as ensembles. const bool is_ensemble = category && (type == LLFolderType::FT_NONE || LLFolderType::lookupIsEnsembleType(type)); @@ -2444,8 +2462,8 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back("Delete"); } - // Only enable calling-card related options for non-default folders. - if (!is_sidepanel && !is_default_folder) + // Only enable calling-card related options for non-system folders. + if (!is_sidepanel && !is_system_folder) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) @@ -2479,10 +2497,14 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("Folder Wearables Separator")); } - // Only enable add/replace outfit for non-default folders. - if (!is_default_folder) + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) { - mItems.push_back(std::string("Add To Outfit")); + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (type != LLFolderType::FT_OUTFIT) + { + mItems.push_back(std::string("Add To Outfit")); + } mItems.push_back(std::string("Replace Outfit")); } if (is_ensemble) @@ -2614,6 +2636,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { mItems.push_back(std::string("Rename")); mItems.push_back(std::string("Delete")); + + // EXT-4030: disallow deletion of currently worn outfit + const LLViewerInventoryItem *base_outfit_link = LLAppearanceManager::instance().getBaseOutfitLink(); + if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) + { + mDisabledItems.push_back(std::string("Delete")); + } } } @@ -2902,80 +2931,6 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response return false; } -/* -Next functions intended to reorder items in the inventory folder and save order on server -Is now used for Favorites folder. - -*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel -*/ -void saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - - // Tell the parent folder to refresh its sort order. - gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); - } - - gInventory.notifyObservers(); -} - -LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) -{ - LLInventoryModel::item_array_t::iterator result = items.end(); - - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - if ((*i)->getUUID() == id) - { - result = i; - break; - } - } - - return result; -} - -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: - bool operator()(const LLPointer& a, const LLPointer& b) - { - return a->getSortField() < b->getSortField(); - } -}; - -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ - static LLViewerInventoryItemSort sort_functor; - std::sort(items.begin(), items.end(), sort_functor); -} - -void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop) { @@ -3058,36 +3013,34 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // if dragging from/into favorites folder only reorder items if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(mUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; if (itemp) { LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = itemp->getListener()->getUUID(); - - // ensure items are sorted properly before changing order. EXT-3498 - rearrange_item_order_by_sort_field(items); - - // update order - updateItemsOrder(items, srcItemId, destItemId); - - saveItemsOrder(items); + gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } else if (favorites_id == mUUID) // if target is the favorites folder we use copy { + // use callback to rearrange favorite landmarks after adding + // to have new one placed before target (on which it was dropped). See EXT-4312. + LLPointer cb = new AddFavoriteLandmarkCallback(); + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (drag_over_item && drag_over_item->getListener()) + { + cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + } + copy_inventory_item( gAgent.getID(), inv_item->getPermissions().getOwner(), inv_item->getUUID(), mUUID, std::string(), - LLPointer(NULL)); + cb); } else if (move_is_into_current_outfit || move_is_into_outfit) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index cc1fa45b26..fced0047e8 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -289,6 +289,7 @@ public: virtual LLFolderType::EType getPreferredType() const; virtual LLUIImagePtr getIcon() const; + virtual LLUIImagePtr getOpenIcon() const; static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 8f4136c01f..2885ba13fa 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -50,8 +50,7 @@ // newview includes #include "llappearancemgr.h" #include "llappviewer.h" -#include "llfirstuse.h" -#include "llfloaterchat.h" +//#include "llfirstuse.h" #include "llfloatercustomize.h" #include "llfocusmgr.h" #include "llfolderview.h" diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 711114173c..e44adfb511 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1994,21 +1994,23 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const descendents_actual += update.mDescendentDelta; cat->setDescendentCount(descendents_actual); cat->setVersion(++version); - llinfos << "accounted: '" << cat->getName() << "' " - << version << " with " << descendents_actual - << " descendents." << llendl; + lldebugs << "accounted: '" << cat->getName() << "' " + << version << " with " << descendents_actual + << " descendents." << llendl; } } if(!accounted) { - lldebugs << "No accounting for: '" << cat->getName() << "' " + // Error condition, this means that the category did not register that + // it got new descendents (perhaps because it is still being loaded) + // which means its descendent count will be wrong. + llwarns << "Accounting failed for '" << cat->getName() << "' version:" << version << llendl; } } else { - llwarns << "No category found for update " << update.mCategoryID - << llendl; + llwarns << "No category found for update " << update.mCategoryID << llendl; } } @@ -3620,6 +3622,98 @@ BOOL LLInventoryModel::getIsFirstTimeInViewer2() return sFirstTimeInViewer2; } +static LLInventoryModel::item_array_t::iterator find_item_iter_by_uuid(LLInventoryModel::item_array_t& items, const LLUUID& id) +{ + LLInventoryModel::item_array_t::iterator result = items.end(); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + if ((*i)->getUUID() == id) + { + result = i; + break; + } + } + + return result; +} + +// static +void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& src_item_id, const LLUUID& dest_item_id) +{ + LLInventoryModel::item_array_t::iterator it_src = find_item_iter_by_uuid(items, src_item_id); + LLInventoryModel::item_array_t::iterator it_dest = find_item_iter_by_uuid(items, dest_item_id); + + if (it_src == items.end() || it_dest == items.end()) return; + + LLViewerInventoryItem* src_item = *it_src; + items.erase(it_src); + + // target iterator can not be valid because the container was changed, so update it. + it_dest = find_item_iter_by_uuid(items, dest_item_id); + items.insert(it_dest, src_item); +} + +void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + item->setSortField(++sortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + updateItem(item); + + // Tell the parent folder to refresh its sort order. + addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); + } + + notifyObservers(); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer& a, const LLPointer& b) + { + return a->getSortField() < b->getSortField(); + } +}; + +/** + * Sorts passed items by LLViewerInventoryItem sort field. + * + * @param[in, out] items - array of items, not sorted. + */ +static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) +{ + static LLViewerInventoryItemSort sort_functor; + std::sort(items.begin(), items.end(), sort_functor); +} + +void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + // ensure items are sorted properly before changing order. EXT-3498 + rearrange_item_order_by_sort_field(items); + + // update order + updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} + //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 39377b4ae2..2a2b48ce3c 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -384,6 +384,39 @@ public: void setLibraryOwnerID(const LLUUID& id); void setLibraryRootFolderID(const LLUUID& id); + + /** + * Changes items order by insertion of the item identified by src_item_id + * BEFORE the item identified by dest_item_id. Both items must exist in items array. + * + * Sorting is stored after method is finished. Only src_item_id is moved before dest_item_id. + * + * @param[in, out] items - vector with items to be updated. It should be sorted in a right way + * before calling this method. + * @param src_item_id - LLUUID of inventory item to be moved in new position + * @param dest_item_id - LLUUID of inventory item before which source item should be placed. + */ + static void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& src_item_id, const LLUUID& dest_item_id); + + /** + * Saves current order of the passed items using inventory item sort field. + * + * It reset items' sort fields and saves them on server. + * Is used to save order for Favorites folder. + * + * @param[in] items vector of items in order to be saved. + */ + void saveItemsOrder(const LLInventoryModel::item_array_t& items); + + /** + * Rearranges Landmarks inside Favorites folder. + * Moves source landmark before target one. + * + * @param source_item_id - LLUUID of the source item to be moved into new position + * @param target_item_id - LLUUID of the target item before which source item should be placed. + */ + void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + protected: // Internal methods which add inventory and make sure that all of diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 2d9ea21b5f..2fb8aea4e9 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -311,10 +311,10 @@ bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat) { - S32 version = cat->getVersion(); - S32 descendents = cat->getDescendentCount(); - if((LLViewerInventoryCategory::VERSION_UNKNOWN == version) - || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents)) + const S32 version = cat->getVersion(); + const S32 expected_num_descendents = cat->getDescendentCount(); + if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) || + (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)) { return false; } @@ -325,15 +325,28 @@ bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items); if(!cats || !items) { - // bit of a hack - pretend we're done if they are gone or - // incomplete. should never know, but it would suck if this - // kept tight looping because of a corrupt memory state. + llwarns << "Category '" << cat->getName() << "' descendents corrupted, fetch failed." << llendl; + // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean + // that the cat just doesn't have any items or subfolders). + // Unrecoverable, so just return done so that this observer can be cleared + // from memory. return true; } - S32 known = cats->count() + items->count(); - if(descendents == known) + const S32 current_num_known_descendents = cats->count() + items->count(); + + // Got the number of descendents that we were expecting, so we're done. + if (current_num_known_descendents == expected_num_descendents) + { + return true; + } + + // Error condition, but recoverable. This happens if something was added to the + // category before it was initialized, so accountForUpdate didn't update descendent + // count and thus the category thinks it has fewer descendents than it actually has. + if (current_num_known_descendents >= expected_num_descendents) { - // hey - we're done. + llwarns << "Category '" << cat->getName() << "' expected descendentcount:" << expected_num_descendents << " descendents but got descendentcount:" << current_num_known_descendents << llendl; + cat->setDescendentCount(current_num_known_descendents); return true; } return false; @@ -352,7 +365,7 @@ void LLInventoryFetchComboObserver::changed(U32 mask) continue; } if(item->isComplete()) - { + { mCompleteItems.push_back(*it); it = mIncompleteItems.erase(it); continue; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 164e72e621..9141d50829 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -98,10 +98,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor")); - setBackgroundVisible(TRUE); - setBackgroundOpaque(TRUE); - if (mStartFolderString != "") { mBuildDefaultHierarchy = false; @@ -433,11 +429,10 @@ void LLInventoryPanel::initializeViews() { mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); } - llinfos << this << " Generating views for start folder " << mStartFolderString << llendl; rebuildViewsFor(mStartFolderID); mViewsInitialized = true; - defaultOpenInventory(); + openStartFolderOrMyInventory(); } void LLInventoryPanel::rebuildViewsFor(const LLUUID& id) @@ -491,13 +486,14 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) if (new_listener) { - LLFolderViewFolder::Params p; - p.name = new_listener->getDisplayName(); - p.icon = new_listener->getIcon(); - p.root = mFolders; - p.listener = new_listener; - p.tool_tip = p.name; - LLFolderViewFolder* folderp = LLUICtrlFactory::create(p); + LLFolderViewFolder::Params params; + params.name = new_listener->getDisplayName(); + params.icon = new_listener->getIcon(); + params.icon_open = new_listener->getOpenIcon(); + params.root = mFolders; + params.listener = new_listener; + params.tool_tip = params.name; + LLFolderViewFolder* folderp = LLUICtrlFactory::create(params); folderp->setItemSortOrder(mFolders->getSortOrder()); itemp = folderp; @@ -523,12 +519,13 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) if (new_listener) { LLFolderViewItem::Params params; - params.name(new_listener->getDisplayName()); - params.icon(new_listener->getIcon()); - params.creation_date(new_listener->getCreationDate()); - params.root(mFolders); - params.listener(new_listener); - params.rect(LLRect (0, 0, 0, 0)); + params.name = new_listener->getDisplayName(); + params.icon = new_listener->getIcon(); + params.icon_open = new_listener->getOpenIcon(); + params.creation_date = new_listener->getCreationDate(); + params.root = mFolders; + params.listener = new_listener; + params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; itemp = LLUICtrlFactory::create (params); } @@ -575,7 +572,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) } // bit of a hack to make sure the inventory is open. -void LLInventoryPanel::defaultOpenInventory() +void LLInventoryPanel::openStartFolderOrMyInventory() { if (mStartFolderString != "") { @@ -583,13 +580,17 @@ void LLInventoryPanel::defaultOpenInventory() } else { - // Get the first child (it should be "My Inventory") and - // open it up by name (just to make sure the first child is actually a folder). - LLView* first_child = mFolders->getFirstChild(); - if (first_child) + // Find My Inventory folder and open it up by name + for (LLView *child = mFolders->getFirstChild(); child; child = mFolders->findNextSibling(child)) { - const std::string& first_child_name = first_child->getName(); - mFolders->openFolder(first_child_name); + LLFolderViewFolder *fchild = dynamic_cast(child); + if (fchild && fchild->getListener() && + (fchild->getListener()->getUUID() == gInventory.getRootFolderID())) + { + const std::string& child_name = child->getName(); + mFolders->openFolder(child_name); + break; + } } } } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 4f7f0a79f6..09533b52f1 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -167,7 +167,7 @@ public: static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE); protected: - void defaultOpenInventory(); // open the first level of inventory + void openStartFolderOrMyInventory(); // open the first level of inventory LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index bd9d22c327..ce84474c05 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -59,6 +59,13 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t LLLandmark* landmark = get_ptr_in_map(mList, asset_uuid); if(landmark) { + LLVector3d dummy; + if(cb && !landmark->getGlobalPos(dummy)) + { + // landmark is not completely loaded yet + loaded_callback_map_t::value_type vt(asset_uuid, cb); + mLoadedCallbackMap.insert(vt); + } return landmark; } else diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp index d910dbf718..ae1b8f8540 100644 --- a/indra/newview/lllocationhistory.cpp +++ b/indra/newview/lllocationhistory.cpp @@ -123,6 +123,12 @@ void LLLocationHistory::save() const // build filename for each user std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + if (resolved_filename.empty()) + { + llinfos << "can't get path to location history filename - probably not logged in yet." << llendl; + return; + } + // open a file for writing llofstream file (resolved_filename); if (!file.is_open()) diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index fc9654e9ad..4e5aaeb66a 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -35,7 +35,6 @@ #include "llagent.h" #include "llagentui.h" #include "lllogchat.h" -#include "llfloaterchat.h" #include "lltrans.h" #include "llviewercontrol.h" @@ -59,9 +58,6 @@ const static std::string NEW_LINE_SPACE_PREFIX("\n "); const static std::string TWO_SPACES(" "); const static std::string MULTI_LINE_PREFIX(" "); -//viewer 1.23 may have used "You" for Agent's entries -const static std::string YOU("You"); - /** * Chat log lines - timestamp and name are optional but message text is mandatory. * diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index f30821cacf..a96240e31c 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -436,7 +436,7 @@ void LLManip::renderXYZ(const LLVector3 &vec) glPushMatrix(); { - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); gViewerWindow->setup2DRender(); const LLVector2& display_scale = gViewerWindow->getDisplayScale(); glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 93f926b5d0..87ebce1d34 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -84,7 +84,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mHomePageUrl( "" ), mIgnoreUIScale( true ), mAlwaysRefresh( false ), - mExternalUrl( "" ), mMediaSource( 0 ), mTakeFocusOnClick( true ), mCurrentNavUrl( "" ), @@ -632,6 +631,7 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->setHomeURL(mHomePageUrl); mMediaSource->setVisible( getVisible() ); mMediaSource->addObserver( this ); + mMediaSource->setBackgroundColor( getBackgroundColor() ); if(mClearCache) { mMediaSource->clearCache(); @@ -671,34 +671,12 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() // void LLMediaCtrl::draw() { - LLPluginClassMedia* media_plugin = NULL; - - if(mMediaSource && mMediaSource->hasMedia()) - { - media_plugin = mMediaSource->getMediaPlugin(); - } - else - { - return; - } - - if(!media_plugin || (!media_plugin->textureValid())) - { - // Don't try to draw without a valid texture - return; - } - - LLViewerMediaTexture* media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID); - - if (!media_texture ) - return; - if ( gRestoreGL == 1 ) { LLRect r = getRect(); reshape( r.getWidth(), r.getHeight(), FALSE ); return; - }; + } // NOTE: optimization needed here - probably only need to do this once // unless tearoffs change the parent which they probably do. @@ -712,125 +690,161 @@ void LLMediaCtrl::draw() setFrequentUpdates( false ); }; + bool draw_media = false; + + LLPluginClassMedia* media_plugin = NULL; + LLViewerMediaTexture* media_texture = NULL; + + if(mMediaSource && mMediaSource->hasMedia()) + { + media_plugin = mMediaSource->getMediaPlugin(); + + if(media_plugin && (media_plugin->textureValid())) + { + media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID); + if(media_texture) + { + draw_media = true; + } + } + } + if(mHidingInitialLoad) { // If we're hiding loading, don't draw at all. - return; + draw_media = false; } - // alpha off for this - LLGLSUIDefault gls_ui; - LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); - - gGL.pushMatrix(); + bool background_visible = isBackgroundVisible(); + bool background_opaque = isBackgroundOpaque(); + + if(draw_media) { - if (mIgnoreUIScale) + // alpha off for this + LLGLSUIDefault gls_ui; + LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); + + gGL.pushMatrix(); { - glLoadIdentity(); - // font system stores true screen origin, need to scale this by UI scale factor - // to get render origin for this view (with unit scale) - gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), - floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), - LLFontGL::sCurOrigin.mZ); - } + if (mIgnoreUIScale) + { + glLoadIdentity(); + // font system stores true screen origin, need to scale this by UI scale factor + // to get render origin for this view (with unit scale) + gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), + floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), + LLFontGL::sCurOrigin.mZ); + } - // scale texture to fit the space using texture coords - gGL.getTexUnit(0)->bind(media_texture); - gGL.color4fv( LLColor4::white.mV ); - F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); - F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); + // scale texture to fit the space using texture coords + gGL.getTexUnit(0)->bind(media_texture); + gGL.color4fv( LLColor4::white.mV ); + F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); + F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); - LLRect r = getRect(); - S32 width, height; - S32 x_offset = 0; - S32 y_offset = 0; - - if(mStretchToFill) - { - if(mMaintainAspectRatio) + LLRect r = getRect(); + S32 width, height; + S32 x_offset = 0; + S32 y_offset = 0; + + if(mStretchToFill) { - F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); - F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); - if(media_aspect > view_aspect) + if(mMaintainAspectRatio) { - // max width, adjusted height - width = r.getWidth(); - height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight()); + F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + width = r.getWidth(); + height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + height = r.getHeight(); + width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth()); + } } else { - // max height, adjusted width + width = r.getWidth(); height = r.getHeight(); - width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth()); } } else { - width = r.getWidth(); - height = r.getHeight(); + width = llmin(media_plugin->getWidth(), r.getWidth()); + height = llmin(media_plugin->getHeight(), r.getHeight()); } - } - else - { - width = llmin(media_plugin->getWidth(), r.getWidth()); - height = llmin(media_plugin->getHeight(), r.getHeight()); - } - - x_offset = (r.getWidth() - width) / 2; - y_offset = (r.getHeight() - height) / 2; + + x_offset = (r.getWidth() - width) / 2; + y_offset = (r.getHeight() - height) / 2; - if(mIgnoreUIScale) - { - x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]); - y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]); - width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); - height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); - } + if(mIgnoreUIScale) + { + x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]); + y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]); + width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); + height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + } - // draw the browser - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.begin( LLRender::QUADS ); - if (! media_plugin->getTextureCoordsOpenGL()) - { - // render using web browser reported width and height, instead of trying to invert GL scale - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( x_offset + width, y_offset + height ); + // draw the browser + gGL.setSceneBlendType(LLRender::BT_REPLACE); + gGL.begin( LLRender::QUADS ); + if (! media_plugin->getTextureCoordsOpenGL()) + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset + height ); - gGL.texCoord2f( 0.f, 0.f ); - gGL.vertex2i( x_offset, y_offset + height ); + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset + height ); - gGL.texCoord2f( 0.f, max_v ); - gGL.vertex2i( x_offset, y_offset ); + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset ); - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( x_offset + width, y_offset ); - } - else - { - // render using web browser reported width and height, instead of trying to invert GL scale - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( x_offset + width, y_offset + height ); + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset ); + } + else + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset + height ); - gGL.texCoord2f( 0.f, max_v ); - gGL.vertex2i( x_offset, y_offset + height ); + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset + height ); - gGL.texCoord2f( 0.f, 0.f ); - gGL.vertex2i( x_offset, y_offset ); + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset ); - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( x_offset + width, y_offset ); + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset ); + } + gGL.end(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } - gGL.end(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.popMatrix(); + } - gGL.popMatrix(); - + else + { + // Setting these will make LLPanel::draw draw the opaque background color. + setBackgroundVisible(true); + setBackgroundOpaque(true); + } + // highlight if keyboard focus here. (TODO: this needs some work) if ( mBorder && mBorder->getVisible() ) mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); LLPanel::draw(); + + // Restore the previous values + setBackgroundVisible(background_visible); + setBackgroundOpaque(background_opaque); } //////////////////////////////////////////////////////////////////////////////// @@ -862,9 +876,27 @@ bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( 0 == option ) { - // open in external browser because we don't support - // creation of our own secondary browser windows - LLWeb::loadURLExternal( notification["payload"]["external_url"].asString() ); + LLSD payload = notification["payload"]; + std::string url = payload["url"].asString(); + S32 target_type = payload["target_type"].asInteger(); + + switch (target_type) + { + case LLPluginClassMedia::TARGET_EXTERNAL: + // load target in an external browser + LLWeb::loadURLExternal(url); + break; + + case LLPluginClassMedia::TARGET_BLANK: + // load target in the user's preferred browser + LLWeb::loadURL(url); + break; + + default: + // unsupported link target - shouldn't happen + LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL; + break; + } } return false; } @@ -978,20 +1010,18 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self ) { // retrieve the event parameters - std::string target = self->getClickTarget(); std::string url = self->getClickURL(); + U32 target_type = self->getClickTargetType(); - // if there is a value for the target - if ( !target.empty() ) + // is there is a target specified for the link? + if (target_type == LLPluginClassMedia::TARGET_EXTERNAL || + target_type == LLPluginClassMedia::TARGET_BLANK) { - if ( target == "_external" ) - { - mExternalUrl = url; - LLSD payload; - payload["external_url"] = mExternalUrl; - LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget); - return; - } + LLSD payload; + payload["url"] = url; + payload["target_type"] = LLSD::Integer(target_type); + LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget); + return; } const std::string protocol1( "http://" ); diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 8f9e6e7179..b0aca3cfa4 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -182,7 +182,6 @@ public: bool mOpenLinksInInternalBrowser; bool mTrusted; std::string mHomePageUrl; - std::string mExternalUrl; std::string mCurrentNavUrl; bool mIgnoreUIScale; bool mAlwaysRefresh; diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index a2aef9ba63..8d950f072d 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -45,8 +45,7 @@ #include "llagent.h" #include "llcallingcard.h" #include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llfloaterchat.h" +//#include "llfirstuse.h" #include "llfloaterworldmap.h" #include "lllineeditor.h" #include "llstatusbar.h" diff --git a/indra/newview/llmorphview.cpp b/indra/newview/llmorphview.cpp index f562e45770..b95e8bd3a2 100644 --- a/indra/newview/llmorphview.cpp +++ b/indra/newview/llmorphview.cpp @@ -40,7 +40,7 @@ #include "lldrawable.h" #include "lldrawpoolavatar.h" #include "llface.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llfloatercustomize.h" #include "llfloatertools.h" #include "llresmgr.h" @@ -143,7 +143,7 @@ void LLMorphView::setVisible(BOOL visible) initialize(); // First run dialog - LLFirstUse::useAppearance(); + //LLFirstUse::useAppearance(); } else { diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index b520bc1c2d..7ee4c64f8f 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -64,7 +64,7 @@ #include "llviewerwindow.h" #include "llworld.h" //for particle system banning #include "llchat.h" -#include "llfloaterchat.h" +#include "llimpanel.h" #include "llimview.h" #include "llnotifications.h" #include "lluistring.h" @@ -258,7 +258,7 @@ LLMuteList::~LLMuteList() { // If we quit from the login screen we will not have an SL account // name. Don't try to save, otherwise we'll dump a file in - // C:\Program Files\SecondLife\ JC + // C:\Program Files\SecondLife\ or similar. JC std::string user_dir = gDirUtilp->getLindenUserDir(); if (!user_dir.empty()) { @@ -532,9 +532,6 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n LLIMModel::getInstance()->addMessage(agent_id, SYSTEM_FROM, LLUUID::null, message); } - - LLChat auto_chat(message); - LLFloaterChat::addChat(auto_chat, FALSE, FALSE); } } diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp index 2f4a266198..cd810b9793 100644 --- a/indra/newview/llnamebox.cpp +++ b/indra/newview/llnamebox.cpp @@ -52,6 +52,8 @@ LLNameBox::LLNameBox(const Params& p) : LLTextBox(p) { mNameID = LLUUID::null; + mLink = p.link; + mInitialValue = p.initial_value().asString(); LLNameBox::sInstances.insert(this); setText(LLStringUtil::null); } @@ -66,17 +68,23 @@ void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group) mNameID = name_id; std::string name; + BOOL got_name = FALSE; if (!is_group) { - gCacheName->getFullName(name_id, name); + got_name = gCacheName->getFullName(name_id, name); } else { - gCacheName->getGroupName(name_id, name); + got_name = gCacheName->getGroupName(name_id, name); } - setText(name); + // Got the name already? Set it. + // Otherwise it will be set later in refresh(). + if (got_name) + setName(name, is_group); + else + setText(mInitialValue); } void LLNameBox::refresh(const LLUUID& id, const std::string& firstname, @@ -93,7 +101,7 @@ void LLNameBox::refresh(const LLUUID& id, const std::string& firstname, { name = firstname; } - setText(name); + setName(name, is_group); } } @@ -109,3 +117,22 @@ void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname, box->refresh(id, firstname, lastname, is_group); } } + +void LLNameBox::setName(const std::string& name, BOOL is_group) +{ + if (mLink) + { + std::string url; + + if (is_group) + url = "[secondlife:///app/group/" + LLURI::escape(name) + "/about " + name + "]"; + else + url = "[secondlife:///app/agent/" + mNameID.asString() + "/about " + name + "]"; + + setText(url); + } + else + { + setText(name); + } +} diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h index 3edb36883f..48b54faec8 100644 --- a/indra/newview/llnamebox.h +++ b/indra/newview/llnamebox.h @@ -47,9 +47,11 @@ public: struct Params : public LLInitParam::Block { Optional is_group; + Optional link; Params() : is_group("is_group", false) + , link("link", false) {} }; @@ -67,10 +69,14 @@ protected: friend class LLUICtrlFactory; private: + void setName(const std::string& name, BOOL is_group); + static std::set sInstances; private: LLUUID mNameID; + BOOL mLink; + std::string mInitialValue; }; diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 7e6145f578..6375362ae2 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -74,12 +74,12 @@ void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; - std::string fullname; - gCacheName->getFullName(agent_id, fullname); - - fullname.append(suffix); + NameItem item; + item.value = agent_id; + item.enabled = enabled; + item.target = INDIVIDUAL; - addStringUUIDItem(fullname, agent_id, pos, enabled); + addNameItemRow(item, pos); } // virtual, public @@ -130,11 +130,12 @@ BOOL LLNameListCtrl::handleDragAndDrop( return handled; } -void LLNameListCtrl::showAvatarInspector(const LLUUID& avatar_id) +void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group) { - LLSD key; - key["avatar_id"] = avatar_id; - LLFloaterReg::showInstance("inspect_avatar", key); + if (is_group) + LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id)); + else + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); } //virtual @@ -147,7 +148,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) && column_index == mNameColumnIndex) { // ...this is the column with the avatar name - LLUUID avatar_id = hit_item->getValue().asUUID(); + LLUUID avatar_id = getItemId(hit_item); if (avatar_id.notNull()) { // ...valid avatar id @@ -164,9 +165,12 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) LLCoordGL pos( sticky_rect.mRight - 16, sticky_rect.mTop ); LLPointer icon = LLUI::getUIImage("Info_Small"); + // Should we show a group or an avatar inspector? + bool is_group = hit_item->getValue()["is_group"].asBoolean(); + LLToolTip::Params params; params.background_visible( false ); - params.click_callback( boost::bind(&LLNameListCtrl::showAvatarInspector, this, avatar_id) ); + params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) ); params.delay_time(0.0f); // spawn instantly on hover params.image( icon ); params.message(""); @@ -220,9 +224,22 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition p } -LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLNameListCtrl::NameItem& name_item, EAddPosition pos) +LLScrollListItem* LLNameListCtrl::addNameItemRow( + const LLNameListCtrl::NameItem& name_item, + EAddPosition pos, + std::string& suffix) { - LLScrollListItem* item = LLScrollListCtrl::addRow(name_item, pos); + LLUUID id = name_item.value().asUUID(); + LLScrollListItem* item = NULL; + + // Store item type so that we can invoke the proper inspector. + // *TODO Vadim: Is there a more proper way of storing additional item data? + { + LLNameListCtrl::NameItem name_item_(name_item); + name_item_.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP); + item = LLScrollListCtrl::addRow(name_item_, pos); + } + if (!item) return NULL; // use supplied name by default @@ -230,7 +247,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLNameListCtrl::NameItem& switch(name_item.target) { case GROUP: - gCacheName->getGroupName(name_item.value().asUUID(), fullname); + gCacheName->getGroupName(id, fullname); // fullname will be "nobody" if group not found break; case SPECIAL: @@ -239,7 +256,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLNameListCtrl::NameItem& case INDIVIDUAL: { std::string name; - if (gCacheName->getFullName(name_item.value().asUUID(), name)) + if (gCacheName->getFullName(id, name)) { fullname = name; } @@ -249,6 +266,12 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLNameListCtrl::NameItem& break; } + // Append optional suffix. + if (!suffix.empty()) + { + fullname.append(suffix); + } + LLScrollListCell* cell = item->getColumn(mNameColumnIndex); if (cell) { @@ -270,15 +293,24 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLNameListCtrl::NameItem& // public void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) { - BOOL item_exists = selectByID( agent_id ); - if(item_exists) + // Find the item specified with agent_id. + S32 idx = -1; + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) { - S32 index = getItemIndex(getFirstSelected()); - if(index >= 0) + LLScrollListItem* item = *it; + if (getItemId(item) == agent_id) { - deleteSingleItem(index); + idx = getItemIndex(item); + break; } } + + // Remove it. + if (idx >= 0) + { + selectNthItem(idx); // not sure whether this is needed, taken from previous implementation + deleteSingleItem(idx); + } } // public @@ -303,7 +335,7 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first, for (iter = getItemList().begin(); iter != getItemList().end(); iter++) { LLScrollListItem* item = *iter; - if (item->getUUID() == id) + if (getItemId(item) == id) { LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(0); cell = item->getColumn(mNameColumnIndex); @@ -343,3 +375,9 @@ void LLNameListCtrl::updateColumns() } } } + +// static +LLUUID LLNameListCtrl::getItemId(LLScrollListItem* item) +{ + return item->getValue()["uuid"].asUUID(); +} diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index d0f0ec4d21..192a3a5afa 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -94,7 +94,7 @@ public: void addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); - LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM); + LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, std::string& suffix = LLStringUtil::null); // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. @@ -121,7 +121,8 @@ public: /*virtual*/ void updateColumns(); private: - void showAvatarInspector(const LLUUID& avatar_id); + void showInspector(const LLUUID& avatar_id, bool is_group); + static LLUUID getItemId(LLScrollListItem* item); private: S32 mNameColumnIndex; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 2ad82d3e8e..a7c1e73328 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -63,7 +63,7 @@ static const S32 RESIZE_BAR_THICKNESS = 3; LLNearbyChat::LLNearbyChat(const LLSD& key) - : LLDockableFloater(NULL, false, key) + : LLDockableFloater(NULL, false, false, key) ,mChatHistory(NULL) { @@ -137,7 +137,7 @@ std::string appendTime() time_t utc_time; utc_time = time_corrected(); std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"] "; + +LLTrans::getString("TimeMin")+"]"; LLSD substitution; @@ -178,28 +178,8 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive) if (!chat.mMuted) { - tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You"); - - if (chat.mChatStyle == CHAT_STYLE_IRC) - { - LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); - LLViewerChat::getChatColor(chat,txt_color); - LLFontGL* fontp = LLViewerChat::getChatFont(); - std::string font_name = LLFontGL::nameFromFont(fontp); - std::string font_size = LLFontGL::sizeFromFont(fontp); - LLStyle::Params append_style_params; - append_style_params.color(txt_color); - append_style_params.readonly_color(txt_color); - append_style_params.font.name(font_name); - append_style_params.font.size(font_size); - append_style_params.font.style = "ITALIC"; - - mChatHistory->appendMessage(chat, use_plain_text_chat_history, append_style_params); - } - else - { - mChatHistory->appendMessage(chat, use_plain_text_chat_history); - } + tmp_chat.mFromName = chat.mFromName; + mChatHistory->appendMessage(chat, use_plain_text_chat_history); } if(archive) diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 8dbaa5ac53..6cf8bcb417 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -48,13 +48,16 @@ #include "llcommandhandler.h" #include "llviewercontrol.h" #include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; // legacy callback glue void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); -static LLDefaultChildRegistry::Register r("gesture_combo_box"); +static LLDefaultChildRegistry::Register r("gesture_combo_list"); struct LLChatTypeTrigger { std::string name; @@ -66,13 +69,42 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { { "/shout" , CHAT_TYPE_SHOUT} }; -LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p) - : LLComboBox(p) - , mGestureLabelTimer() +LLGestureComboList::Params::Params() +: combo_button("combo_button"), + combo_list("combo_list") +{ +} + +LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p) +: LLUICtrl(p) , mLabel(p.label) , mViewAllItemIndex(0) { - setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this)); + LLButton::Params button_params = p.combo_button; + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + + mButton = LLUICtrlFactory::create(button_params); + mButton->reshape(getRect().getWidth(),getRect().getHeight()); + mButton->setCommitCallback(boost::bind(&LLGestureComboList::onButtonCommit, this)); + + addChild(mButton); + + LLScrollListCtrl::Params params = p.combo_list; + params.name("GestureComboList"); + params.commit_callback.function(boost::bind(&LLGestureComboList::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); + + mList = LLUICtrlFactory::create(params); + + // *HACK: adding list as a child to NonSideTrayView to make it fully visible without + // making it top control (because it would cause problems). + gViewerWindow->getNonSideTrayView()->addChild(mList); + mList->setVisible(FALSE); + + //****************************Gesture Part********************************/ + + setCommitCallback(boost::bind(&LLGestureComboList::onCommitGesture, this)); // now register us as observer since we have a place to put the results LLGestureManager::instance().addObserver(this); @@ -80,23 +112,139 @@ LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p) // refresh list from current active gestures refreshGestures(); - // This forces using of halign from xml, since LLComboBox - // sets it to LLFontGL::LEFT, if text entry is disabled - mButton->setHAlign(p.drop_down_button.font_halign); + setFocusLostCallback(boost::bind(&LLGestureComboList::hideList, this)); } -LLGestureComboBox::~LLGestureComboBox() +BOOL LLGestureComboList::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - LLGestureManager::instance().removeObserver(this); + BOOL handled = FALSE; + + if (key == KEY_ESCAPE && mask == MASK_NONE ) + { + hideList(); + handled = TRUE; + } + else + { + handled = mList->handleKey(key, mask, called_from_parent); + } + + return handled; +} + +void LLGestureComboList::showList() +{ + LLRect rect = mList->getRect(); + LLRect screen; + mButton->localRectToScreen(getRect(), &screen); + + // Calculating amount of space between the navigation bar and gestures combo + LLNavigationBar* nb = LLNavigationBar::getInstance(); + + S32 x, nb_bottom; + nb->localPointToScreen(0, 0, &x, &nb_bottom); + + S32 max_height = nb_bottom - screen.mTop; + mList->calcColumnWidths(); + rect.setOriginAndSize(screen.mLeft, screen.mTop, llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height); + + mList->setRect(rect); + mList->fitContents( llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height); + + gFocusMgr.setKeyboardFocus(this); + + // Show the list and push the button down + mButton->setToggleState(TRUE); + mList->setVisible(TRUE); +} + +void LLGestureComboList::onButtonCommit() +{ + if (!mList->getVisible()) + { + // highlight the last selected item from the original selection before potentially selecting a new item + // as visual cue to original value of combo box + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + + if (mList->getItemCount() != 0) + { + showList(); + } + } + else + { + hideList(); + } +} + +void LLGestureComboList::hideList() +{ + if (mList->getVisible()) + { + mButton->setToggleState(FALSE); + mList->setVisible(FALSE); + mList->mouseOverHighlightNthItem(-1); + gFocusMgr.setKeyboardFocus(NULL); + } +} + +S32 LLGestureComboList::getCurrentIndex() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return mList->getItemIndex( item ); + } + return -1; +} + +void LLGestureComboList::onItemSelected(const LLSD& data) +{ + const std::string name = mList->getSelectedItemLabel(); + + S32 cur_id = getCurrentIndex(); + mLastSelectedIndex = cur_id; + if (cur_id != mList->getItemCount()-1 && cur_id != -1) + { + mButton->setLabel(name); + } + + // hiding the list reasserts the old value stored in the text editor/dropdown button + hideList(); + + // commit does the reverse, asserting the value in the list + onCommit(); +} + +void LLGestureComboList::sortByName(bool ascending) +{ + mList->sortOnce(0, ascending); +} + +LLSD LLGestureComboList::getValue() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getValue(); + } + else + { + return LLSD(); + } } -void LLGestureComboBox::refreshGestures() +void LLGestureComboList::refreshGestures() { //store current selection so we can maintain it LLSD cur_gesture = getValue(); - selectFirstItem(); - // clear - clearRows(); + + mList->selectFirstItem(); + mList->clearRows(); mGestures.clear(); LLGestureManager::item_map_t::const_iterator it; @@ -107,7 +255,7 @@ void LLGestureComboBox::refreshGestures() LLMultiGesture* gesture = (*it).second; if (gesture) { - addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx)); + mList->addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx)); mGestures.push_back(gesture); idx++; } @@ -117,23 +265,42 @@ void LLGestureComboBox::refreshGestures() // store index followed by the last added Gesture and add View All item at bottom mViewAllItemIndex = idx; - addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex)); + + mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex)); // Insert label after sorting, at top, with separator below it - addSeparator(ADD_TOP); - addSimpleElement(mLabel, ADD_TOP); + mList->addSeparator(ADD_TOP); + mList->addSimpleElement(mLabel, ADD_TOP); if (cur_gesture.isDefined()) { - selectByValue(cur_gesture); + mList->selectByValue(cur_gesture); + } else { - selectFirstItem(); + mList->selectFirstItem(); } + + LLCtrlListInterface* gestures = getListInterface(); + LLMultiGesture* gesture = NULL; + + if (gestures) + { + S32 index = gestures->getSelectedValue().asInteger(); + if(index > 0) + gesture = mGestures.at(index); + } + + if(gesture && LLGestureManager::instance().isGesturePlaying(gesture)) + { + return; + } + + mButton->setLabel(mLabel); } -void LLGestureComboBox::onCommitGesture() +void LLGestureComboList::onCommitGesture() { LLCtrlListInterface* gestures = getListInterface(); if (gestures) @@ -164,50 +331,11 @@ void LLGestureComboBox::onCommitGesture() } } } - - mGestureLabelTimer.start(); - // free focus back to chat bar - setFocus(FALSE); } -//virtual -void LLGestureComboBox::draw() +LLGestureComboList::~LLGestureComboList() { - // HACK: Leave the name of the gesture in place for a few seconds. - const F32 SHOW_GESTURE_NAME_TIME = 2.f; - if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) - { - LLCtrlListInterface* gestures = getListInterface(); - if (gestures) gestures->selectFirstItem(); - mGestureLabelTimer.stop(); - } - - LLComboBox::draw(); -} - -//virtual -void LLGestureComboBox::showList() -{ - LLComboBox::showList(); - - // Calculating amount of space between the navigation bar and gestures combo - LLNavigationBar* nb = LLNavigationBar::getInstance(); - S32 x, nb_bottom; - nb->localPointToScreen(0, 0, &x, &nb_bottom); - - S32 list_bottom; - mList->localPointToScreen(0, 0, &x, &list_bottom); - - S32 max_height = nb_bottom - list_bottom; - - LLRect rect = mList->getRect(); - // List overlapped navigation bar, downsize it - if (rect.getHeight() > max_height) - { - rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height); - mList->setRect(rect); - mList->reshape(rect.getWidth(), rect.getHeight()); - } + LLGestureManager::instance().removeObserver(this); } LLNearbyChatBar::LLNearbyChatBar() diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 224118e088..d9a7403611 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -42,33 +42,52 @@ #include "llspeakers.h" -class LLGestureComboBox - : public LLComboBox - , public LLGestureManagerObserver +class LLGestureComboList + : public LLGestureManagerObserver + , public LLUICtrl { public: - struct Params : public LLInitParam::Block { }; + struct Params : public LLInitParam::Block + { + Optional combo_button; + Optional combo_list; + + Params(); + }; + protected: - LLGestureComboBox(const Params&); + friend class LLUICtrlFactory; + LLGestureComboList(const Params&); + std::vector mGestures; + std::string mLabel; + LLSD::Integer mViewAllItemIndex; + public: - ~LLGestureComboBox(); + ~LLGestureComboList(); + + LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)mList; }; + virtual void showList(); + virtual void hideList(); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + S32 getCurrentIndex() const; + void onItemSelected(const LLSD& data); + void sortByName(bool ascending = true); void refreshGestures(); void onCommitGesture(); - virtual void draw(); + void onButtonCommit(); + virtual LLSD getValue() const; // LLGestureManagerObserver trigger virtual void changed() { refreshGestures(); } -protected: - - virtual void showList(); +private: - LLFrameTimer mGestureLabelTimer; - std::vector mGestures; - std::string mLabel; - LLSD::Integer mViewAllItemIndex; + LLButton* mButton; + LLScrollListCtrl* mList; + S32 mLastSelectedIndex; }; class LLNearbyChatBar diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 9e13a626b4..c50e049d4c 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -302,7 +302,6 @@ LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& i channel->setCreatePanelCallback(callback); mChannel = LLChannelManager::getInstance()->addChannel(channel); - mChannel->setOverflowFormatString("You have %d unread nearby chat messages"); } LLNearbyChatHandler::~LLNearbyChatHandler() @@ -332,25 +331,25 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) LLChat& tmp_chat = const_cast(chat_msg); - if (tmp_chat.mChatStyle == CHAT_STYLE_IRC) - { - if(!tmp_chat.mFromName.empty()) - tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3); - else - tmp_chat.mText = tmp_chat.mText.substr(3); - } - + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); { //sometimes its usefull to have no name at all... //if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null) // tmp_chat.mFromName = tmp_chat.mFromID.asString(); } - - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); nearby_chat->addMessage(chat_msg); if(nearby_chat->getVisible()) return;//no need in toast if chat is visible - + + // Handle irc styled messages for toast panel + if (tmp_chat.mChatStyle == CHAT_STYLE_IRC) + { + if(!tmp_chat.mFromName.empty()) + tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3); + else + tmp_chat.mText = tmp_chat.mText.substr(3); + } + // arrange a channel on a screen if(!mChannel->getVisible()) { diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index dd66a6c507..fad0c6a91e 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -112,8 +112,8 @@ bool LLOfferHandler::processNotification(const LLSD& notify) LLHandlerUtil::spawnIMSession(name, from_id); } - if (notification->getPayload().has("SUPPRES_TOST") - && notification->getPayload()["SUPPRES_TOST"]) + if (notification->getPayload().has("SUPPRESS_TOAST") + && notification->getPayload()["SUPPRESS_TOAST"]) { LLNotificationsUtil::cancel(notification); } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 63803469dd..f816dc589d 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -77,7 +77,9 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) mImageLevel3(p.image_level_3), mAutoUpdate(p.auto_update), mSpeakerId(p.speaker_id), - mIsAgentControl(false) + mIsAgentControl(false), + mIsSwitchDirty(false), + mShouldSwitchOn(false) { //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange); //static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red); @@ -108,6 +110,7 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) LLOutputMonitorCtrl::~LLOutputMonitorCtrl() { LLMuteList::getInstance()->removeObserver(this); + LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } void LLOutputMonitorCtrl::setPower(F32 val) @@ -117,6 +120,26 @@ void LLOutputMonitorCtrl::setPower(F32 val) void LLOutputMonitorCtrl::draw() { + // see also switchIndicator() + if (mIsSwitchDirty) + { + mIsSwitchDirty = false; + if (mShouldSwitchOn) + { + // just notify parent visibility may have changed + notifyParentVisibilityChanged(); + } + else + { + // make itself invisible and notify parent about this + setVisible(FALSE); + notifyParentVisibilityChanged(); + + // no needs to render for invisible element + return; + } + } + // Copied from llmediaremotectrl.cpp // *TODO: Give the LLOutputMonitorCtrl an agent-id to monitor, then // call directly into gVoiceClient to ask if that agent-id is muted, is @@ -229,6 +252,7 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id) if (speaker_id.isNull() || speaker_id == mSpeakerId) return; mSpeakerId = speaker_id; + LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this); //mute management if (mAutoUpdate) @@ -251,3 +275,42 @@ void LLOutputMonitorCtrl::onChange() // check only blocking on voice. EXT-3542 setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat)); } + +// virtual +void LLOutputMonitorCtrl::switchIndicator(bool switch_on) +{ + // ensure indicator is visible in case it is not in visible chain + // to be called when parent became visible next time to notify parent that visibility is changed. + setVisible(TRUE); + + // if parent is in visible chain apply switch_on state and notify it immediately + if (getParent() && getParent()->isInVisibleChain()) + { + LL_DEBUGS("SpeakingIndicator") << "Indicator is in visible chain, notifying parent: " << mSpeakerId << LL_ENDL; + setVisible((BOOL)switch_on); + notifyParentVisibilityChanged(); + } + + // otherwise remember necessary state and mark itself as dirty. + // State will be applied i next draw when parents chain became visible. + else + { + LL_DEBUGS("SpeakingIndicator") << "Indicator is not in visible chain, parent won't be notified: " << mSpeakerId << LL_ENDL; + mIsSwitchDirty = true; + mShouldSwitchOn = switch_on; + } +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE SECTION +////////////////////////////////////////////////////////////////////////// +void LLOutputMonitorCtrl::notifyParentVisibilityChanged() +{ + LL_DEBUGS("SpeakingIndicator") << "Notify parent that visibility was changed: " << mSpeakerId << " ,new_visibility: " << getVisible() << LL_ENDL; + + LLSD params = LLSD().with("visibility_changed", getVisible()); + + notifyParent(params); +} + +// EOF diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 85ea552a57..2bbfa251e9 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -36,6 +36,7 @@ #include "v4color.h" #include "llview.h" #include "llmutelist.h" +#include "llspeakingindicatormanager.h" class LLTextBox; class LLUICtrlFactory; @@ -45,7 +46,7 @@ class LLUICtrlFactory; // class LLOutputMonitorCtrl -: public LLView, LLMuteListObserver +: public LLView, public LLSpeakingIndicator, LLMuteListObserver { public: struct Params : public LLInitParam::Block @@ -90,7 +91,29 @@ public: //called by mute list virtual void onChange(); + /** + * Implementation of LLSpeakingIndicator interface. + * Behavior is implemented via changing visibility. + * + * If instance is in visible chain now (all parents are visible) it changes visibility + * and notify parent about this. + * + * Otherwise it marks an instance as dirty and stores necessary visibility. + * It will be applied in next draw and parent will be notified. + */ + virtual void switchIndicator(bool switch_on); + private: + + /** + * Notifies parent about changed visibility. + * + * Passes LLSD with "visibility_changed" => value. + * For now it is processed by LLAvatarListItem to update (reshape) its children. + * Implemented fo complete EXT-3976 + */ + void notifyParentVisibilityChanged(); + //static LLColor4 sColorMuted; //static LLColor4 sColorNormal; //static LLColor4 sColorOverdriven; @@ -117,6 +140,10 @@ private: /** uuid of a speaker being monitored */ LLUUID mSpeakerId; + + /** indicates if the instance is dirty and should notify parent */ + bool mIsSwitchDirty; + bool mShouldSwitchOn; }; #endif diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index f3d6dbbb46..85e95ca1d6 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -52,6 +52,7 @@ #include "llfloaterreg.h" #include "llnotificationsutil.h" #include "llvoiceclient.h" +#include "llnamebox.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLDropTarget @@ -594,8 +595,11 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g if (it != mGroups.begin()) groups += ", "; - - std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + it->first + "]"; + std::string group_name = LLURI::escape(it->first); + std::string group_url= it->second.notNull() + ? "[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]" + : getString("no_group_text"); + groups += group_url; } @@ -621,19 +625,15 @@ void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data) { + LLNameBox* name_box = getChild("partner_text"); if (avatar_data->partner_id.notNull()) { - std::string first, last; - BOOL found = gCacheName->getName(avatar_data->partner_id, first, last); - if (found) - { - childSetTextArg("partner_text", "[FIRST]", first); - childSetTextArg("partner_text", "[LAST]", last); - } + name_box->setNameID(avatar_data->partner_id, FALSE); } else { - childSetTextArg("partner_text", "[FIRST]", getString("no_partner_text")); + name_box->setNameID(LLUUID::null, FALSE); + name_box->setText(getString("no_partner_text")); } } diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index e29320ffc2..3f5d80c123 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -72,6 +72,7 @@ #include "llviewerwindow.h" // for window width, height #include "llappviewer.h" // abortQuit() #include "lltrans.h" +#include "llstatusbar.h" const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ const S32 MATURE_UNDEFINED = -1; @@ -1364,6 +1365,7 @@ static const S32 CB_ITEM_PG = 1; LLPanelClassifiedEdit::LLPanelClassifiedEdit() : LLPanelClassifiedInfo() , mIsNew(false) + , mCanClose(false) { } @@ -1559,7 +1561,7 @@ void LLPanelClassifiedEdit::resetControls() bool LLPanelClassifiedEdit::canClose() { - return isValidName(); + return mCanClose; } void LLPanelClassifiedEdit::sendUpdate() @@ -1676,12 +1678,23 @@ void LLPanelClassifiedEdit::onChange() void LLPanelClassifiedEdit::onSaveClick() { + mCanClose = false; + if(!isValidName()) { notifyInvalidName(); return; } + if(isNew()) + { + if(gStatusBar->getBalance() < getPriceForListing()) + { + LLNotificationsUtil::add("ClassifiedInsufficientFunds"); + return; + } + } + mCanClose = true; sendUpdate(); resetDirty(); } diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index 10fdf60bbe..e46806f576 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -340,6 +340,7 @@ protected: private: bool mIsNew; + bool mCanClose; }; #endif // LL_LLPANELCLASSIFIED_H diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index fff2575893..569d3001bf 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -151,6 +151,11 @@ BOOL LLPanelGroup::postBuild() button->setVisible(true); button->setEnabled(false); + button = getChild("btn_call"); + button->setClickedCallback(onBtnGroupCallClicked, this); + + button = getChild("btn_chat"); + button->setClickedCallback(onBtnGroupChatClicked, this); button = getChild("btn_join"); button->setVisible(false); @@ -215,6 +220,8 @@ void LLPanelGroup::reposButtons() reposButton("btn_create"); reposButton("btn_refresh"); reposButton("btn_cancel"); + reposButton("btn_chat"); + reposButton("btn_call"); } void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent ) @@ -262,6 +269,18 @@ void LLPanelGroup::onBtnApply(void* user_data) self->apply(); } +void LLPanelGroup::onBtnGroupCallClicked(void* user_data) +{ + LLPanelGroup* self = static_cast(user_data); + self->callGroup(); +} + +void LLPanelGroup::onBtnGroupChatClicked(void* user_data) +{ + LLPanelGroup* self = static_cast(user_data); + self->chatGroup(); +} + void LLPanelGroup::onBtnJoin() { lldebugs << "joining group: " << mID << llendl; @@ -349,6 +368,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) LLButton* button_create = findChild("btn_create"); LLButton* button_join = findChild("btn_join"); LLButton* button_cancel = findChild("btn_cancel"); + LLButton* button_call = findChild("btn_call"); + LLButton* button_chat = findChild("btn_chat"); bool is_null_group_id = group_id == LLUUID::null; @@ -362,6 +383,11 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(button_cancel) button_cancel->setVisible(!is_null_group_id); + if(button_call) + button_call->setVisible(!is_null_group_id); + if(button_chat) + button_chat->setVisible(!is_null_group_id); + getChild("prepend_founded_by")->setVisible(!is_null_group_id); LLAccordionCtrl* tab_ctrl = findChild("group_accordion"); @@ -393,12 +419,17 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(tab_land->getDisplayChildren()) tab_land->changeOpenClose(tab_land->getDisplayChildren()); - tab_roles->canOpenClose(false); - tab_notices->canOpenClose(false); - tab_land->canOpenClose(false); + tab_roles->setVisible(false); + tab_notices->setVisible(false); + tab_land->setVisible(false); getChild("group_name")->setVisible(false); getChild("group_name_editor")->setVisible(true); + + if(button_call) + button_call->setVisible(false); + if(button_chat) + button_chat->setVisible(false); } else { @@ -413,19 +444,29 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(tab_land->getDisplayChildren()) tab_land->changeOpenClose(tab_land->getDisplayChildren()); } + + LLGroupData agent_gdatap; + bool is_member = gAgent.getGroupData(mID,agent_gdatap); - tab_roles->canOpenClose(true); - tab_notices->canOpenClose(true); - tab_land->canOpenClose(true); + tab_roles->setVisible(is_member); + tab_notices->setVisible(is_member); + tab_land->setVisible(is_member); getChild("group_name")->setVisible(true); getChild("group_name_editor")->setVisible(false); + + if(button_apply) + button_apply->setVisible(is_member); + if(button_call) + button_call->setVisible(is_member); + if(button_chat) + button_chat->setVisible(is_member); } reposButtons(); } -bool LLPanelGroup::apply(LLPanelGroupTab* tab) +bool LLPanelGroup::apply(LLPanelGroupTab* tab) { if(!tab) return false; @@ -468,12 +509,17 @@ void LLPanelGroup::draw() childEnable("btn_refresh"); } - bool enable = false; - std::string mesg; - for(std::vector::iterator it = mTabs.begin();it!=mTabs.end();++it) - enable = enable || (*it)->needsApply(mesg); + LLButton* button_apply = findChild("btn_apply"); + + if(button_apply && button_apply->getVisible()) + { + bool enable = false; + std::string mesg; + for(std::vector::iterator it = mTabs.begin();it!=mTabs.end();++it) + enable = enable || (*it)->needsApply(mesg); - childSetEnabled("btn_apply", enable); + childSetEnabled("btn_apply", enable); + } } void LLPanelGroup::refreshData() @@ -488,6 +534,15 @@ void LLPanelGroup::refreshData() mRefreshTimer.setTimerExpirySec(5); } +void LLPanelGroup::callGroup() +{ + LLGroupActions::startCall(getID()); +} + +void LLPanelGroup::chatGroup() +{ + LLGroupActions::startIM(getID()); +} void LLPanelGroup::showNotice(const std::string& subject, const std::string& message, diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index f6aefdb676..7ea5e67b44 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -74,6 +74,8 @@ public: bool apply(); void refreshData(); + void callGroup(); + void chatGroup(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -103,6 +105,8 @@ protected: static void onBtnApply(void*); static void onBtnRefresh(void*); + static void onBtnGroupCallClicked(void*); + static void onBtnGroupChatClicked(void*); void reposButton(const std::string& name); void reposButtons(); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 31dfdde887..21b253223f 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -580,7 +580,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) } } - mComboActiveTitle->resetDirty(); } // If this was just a titles update, we are done. @@ -595,8 +594,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) { mCtrlShowInGroupList->set(gdatap->mShowInList); mCtrlShowInGroupList->setEnabled(mAllowEdit && can_change_ident); - mCtrlShowInGroupList->resetDirty(); - } if (mComboMature) { @@ -610,19 +607,16 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) } mComboMature->setEnabled(mAllowEdit && can_change_ident); mComboMature->setVisible( !gAgent.isTeen() ); - mComboMature->resetDirty(); } if (mCtrlOpenEnrollment) { mCtrlOpenEnrollment->set(gdatap->mOpenEnrollment); mCtrlOpenEnrollment->setEnabled(mAllowEdit && can_change_member_opts); - mCtrlOpenEnrollment->resetDirty(); } if (mCtrlEnrollmentFee) { mCtrlEnrollmentFee->set(gdatap->mMembershipFee > 0); mCtrlEnrollmentFee->setEnabled(mAllowEdit && can_change_member_opts); - mCtrlEnrollmentFee->resetDirty(); } if (mSpinEnrollmentFee) @@ -632,7 +626,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) mSpinEnrollmentFee->setEnabled( mAllowEdit && (fee > 0) && can_change_member_opts); - mSpinEnrollmentFee->resetDirty(); } if (mCtrlReceiveNotices) { @@ -641,7 +634,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) { mCtrlReceiveNotices->setEnabled(mAllowEdit); } - mCtrlReceiveNotices->resetDirty(); } @@ -665,7 +657,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if (mEditCharter) { mEditCharter->setText(gdatap->mCharter); - mEditCharter->resetDirty(); } if (mListVisibleMembers) @@ -693,6 +684,8 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) mListVisibleMembers->addElement(row); } } + + resetDirty(); } void LLPanelGroupGeneral::updateMembers() diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 6210973dae..45fc3d4688 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -614,7 +614,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject, mViewInventoryIcon->setVisible(TRUE); std::stringstream ss; - ss << " " << inventory_name; + ss << " " << LLViewerInventoryItem::getDisplayName(inventory_name); mViewInventoryName->setText(ss.str()); mBtnOpenAttachment->setEnabled(TRUE); diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 29b647415c..0e55ff3214 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -460,17 +460,8 @@ LLPanelGroupSubTab::~LLPanelGroupSubTab() { } -BOOL LLPanelGroupSubTab::postBuild() -{ - // Hook up the search widgets. - bool recurse = true; - mSearchEditor = getChild("filter_input", recurse); - - if (!mSearchEditor) - return FALSE; - - mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::setSearchFilter, this, _2)); - +BOOL LLPanelGroupSubTab::postBuildSubTab(LLView* root) +{ // Get icons for later use. mActionIcons.clear(); @@ -488,6 +479,19 @@ BOOL LLPanelGroupSubTab::postBuild() { mActionIcons["partial"] = getString("power_partial_icon"); } + return TRUE; +} + +BOOL LLPanelGroupSubTab::postBuild() +{ + // Hook up the search widgets. + bool recurse = true; + mSearchEditor = getChild("filter_input", recurse); + + if (!mSearchEditor) + return FALSE; + + mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::setSearchFilter, this, _2)); return LLPanelGroupTab::postBuild(); } @@ -567,7 +571,6 @@ bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action) void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl, U64 allowed_by_some, U64 allowed_by_all, - icon_map_t& icons, LLUICtrl::commit_callback_t commit_callback, BOOL show_all, BOOL filter, @@ -588,7 +591,6 @@ void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl, allowed_by_some, allowed_by_all, (*ras_it), - icons, commit_callback, show_all, filter, @@ -600,7 +602,6 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, U64 allowed_by_some, U64 allowed_by_all, LLRoleActionSet* action_set, - icon_map_t& icons, LLUICtrl::commit_callback_t commit_callback, BOOL show_all, BOOL filter, @@ -614,26 +615,26 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, LLSD row; row["columns"][0]["column"] = "icon"; - icon_map_t::iterator iter = icons.find("folder"); - if (iter != icons.end()) + row["columns"][0]["type"] = "icon"; + + icon_map_t::iterator iter = mActionIcons.find("folder"); + if (iter != mActionIcons.end()) { - row["columns"][0]["type"] = "icon"; row["columns"][0]["value"] = (*iter).second; } row["columns"][1]["column"] = "action"; + row["columns"][1]["type"] = "text"; row["columns"][1]["value"] = action_set->mActionSetData->mName; row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][1]["font"]["style"] = "BOLD"; + LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData); - LLScrollListText* name_textp = dynamic_cast(title_row->getColumn(1)); + LLScrollListText* name_textp = dynamic_cast(title_row->getColumn(2)); //?? I have no idea fix getColumn(1) return column spacer... if (name_textp) name_textp->setFontStyle(LLFontGL::BOLD); - - bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true; std::vector::iterator ra_it = action_set->mActions.begin(); @@ -686,8 +687,8 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, { if (show_full_strength) { - icon_map_t::iterator iter = icons.find("full"); - if (iter != icons.end()) + icon_map_t::iterator iter = mActionIcons.find("full"); + if (iter != mActionIcons.end()) { row["columns"][column_index]["column"] = "checkbox"; row["columns"][column_index]["type"] = "icon"; @@ -697,8 +698,8 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, } else { - icon_map_t::iterator iter = icons.find("partial"); - if (iter != icons.end()) + icon_map_t::iterator iter = mActionIcons.find("partial"); + if (iter != mActionIcons.end()) { row["columns"][column_index]["column"] = "checkbox"; row["columns"][column_index]["type"] = "icon"; @@ -792,6 +793,8 @@ LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab() BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) { + LLPanelGroupSubTab::postBuildSubTab(root); + // Upcast parent so we can ask it for sibling controls. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root; @@ -888,7 +891,6 @@ void LLPanelGroupMembersSubTab::handleMemberSelect() buildActionsList(mAllowedActionsList, allowed_by_some, allowed_by_all, - mActionIcons, NULL, FALSE, FALSE, @@ -1211,7 +1213,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id, buildActionsList(mAllowedActionsList, powers_some_have, powers_all_have, - mActionIcons, NULL, FALSE, FALSE, @@ -1684,6 +1685,8 @@ LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab() BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root) { + LLPanelGroupSubTab::postBuildSubTab(root); + // Upcast parent so we can ask it for sibling controls. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root; @@ -1994,7 +1997,6 @@ void LLPanelGroupRolesSubTab::handleRoleSelect() buildActionsList(mAllowedActionsList, rd.mRolePowers, 0LL, - mActionIcons, boost::bind(&LLPanelGroupRolesSubTab::handleActionCheck, this, _1, false), TRUE, FALSE, @@ -2381,6 +2383,8 @@ LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab() BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root) { + LLPanelGroupSubTab::postBuildSubTab(root); + // Upcast parent so we can ask it for sibling controls. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root; @@ -2448,7 +2452,6 @@ void LLPanelGroupActionsSubTab::update(LLGroupChange gc) buildActionsList(mActionList, GP_ALL_POWERS, GP_ALL_POWERS, - mActionIcons, NULL, FALSE, TRUE, diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index bb3c9096cf..2f81900e60 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -108,7 +108,7 @@ public: virtual BOOL postBuild(); // This allows sub-tabs to collect child widgets from a higher level in the view hierarchy. - virtual BOOL postBuildSubTab(LLView* root) { return TRUE; } + virtual BOOL postBuildSubTab(LLView* root); virtual void setSearchFilter( const std::string& filter ); @@ -117,10 +117,15 @@ public: // Helper functions bool matchesActionSearchFilter(std::string action); + + + void setFooterEnabled(BOOL enable); + + virtual void setGroupID(const LLUUID& id); +protected: void buildActionsList(LLScrollListCtrl* ctrl, U64 allowed_by_some, U64 allowed_by_all, - icon_map_t& icons, LLUICtrl::commit_callback_t commit_callback, BOOL show_all, BOOL filter, @@ -129,15 +134,11 @@ public: U64 allowed_by_some, U64 allowed_by_all, LLRoleActionSet* action_set, - icon_map_t& icons, LLUICtrl::commit_callback_t commit_callback, BOOL show_all, BOOL filter, BOOL is_owner_role); - void setFooterEnabled(BOOL enable); - - virtual void setGroupID(const LLUUID& id); protected: LLPanel* mHeader; LLPanel* mFooter; diff --git a/indra/newview/llpanelhome.cpp b/indra/newview/llpanelhome.cpp index 92b6d2f619..713d2d79b4 100644 --- a/indra/newview/llpanelhome.cpp +++ b/indra/newview/llpanelhome.cpp @@ -37,7 +37,7 @@ #include "llmediactrl.h" #include "llviewerhome.h" -static LLRegisterPanelClassWrapper t_people("panel_sidetray_home"); +static LLRegisterPanelClassWrapper t_home("panel_sidetray_home"); LLPanelHome::LLPanelHome() : LLPanel(), diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 279818d52f..b1cdb4d81f 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -46,6 +46,7 @@ #include "llimview.h" #include "llvoicechannel.h" #include "llsidetray.h" +#include "llspeakers.h" #include "lltrans.h" void LLPanelChatControlPanel::onCallButtonClicked() @@ -70,9 +71,9 @@ void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::E void LLPanelChatControlPanel::updateButtons(bool is_call_started) { - childSetVisible("end_call_btn", is_call_started); - childSetVisible("voice_ctrls_btn", is_call_started); - childSetVisible("call_btn", ! is_call_started); + childSetVisible("end_call_btn_panel", is_call_started); + childSetVisible("voice_ctrls_btn_panel", is_call_started); + childSetVisible("call_btn_panel", ! is_call_started); } LLPanelChatControlPanel::~LLPanelChatControlPanel() @@ -302,7 +303,7 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) { LLPanelChatControlPanel::setSessionId(session_id); - mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id); + mGroupID = session_id; // for group and Ad-hoc chat we need to include agent into list if(!mParticipantList) diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp index 920fca66f2..6a4c909759 100644 --- a/indra/newview/llpanellandaudio.cpp +++ b/indra/newview/llpanellandaudio.cpp @@ -37,6 +37,7 @@ // viewer includes #include "llmimetypes.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "lluictrlfactory.h" // library includes @@ -83,8 +84,14 @@ BOOL LLPanelLandAudio::postBuild() mCheckSoundLocal = getChild("check sound local"); childSetCommitCallback("check sound local", onCommitAny, this); - mRadioVoiceChat = getChild("parcel_voice_channel"); - childSetCommitCallback("parcel_voice_channel", onCommitAny, this); + mCheckParcelEnableVoice = getChild("parcel_enable_voice_channel"); + childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this); + + // This one is always disabled so no need for a commit callback + mCheckEstateDisabledVoice = getChild("parcel_enable_voice_channel_is_estate_disabled"); + + mCheckParcelVoiceLocal = getChild("parcel_enable_voice_channel_local"); + childSetCommitCallback("parcel_enable_voice_channel_local", onCommitAny, this); mMusicURLEdit = getChild("music_url"); childSetCommitCallback("music_url", onCommitAny, this); @@ -118,19 +125,33 @@ void LLPanelLandAudio::refresh() mMusicUrlCheck->set( parcel->getObscureMusic() ); mMusicUrlCheck->setEnabled( can_change_media ); - if(parcel->getParcelFlagAllowVoice()) + bool allow_voice = parcel->getParcelFlagAllowVoice(); + + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if (region && region->isVoiceEnabled()) { - if(parcel->getParcelFlagUseEstateVoiceChannel()) - mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatEstate); - else - mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatPrivate); + mCheckEstateDisabledVoice->setVisible(false); + + mCheckParcelEnableVoice->setVisible(true); + mCheckParcelEnableVoice->setEnabled( can_change_media ); + mCheckParcelEnableVoice->set(allow_voice); + + mCheckParcelVoiceLocal->setEnabled( can_change_media && allow_voice ); } else { - mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable); + // Voice disabled at estate level, overrides parcel settings + // Replace the parcel voice checkbox with a disabled one + // labelled with an explanatory message + mCheckEstateDisabledVoice->setVisible(true); + + mCheckParcelEnableVoice->setVisible(false); + mCheckParcelEnableVoice->setEnabled(false); + mCheckParcelVoiceLocal->setEnabled(false); } - mRadioVoiceChat->setEnabled( can_change_media ); + mCheckParcelEnableVoice->set(allow_voice); + mCheckParcelVoiceLocal->set(!parcel->getParcelFlagUseEstateVoiceChannel()); mMusicURLEdit->setText(parcel->getMusicURL()); mMusicURLEdit->setEnabled( can_change_media ); @@ -149,30 +170,11 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata) // Extract data from UI BOOL sound_local = self->mCheckSoundLocal->get(); - int voice_setting = self->mRadioVoiceChat->getSelectedIndex(); std::string music_url = self->mMusicURLEdit->getText(); U8 obscure_music = self->mMusicUrlCheck->get(); - - BOOL voice_enabled; - BOOL voice_estate_chan; - - switch(voice_setting) - { - default: - case kRadioVoiceChatEstate: - voice_enabled = TRUE; - voice_estate_chan = TRUE; - break; - case kRadioVoiceChatPrivate: - voice_enabled = TRUE; - voice_estate_chan = FALSE; - break; - case kRadioVoiceChatDisable: - voice_enabled = FALSE; - voice_estate_chan = FALSE; - break; - } + BOOL voice_enabled = self->mCheckParcelEnableVoice->get(); + BOOL voice_estate_chan = !self->mCheckParcelVoiceLocal->get(); // Remove leading/trailing whitespace (common when copying/pasting) LLStringUtil::trim(music_url); diff --git a/indra/newview/llpanellandaudio.h b/indra/newview/llpanellandaudio.h index de5da95fa4..19766a40b6 100644 --- a/indra/newview/llpanellandaudio.h +++ b/indra/newview/llpanellandaudio.h @@ -52,7 +52,9 @@ private: private: LLCheckBoxCtrl* mCheckSoundLocal; - LLRadioGroup* mRadioVoiceChat; + LLCheckBoxCtrl* mCheckParcelEnableVoice; + LLCheckBoxCtrl* mCheckEstateDisabledVoice; + LLCheckBoxCtrl* mCheckParcelVoiceLocal; LLLineEditor* mMusicURLEdit; LLCheckBoxCtrl* mMusicUrlCheck; diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 597b8bdb2d..9654e17659 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -185,6 +185,13 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) region_z = llround(mPosRegion.mV[VZ]); } + LLSD info; + info["update_verbs"] = true; + info["global_x"] = parcel_data.global_x; + info["global_y"] = parcel_data.global_y; + info["global_z"] = parcel_data.global_z; + notifyParent(info); + if (mInfoType == CREATE_LANDMARK) { if (parcel_data.name.empty()) diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 30acf37f82..47feef496a 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -35,6 +35,7 @@ #include "llbutton.h" #include "llfloaterreg.h" +#include "llnotificationsutil.h" #include "llsdutil.h" #include "llsdutil_math.h" #include "llregionhandle.h" @@ -304,6 +305,29 @@ void LLLandmarksPanel::updateShowFolderState() ); } +void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus) +{ + if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus)) + { + return; + } + + if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus)) + { + return; + } + + if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus)) + { + return; + } + + if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus)) + { + return; + } +} + ////////////////////////////////////////////////////////////////////////// // PROTECTED METHODS ////////////////////////////////////////////////////////////////////////// @@ -349,6 +373,36 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL; } +LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, + const std::string& tab_name, + const LLUUID& obj_id, + BOOL take_keyboard_focus) const +{ + if (!inventory_list) + return NULL; + + LLFolderView* folder_view = inventory_list->getRootFolder(); + + LLFolderViewItem* item = folder_view->getItemByID(obj_id); + if (!item) + return NULL; + + LLAccordionCtrlTab* tab = getChild(tab_name); + if (!tab->isExpanded()) + { + tab->changeOpenClose(false); + } + + folder_view->setSelection(item, FALSE, take_keyboard_focus); + + LLAccordionCtrl* accordion = getChild("landmarks_accordion"); + LLRect screen_rc; + localRectToScreen(item->getRect(), &screen_rc); + accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); + + return item; +} + void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate) { if(!panel) return; @@ -632,8 +686,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); if(landmark) { - LLSideTray::getInstance()->showPanel("panel_places", - LLSD().with("type", "landmark").with("id",landmark->getUUID())); + LLNotificationsUtil::add("LandmarkAlreadyExists"); } else { diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 569739237d..96b790844c 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -73,6 +73,11 @@ public: */ void updateShowFolderState(); + /** + * Selects item with "obj_id" in one of accordion tabs. + */ + void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus); + protected: /** * @return true - if current selected panel is not null and selected item is a landmark @@ -81,6 +86,17 @@ protected: bool isReceivedFolderSelected() const; void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb); LLFolderViewItem* getCurSelectedItem() const; + + /** + * Selects item with "obj_id" in "inventory_list" and scrolls accordion + * scrollbar to show the item. + * Returns pointer to the item if it is found in "inventory_list", otherwise NULL. + */ + LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, + const std::string& tab_name, + const LLUUID& obj_id, + BOOL take_keyboard_focus) const; + void updateSortOrder(LLInventoryPanel* panel, bool byDate); //LLRemoteParcelInfoObserver interface diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e74a39c85c..a5a61f0c7b 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -51,6 +51,8 @@ #include "llviewermenu.h" #include "llviewertexturelist.h" +const std::string FILTERS_FILENAME("filters.xml"); + static LLRegisterPanelClassWrapper t_inventory("panel_main_inventory"); void on_file_loaded_for_save(BOOL success, @@ -160,7 +162,7 @@ BOOL LLPanelMainInventory::postBuild() // Now load the stored settings from disk, if available. std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl; llifstream file(filterSaveName.str()); LLSD savedFilterState; @@ -230,7 +232,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) } std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); llofstream filtersFile(filterSaveName.str()); if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) { diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 6a61e0f02f..d17c287cc7 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -73,7 +73,7 @@ #include "pipeline.h" #include "llviewercontrol.h" #include "lluictrlfactory.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "lldrawpool.h" @@ -682,7 +682,7 @@ void LLPanelObject::getState( ) if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) { selected_item = MI_SCULPT; - LLFirstUse::useSculptedPrim(); + //LLFirstUse::useSculptedPrim(); } diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 43366ef814..d4376550d6 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -445,7 +445,7 @@ bool remove_task_inventory_callback(const LLSD& notification, const LLSD& respon } // helper for remove -// ! REFACTOR ! two_uuids_list_t is also defined in llinevntorybridge.h, but differently. +// ! REFACTOR ! two_uuids_list_t is also defined in llinventorybridge.h, but differently. typedef std::pair > panel_two_uuids_list_t; typedef std::pair remove_data_t; BOOL LLTaskInvFVBridge::removeItem() diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 8e14074de1..fd5ce7a46d 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentwearables.h" +#include "llappearancemgr.h" #include "llbutton.h" #include "llfloaterreg.h" @@ -44,6 +45,8 @@ #include "llinventoryfunctions.h" #include "llinventorypanel.h" #include "lllandmark.h" +#include "lllineeditor.h" +#include "llmodaldialog.h" #include "llsidepanelappearance.h" #include "llsidetray.h" #include "lltabcontainer.h" @@ -61,12 +64,75 @@ static LLRegisterPanelClassWrapper t_inventory("panel_outfits_inventory"); bool LLPanelOutfitsInventory::sShowDebugEditor = false; +class LLOutfitSaveAsDialog : public LLModalDialog +{ +private: + std::string mItemName; + std::string mTempItemName; + + boost::signals2::signal mSaveAsSignal; + +public: + LLOutfitSaveAsDialog( const LLSD& key ) + : LLModalDialog( key ), + mTempItemName(key.asString()) + { + } + + BOOL postBuild() + { + getChild("Save")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onSave, this )); + getChild("Cancel")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onCancel, this )); + + childSetTextArg("name ed", "[DESC]", mTempItemName); + return TRUE; + } + + void setSaveAsCommit( const boost::signals2::signal::slot_type& cb ) + { + mSaveAsSignal.connect(cb); + } + + virtual void onOpen(const LLSD& key) + { + LLLineEditor* edit = getChild("name ed"); + if (edit) + { + edit->setFocus(TRUE); + edit->selectAll(); + } + } + + void onSave() + { + mItemName = childGetValue("name ed").asString(); + LLStringUtil::trim(mItemName); + if( !mItemName.empty() ) + { + mSaveAsSignal(mItemName); + closeFloater(); // destroys this object + } + } + + void onCancel() + { + closeFloater(); // destroys this object + } +}; + LLPanelOutfitsInventory::LLPanelOutfitsInventory() : mActivePanel(NULL), mParent(NULL) { mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); + + static bool registered_dialog = false; + if (!registered_dialog) + { + LLFloaterReg::add("outfit_save_as", "floater_outfit_save_as.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + registered_dialog = true; + } } LLPanelOutfitsInventory::~LLPanelOutfitsInventory() @@ -84,6 +150,14 @@ BOOL LLPanelOutfitsInventory::postBuild() return TRUE; } +// virtual +void LLPanelOutfitsInventory::onOpen(const LLSD& key) +{ + // Make sure we know which tab is selected, update the filter, + // and update verbs. + onTabChange(); +} + void LLPanelOutfitsInventory::updateVerbs() { if (mParent) @@ -94,6 +168,7 @@ void LLPanelOutfitsInventory::updateVerbs() if (mListCommands) { mListCommands->childSetVisible("look_edit_btn",sShowDebugEditor); + updateListCommands(); } } @@ -168,15 +243,36 @@ void LLPanelOutfitsInventory::onEdit() { } -void LLPanelOutfitsInventory::onNew() +void LLPanelOutfitsInventory::onSave() +{ + std::string outfit_name; + + if (!LLAppearanceManager::getInstance()->getBaseOutfitName(outfit_name)) + { + outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); + } + + LLOutfitSaveAsDialog* save_as_dialog = LLFloaterReg::showTypedInstance("outfit_save_as", LLSD(outfit_name), TRUE); + if (save_as_dialog) + { + save_as_dialog->setSaveAsCommit(boost::bind(&LLPanelOutfitsInventory::onSaveCommit, this, _1 )); + } +} + +void LLPanelOutfitsInventory::onSaveCommit(const std::string& outfit_name) { - const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); + LLSD key; + LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + + if (mAppearanceTabs) + { + mAppearanceTabs->selectTabByName("outfitslist_tab"); + } } void LLPanelOutfitsInventory::onSelectionChange(const std::deque &items, BOOL user_action) { - updateListCommands(); updateVerbs(); if (getRootFolder()->needsAutoRename() && items.size()) { @@ -264,9 +360,12 @@ void LLPanelOutfitsInventory::updateListCommands() { bool trash_enabled = isActionEnabled("delete"); bool wear_enabled = isActionEnabled("wear"); + bool make_outfit_enabled = isActionEnabled("make_outfit"); mListCommands->childSetEnabled("trash_btn", trash_enabled); mListCommands->childSetEnabled("wear_btn", wear_enabled); + mListCommands->childSetVisible("wear_btn", wear_enabled); + mListCommands->childSetEnabled("make_outfit_btn", make_outfit_enabled); } void LLPanelOutfitsInventory::onGearButtonClick() @@ -276,7 +375,7 @@ void LLPanelOutfitsInventory::onGearButtonClick() void LLPanelOutfitsInventory::onAddButtonClick() { - onNew(); + onSave(); } void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) @@ -303,6 +402,8 @@ void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); + updateListCommands(); + updateVerbs(); } void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) @@ -313,7 +414,7 @@ void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) const std::string command_name = userdata.asString(); if (command_name == "new") { - onNew(); + onSave(); } if (command_name == "edit") { @@ -323,6 +424,7 @@ void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) { onWearButtonClick(); } + // Note: This option has been removed from the gear menu. if (command_name == "add") { onAdd(); @@ -343,20 +445,22 @@ void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) { onClipboardAction("delete"); } + updateListCommands(); + updateVerbs(); } BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { const std::string command_name = userdata.asString(); - if (command_name == "delete") + if (command_name == "delete" || command_name == "remove") { BOOL can_delete = FALSE; LLFolderView *folder = getActivePanel()->getRootFolder(); if (folder) { - can_delete = TRUE; std::set selection_set; folder->getSelectionList(selection_set); + can_delete = (selection_set.size() > 0); for (std::set::iterator iter = selection_set.begin(); iter != selection_set.end(); ++iter) @@ -375,9 +479,9 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) LLFolderView *folder = getActivePanel()->getRootFolder(); if (folder) { - can_delete = TRUE; std::set selection_set; folder->getSelectionList(selection_set); + can_delete = (selection_set.size() > 0); for (std::set::iterator iter = selection_set.begin(); iter != selection_set.end(); ++iter) @@ -391,10 +495,27 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) } return FALSE; } + if (command_name == "rename" || + command_name == "delete_outfit") + { + return (getCorrectListenerForAction() != NULL) && hasItemsSelected(); + } + + if (command_name == "wear") + { + const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab"); + if (!is_my_outfits) + { + return FALSE; + } + } + if (command_name == "make_outfit") + { + return TRUE; + } + if (command_name == "edit" || - command_name == "wear" || - command_name == "add" || - command_name == "remove" + command_name == "add" ) { return (getCorrectListenerForAction() != NULL); @@ -402,6 +523,19 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return TRUE; } +bool LLPanelOutfitsInventory::hasItemsSelected() +{ + bool has_items_selected = false; + LLFolderView *folder = getActivePanel()->getRootFolder(); + if (folder) + { + std::set selection_set; + folder->getSelectionList(selection_set); + has_items_selected = (selection_set.size() > 0); + } + return has_items_selected; +} + bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept) { *accept = ACCEPT_NO; @@ -425,17 +559,15 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy void LLPanelOutfitsInventory::initTabPanels() { mTabPanels.resize(2); + + LLInventoryPanel *cof_panel = getChild("cof_tab"); + cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mTabPanels[0] = cof_panel; - LLInventoryPanel *myoutfits_panel = getChild("outfitslist_accordionpanel"); + LLInventoryPanel *myoutfits_panel = getChild("outfitslist_tab"); myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY); myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mTabPanels[0] = myoutfits_panel; - mActivePanel = myoutfits_panel; - - - LLInventoryPanel *cof_panel = getChild("cof_accordionpanel"); - cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mTabPanels[1] = cof_panel; + mTabPanels[1] = myoutfits_panel; for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); iter != mTabPanels.end(); @@ -447,6 +579,7 @@ void LLPanelOutfitsInventory::initTabPanels() mAppearanceTabs = getChild("appearance_tabs"); mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this)); + mActivePanel = (LLInventoryPanel*)mAppearanceTabs->getCurrentPanel(); } void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque &items, BOOL user_action) @@ -479,9 +612,7 @@ void LLPanelOutfitsInventory::onTabChange() return; } mActivePanel->setFilterSubString(mFilterSubString); - - bool is_my_outfits = (mActivePanel->getName() == "outfitslist_accordionpanel"); - mListCommands->childSetEnabled("make_outfit_btn", is_my_outfits); + updateVerbs(); } LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel() diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 1e084750a0..76110e2a3f 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -53,12 +53,15 @@ public: virtual ~LLPanelOutfitsInventory(); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); void onSearchEdit(const std::string& string); void onAdd(); void onRemove(); void onEdit(); - void onNew(); + void onSave(); + + void onSaveCommit(const std::string& item_name); void onSelectionChange(const std::deque &items, BOOL user_action); void onSelectorButtonClicked(); @@ -114,6 +117,7 @@ protected: BOOL isActionEnabled(const LLSD& command_name); void onCustomAction(const LLSD& command_name); bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept); + bool hasItemsSelected(); private: LLPanel* mListCommands; LLMenuGL* mMenuGearDefault; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index e14a5778ad..c14b282488 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -35,6 +35,7 @@ // libs #include "llfloaterreg.h" #include "llmenugl.h" +#include "llnotificationsutil.h" #include "llfiltereditor.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" @@ -531,10 +532,10 @@ BOOL LLPanelPeople::postBuild() friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this)); friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this)); - mOnlineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOnlineFriendList)); - mAllFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mAllFriendList)); - mNearbyList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mNearbyList)); - mRecentList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mRecentList)); + mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); + mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); + mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); + mRecentList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList)); mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList)); @@ -750,7 +751,6 @@ void LLPanelPeople::updateButtons() LLPanel* groups_panel = mTabContainer->getCurrentPanel(); groups_panel->childSetEnabled("activate_btn", item_selected && !cur_group_active); // "none" or a non-active group selected - groups_panel->childSetEnabled("plus_btn", item_selected); groups_panel->childSetEnabled("minus_btn", item_selected && selected_id.notNull()); } else @@ -1005,12 +1005,15 @@ void LLPanelPeople::onTabSelected(const LLSD& param) mFilterEditor->setLabel(getString("people_filter_label")); } -void LLPanelPeople::onAvatarListDoubleClicked(LLAvatarList* list) +void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) { - LLUUID clicked_id = list->getSelectedUUID(); - - if (clicked_id.isNull()) + LLAvatarListItem* item = dynamic_cast(ctrl); + if(!item) + { return; + } + + LLUUID clicked_id = item->getAvatarId(); #if 0 // SJB: Useful for testing, but not currently functional or to spec LLAvatarActions::showProfile(clicked_id); @@ -1138,6 +1141,12 @@ void LLPanelPeople::onAvatarPicked( void LLPanelPeople::onGroupPlusButtonClicked() { + if (!gAgent.canJoinGroups()) + { + LLNotificationsUtil::add("JoinedTooManyGroups"); + return; + } + LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); if (!plus_menu) return; diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index da2c0e368c..7580fdbeef 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -109,7 +109,7 @@ private: void onNearbyViewSortButtonClicked(); void onFriendsViewSortButtonClicked(); void onGroupsViewSortButtonClicked(); - void onAvatarListDoubleClicked(LLAvatarList* list); + void onAvatarListDoubleClicked(LLUICtrl* ctrl); void onAvatarListCommitted(LLAvatarList* list); void onGroupPlusButtonClicked(); void onGroupMinusButtonClicked(); diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 7a4dd3569d..5ac0587550 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -35,24 +35,30 @@ // profile. #include "llviewerprecompiledheaders.h" -#include "llpanel.h" + +#include "llpanelpick.h" + #include "message.h" -#include "llagent.h" -#include "llagentpicksinfo.h" + +#include "llparcel.h" + #include "llbutton.h" +#include "llfloaterreg.h" #include "lliconctrl.h" #include "lllineeditor.h" -#include "llparcel.h" -#include "llviewerparcelmgr.h" +#include "llpanel.h" +#include "llscrollcontainer.h" #include "lltexteditor.h" + +#include "llagent.h" +#include "llagentpicksinfo.h" +#include "llavatarpropertiesprocessor.h" +#include "llfloaterworldmap.h" #include "lltexturectrl.h" #include "lluiconstants.h" +#include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llworldmap.h" -#include "llfloaterworldmap.h" -#include "llfloaterreg.h" -#include "llavatarpropertiesprocessor.h" -#include "llpanelpick.h" #define XML_PANEL_EDIT_PICK "panel_edit_pick.xml" @@ -93,6 +99,10 @@ LLPanelPickInfo::LLPanelPickInfo() , mPickId(LLUUID::null) , mParcelId(LLUUID::null) , mRequestedId(LLUUID::null) + , mScrollingPanelMinHeight(0) + , mScrollingPanelWidth(0) + , mScrollingPanel(NULL) + , mScrollContainer(NULL) { } @@ -146,9 +156,35 @@ BOOL LLPanelPickInfo::postBuild() childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this)); childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this)); + mScrollingPanel = getChild("scroll_content_panel"); + mScrollContainer = getChild("profile_scroll"); + + mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight(); + mScrollingPanelWidth = mScrollingPanel->getRect().getWidth(); + return TRUE; } +void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLPanel::reshape(width, height, called_from_parent); + + if (!mScrollContainer || !mScrollingPanel) + return; + + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + S32 scroll_height = mScrollContainer->getRect().getHeight(); + if (mScrollingPanelMinHeight >= scroll_height) + { + mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight); + } + else + { + mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height); + } +} + void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type) { if(APT_PICK_INFO != type) @@ -284,7 +320,6 @@ void LLPanelPickInfo::setPickName(const std::string& name) void LLPanelPickInfo::setPickDesc(const std::string& desc) { childSetValue(XML_DESC, desc); - updateContentPanelRect(); } void LLPanelPickInfo::setPickLocation(const std::string& location) @@ -292,31 +327,6 @@ void LLPanelPickInfo::setPickLocation(const std::string& location) childSetValue(XML_LOCATION, location); } -void LLPanelPickInfo::updateContentPanelRect() -{ - LLTextBox* desc = getChild(XML_DESC); - - S32 text_height = desc->getTextPixelHeight(); - LLRect text_rect = desc->getRect(); - - // let text-box height fit text height - text_rect.set(text_rect.mLeft, text_rect.mTop, text_rect.mRight, text_rect.mTop - text_height); - desc->setRect(text_rect); - desc->reshape(text_rect.getWidth(), text_rect.getHeight()); - // force reflow - desc->setText(desc->getText()); - - // bottom of description text-box will be bottom of content panel - desc->localRectToOtherView(desc->getLocalRect(), &text_rect, getChild("profile_scroll")); - - LLPanel* content_panel = getChild("scroll_content_panel"); - LLRect content_rect = content_panel->getRect(); - content_rect.set(content_rect.mLeft, content_rect.mTop, content_rect.mRight, text_rect.mBottom); - // Somehow setRect moves all elements down. - // Single reshape() updates rect and does not move anything. - content_panel->reshape(content_rect.getWidth(), content_rect.getHeight()); -} - void LLPanelPickInfo::onClickMap() { LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); @@ -438,7 +448,7 @@ BOOL LLPanelPickEdit::postBuild() { LLPanelPickInfo::postBuild(); - mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1)); + mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this)); LLLineEditor* line_edit = getChild("pick_name"); line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL); @@ -527,16 +537,14 @@ void LLPanelPickEdit::sendUpdate() } } +void LLPanelPickEdit::onSnapshotChanged() +{ + enableSaveButton(true); +} + void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl) { - if(isDirty()) - { - enableSaveButton(true); - } - else - { - enableSaveButton(false); - } + enableSaveButton(isDirty()); } void LLPanelPickEdit::resetData() @@ -603,10 +611,6 @@ void LLPanelPickEdit::initTexturePickerMouseEvents() mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1)); mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1)); - // *WORKAROUND: Needed for EXT-1625: enabling save button each time when picker is opened, even if - // texture wasn't changed (see Steve's comment). - mSnapshotCtrl->setMouseDownCallback(boost::bind(&LLPanelPickEdit::enableSaveButton, this, true)); - text_icon->setVisible(FALSE); } diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 12b5a116b4..4f27760a8d 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -43,6 +43,7 @@ class LLIconCtrl; class LLTextureCtrl; +class LLScrollContainer; class LLMessageSystem; class LLAvatarPropertiesObserver; @@ -69,6 +70,8 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); /** @@ -139,15 +142,6 @@ protected: virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } virtual LLVector3d& getPosGlobal() { return mPosGlobal; } - /** - * Reshapes content panel to fit all elements. - * - * Assume that description text-box is the last element of panel. - * Reshape text-box to fit text height and then reshape content panel to fit - * text-box bottom. EXT-1326 - */ - void updateContentPanelRect(); - /** * Callback for "Map" button, opens Map */ @@ -162,7 +156,11 @@ protected: protected: - LLTextureCtrl* mSnapshotCtrl; + S32 mScrollingPanelMinHeight; + S32 mScrollingPanelWidth; + LLScrollContainer* mScrollContainer; + LLPanel* mScrollingPanel; + LLTextureCtrl* mSnapshotCtrl; LLUUID mAvatarId; LLVector3d mPosGlobal; @@ -223,6 +221,11 @@ protected: */ void sendUpdate(); + /** + * Called when snapshot image changes. + */ + void onSnapshotChanged(); + /** * Callback for Pick snapshot, name and description changed event. */ diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 751705dd57..ada65c98a4 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -411,6 +411,7 @@ BOOL LLPanelPicks::postBuild() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar; plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("Picks.Plus.Enable", boost::bind(&LLPanelPicks::isActionEnabled, this, _2)); mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); return TRUE; @@ -430,6 +431,18 @@ void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param) } } +bool LLPanelPicks::isActionEnabled(const LLSD& userdata) const +{ + std::string command_name = userdata.asString(); + + if (command_name == "new_pick" && LLAgentPicksInfo::getInstance()->isPickLimitReached()) + { + return false; + } + + return true; +} + void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab) { if(!mPicksAccTab->getDisplayChildren()) @@ -652,7 +665,6 @@ void LLPanelPicks::updateButtons() if (getAvatarId() == gAgentID) { - childSetEnabled(XML_BTN_NEW, !LLAgentPicksInfo::getInstance()->isPickLimitReached()); childSetEnabled(XML_BTN_DELETE, has_selected); } diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 1b2e35ca46..3f757e482e 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -97,6 +97,7 @@ private: void onClickMap(); void onPlusMenuItemClicked(const LLSD& param); + bool isActionEnabled(const LLSD& userdata) const; void onListCommit(const LLFlatListView* f_list); void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 685104a8b1..b037674c37 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -449,6 +449,22 @@ void LLPanelPlaces::setItem(LLInventoryItem* item) } } +S32 LLPanelPlaces::notifyParent(const LLSD& info) +{ + if(info.has("update_verbs")) + { + if(mPosGlobal.isExactlyZero()) + { + mPosGlobal.setVec(info["global_x"], info["global_y"], info["global_z"]); + } + + updateVerbs(); + + return 1; + } + return LLPanel::notifyParent(info); +} + void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark) { if (!mLandmarkInfo) @@ -460,6 +476,8 @@ void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark) mLandmarkInfo->displayParcelInfo(region_id, mPosGlobal); mSaveBtn->setEnabled(TRUE); + + updateVerbs(); } void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_filter) @@ -824,6 +842,19 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) mPlaceProfile->setVisible(FALSE); } + else + { + LLLandmarksPanel* landmarks_panel = + dynamic_cast(mTabContainer->getPanelByName("Landmarks")); + if (landmarks_panel && mItem.notNull()) + { + // If a landmark info is being closed we open the landmarks tab + // and set this landmark selected. + mTabContainer->selectTabPanel(landmarks_panel); + + landmarks_panel->setItemSelected(mItem->getUUID(), TRUE); + } + } } } diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 5ee8704992..27b5911ebb 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -71,6 +71,12 @@ public: void setItem(LLInventoryItem* item); + LLInventoryItem* getItem() { return mItem; } + + std::string getPlaceInfoType() { return mPlaceInfoType; } + + /*virtual*/ S32 notifyParent(const LLSD& info); + private: void onLandmarkLoaded(LLLandmark* landmark); void onFilterEdit(const std::string& search_string, bool force_filter); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 5cc9c1951b..2dc3a62637 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -127,7 +127,11 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mScrollState = SCROLL_NONE; mPanelHandle.bind(this); + + mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout"); + mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); } + LLPanelPrimMediaControls::~LLPanelPrimMediaControls() { } @@ -156,8 +160,6 @@ BOOL LLPanelPrimMediaControls::postBuild() mSkipBackCtrl = getChild("skip_back"); mVolumeCtrl = getChild("media_volume"); mMuteBtn = getChild("media_mute_button"); - mVolumeUpCtrl = getChild("volume_up"); - mVolumeDownCtrl = getChild("volume_down"); mVolumeSliderCtrl = getChild("volume_slider"); mWhitelistIcon = getChild("media_whitelist_flag"); mSecureLockIcon = getChild("media_secure_lock_flag"); @@ -172,6 +174,7 @@ BOOL LLPanelPrimMediaControls::postBuild() LLStringUtil::convertToF32(getString("zoom_near_padding"), mZoomNearPadding); LLStringUtil::convertToF32(getString("zoom_medium_padding"), mZoomMediumPadding); LLStringUtil::convertToF32(getString("zoom_far_padding"), mZoomFarPadding); + LLStringUtil::convertToS32(getString("top_world_view_avoid_zone"), mTopWorldViewAvoidZone); // These are currently removed...but getChild creates a "dummy" widget. // This class handles them missing. @@ -207,11 +210,9 @@ BOOL LLPanelPrimMediaControls::postBuild() } mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this )); - mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout"); - mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); - + mCurrentZoom = ZOOM_NONE; - // clicks on HUD buttons do not remove keyboard focus from media + // clicks on buttons do not remove keyboard focus from media setIsChrome(TRUE); return TRUE; } @@ -336,8 +337,6 @@ void LLPanelPrimMediaControls::updateShape() mMediaAddressCtrl->setVisible(has_focus && !mini_controls); mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls); mVolumeCtrl->setVisible(false); - mVolumeUpCtrl->setVisible(false); - mVolumeDownCtrl->setVisible(false); mWhitelistIcon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false); // Disable zoom if HUD @@ -370,11 +369,9 @@ void LLPanelPrimMediaControls::updateShape() mSkipBackCtrl->setEnabled(has_focus && !mini_controls); mVolumeCtrl->setVisible(has_focus); - mVolumeUpCtrl->setVisible(has_focus); - mVolumeDownCtrl->setVisible(has_focus); mVolumeCtrl->setEnabled(has_focus); - mVolumeSliderCtrl->setEnabled(has_focus && mVolumeSliderVisible > 0); - mVolumeSliderCtrl->setVisible(has_focus && mVolumeSliderVisible > 0); + mVolumeSliderCtrl->setEnabled(has_focus && shouldVolumeSliderBeVisible()); + mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible()); mWhitelistIcon->setVisible(false); mSecureLockIcon->setVisible(false); @@ -414,21 +411,15 @@ void LLPanelPrimMediaControls::updateShape() // video vloume if(volume <= 0.0) { - mVolumeUpCtrl->setEnabled(TRUE); - mVolumeDownCtrl->setEnabled(FALSE); mMuteBtn->setToggleState(true); } else if (volume >= 1.0) { - mVolumeUpCtrl->setEnabled(FALSE); - mVolumeDownCtrl->setEnabled(TRUE); mMuteBtn->setToggleState(false); } else { mMuteBtn->setToggleState(false); - mVolumeUpCtrl->setEnabled(TRUE); - mVolumeDownCtrl->setEnabled(TRUE); } switch(result) @@ -473,12 +464,8 @@ void LLPanelPrimMediaControls::updateShape() mSkipBackCtrl->setEnabled(FALSE); mVolumeCtrl->setVisible(FALSE); - mVolumeUpCtrl->setVisible(FALSE); - mVolumeDownCtrl->setVisible(FALSE); mVolumeSliderCtrl->setVisible(FALSE); mVolumeCtrl->setEnabled(FALSE); - mVolumeUpCtrl->setEnabled(FALSE); - mVolumeDownCtrl->setEnabled(FALSE); mVolumeSliderCtrl->setEnabled(FALSE); if (mMediaPanelScroll) @@ -627,36 +614,45 @@ void LLPanelPrimMediaControls::updateShape() update_min_max(min, max, LLVector3(screen_vert.v)); } + // convert screenspace bbox to pixels (in screen coords) + LLRect window_rect = gViewerWindow->getWorldViewRectScaled(); LLCoordGL screen_min; - screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (min.mV[VX] + 1.f) * 0.5f); - screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (min.mV[VY] + 1.f) * 0.5f); + screen_min.mX = llround((F32)window_rect.getWidth() * (min.mV[VX] + 1.f) * 0.5f); + screen_min.mY = llround((F32)window_rect.getHeight() * (min.mV[VY] + 1.f) * 0.5f); LLCoordGL screen_max; - screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (max.mV[VX] + 1.f) * 0.5f); - screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (max.mV[VY] + 1.f) * 0.5f); + screen_max.mX = llround((F32)window_rect.getWidth() * (max.mV[VX] + 1.f) * 0.5f); + screen_max.mY = llround((F32)window_rect.getHeight() * (max.mV[VY] + 1.f) * 0.5f); - // grow panel so that screenspace bounding box fits inside "media_region" element of HUD - LLRect media_controls_rect; - S32 volume_slider_height = mVolumeSliderCtrl->getRect().getHeight() - /*fudge*/ 2; - getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_controls_rect); - media_controls_rect.mLeft -= mMediaRegion->getRect().mLeft; - media_controls_rect.mBottom -= mMediaRegion->getRect().mBottom - volume_slider_height; - media_controls_rect.mTop += getRect().getHeight() - mMediaRegion->getRect().mTop; - media_controls_rect.mRight += getRect().getWidth() - mMediaRegion->getRect().mRight; + // grow panel so that screenspace bounding box fits inside "media_region" element of panel + LLRect media_panel_rect; + // Get the height of the controls (less the volume slider) + S32 controls_height = mMediaControlsStack->getRect().getHeight() - mVolumeSliderCtrl->getRect().getHeight(); + getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_panel_rect); + media_panel_rect.mTop += controls_height; - // keep all parts of HUD on-screen - LLRect window_rect = getParent()->getLocalRect(); - media_controls_rect.intersectWith(window_rect); + // keep all parts of panel on-screen + // Area of the top of the world view to avoid putting the controls + window_rect.mTop -= mTopWorldViewAvoidZone; + // Don't include "spacing" bookends on left & right of the media controls + window_rect.mLeft -= mLeftBookend->getRect().getWidth(); + window_rect.mRight += mRightBookend->getRect().getWidth(); + // Don't include the volume slider + window_rect.mBottom -= mVolumeSliderCtrl->getRect().getHeight(); + media_panel_rect.intersectWith(window_rect); // clamp to minimum size, keeping rect inside window - S32 centerX = media_controls_rect.getCenterX(); - S32 centerY = media_controls_rect.getCenterY(); + S32 centerX = media_panel_rect.getCenterX(); + S32 centerY = media_panel_rect.getCenterY(); + // Shrink screen rect by min width and height, to ensure containment window_rect.stretch(-mMinWidth/2, -mMinHeight/2); window_rect.clampPointToRect(centerX, centerY); - media_controls_rect.setCenterAndSize(centerX, centerY, - llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); + media_panel_rect.setCenterAndSize(centerX, centerY, + llmax(mMinWidth, media_panel_rect.getWidth()), + llmax(mMinHeight, media_panel_rect.getHeight())); - setShape(media_controls_rect, true); + // Finally set the size of the panel + setShape(media_panel_rect, true); // Test mouse position to see if the cursor is stationary LLCoordWindow cursor_pos_window; @@ -699,13 +695,13 @@ void LLPanelPrimMediaControls::updateShape() /*virtual*/ void LLPanelPrimMediaControls::draw() { - F32 alpha = 1.f; + F32 alpha = getDrawContext().mAlpha; if(mFadeTimer.getStarted()) { F32 time = mFadeTimer.getElapsedTimeF32(); - alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); + alpha *= llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); - if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime) + if(time >= mControlFadeTime) { if(mClearFaceOnFade) { @@ -726,27 +722,30 @@ void LLPanelPrimMediaControls::draw() // Build rect for icon area in coord system of this panel // Assumes layout_stack is a direct child of this panel mMediaControlsStack->updateLayout(); - LLRect icon_area = mMediaControlsStack->getRect(); - + + // adjust for layout stack spacing + S32 space = mMediaControlsStack->getPanelSpacing() + 1; + LLRect controls_bg_area = mMediaControlsStack->getRect(); + + controls_bg_area.mTop += space; + // adjust to ignore space from volume slider - icon_area.mTop -= mVolumeSliderCtrl->getRect().getHeight(); + controls_bg_area.mBottom += mVolumeSliderCtrl->getRect().getHeight(); // adjust to ignore space from left bookend padding - icon_area.mLeft += mLeftBookend->getRect().getWidth(); + controls_bg_area.mLeft += mLeftBookend->getRect().getWidth() - space; // ignore space from right bookend padding - icon_area.mRight -= mRightBookend->getRect().getWidth(); + controls_bg_area.mRight -= mRightBookend->getRect().getWidth() - space; // draw control background UI image - mBackgroundImage->draw( icon_area, UI_VERTEX_COLOR % alpha); + mBackgroundImage->draw( controls_bg_area, UI_VERTEX_COLOR % alpha); // draw volume slider background UI image if (mVolumeSliderCtrl->getVisible()) { - LLRect volume_slider_rect = mVolumeSliderCtrl->getRect(); - // For some reason the rect is not in the right place (??) - // This translates the bg to under the slider - volume_slider_rect.translate(mVolumeSliderCtrl->getParent()->getRect().mLeft, icon_area.getHeight()); + LLRect volume_slider_rect; + screenRectToLocal(mVolumeSliderCtrl->calcScreenRect(), &volume_slider_rect); mVolumeSliderBackgroundImage->draw(volume_slider_rect, UI_VERTEX_COLOR % alpha); } @@ -1259,6 +1258,11 @@ void LLPanelPrimMediaControls::onToggleMute() { media_impl->setVolume(0.0); } + else if (mVolumeSliderCtrl->getValueF32() == 0.0) + { + media_impl->setVolume(1.0); + mVolumeSliderCtrl->setValue(1.0); + } else { media_impl->setVolume(mVolumeSliderCtrl->getValueF32()); @@ -1271,8 +1275,12 @@ void LLPanelPrimMediaControls::showVolumeSlider() mVolumeSliderVisible++; } - void LLPanelPrimMediaControls::hideVolumeSlider() { mVolumeSliderVisible--; } + +bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible() +{ + return mVolumeSliderVisible > 0; +} diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index d899ee4473..743cec70a1 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -111,6 +111,7 @@ private: void onToggleMute(); void showVolumeSlider(); void hideVolumeSlider(); + bool shouldVolumeSliderBeVisible(); static void onScrollUp(void* user_data); static void onScrollUpHeld(void* user_data); @@ -155,8 +156,6 @@ private: LLUICtrl *mMediaPlaySliderCtrl; LLUICtrl *mVolumeCtrl; LLButton *mMuteBtn; - LLUICtrl *mVolumeUpCtrl; - LLUICtrl *mVolumeDownCtrl; LLSliderCtrl *mVolumeSliderCtrl; LLIconCtrl *mWhitelistIcon; LLIconCtrl *mSecureLockIcon; @@ -171,6 +170,7 @@ private: F32 mZoomNearPadding; F32 mZoomMediumPadding; F32 mZoomFarPadding; + S32 mTopWorldViewAvoidZone; LLUICtrl *mMediaPanelScroll; LLButton *mScrollUpCtrl; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 245f694ac6..1b8fb49641 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -550,7 +550,7 @@ void LLTeleportHistoryPanel::updateVerbs() LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedFlatlList->getSelectedItem()); - mTeleportBtn->setEnabled(NULL != itemp && itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1); + mTeleportBtn->setEnabled(NULL != itemp); mShowOnMapBtn->setEnabled(NULL != itemp); } @@ -723,7 +723,10 @@ void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index) if (-1 == removed_index) showTeleportHistory(); // recreate all items else + { replaceItem(removed_index); // replace removed item by most recent + updateVerbs(); + } } void LLTeleportHistoryPanel::replaceItem(S32 removed_index) @@ -1033,7 +1036,7 @@ void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab) { LLSD param = acc_tab->getValue(); - if(!param.has("acc_collapsed")) + if(!param.has(COLLAPSED_BY_USER)) { return false; } @@ -1045,4 +1048,11 @@ void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param bool expanded = param.asBoolean(); // Save accordion tab state to restore it in refresh() setAccordionCollapsedByUser(ctrl, !expanded); + + // Reset selection upon accordion being collapsed + // to disable "Teleport" and "Map" buttons for hidden item. + if (!expanded && mLastSelectedFlatlList) + { + mLastSelectedFlatlList->resetSelection(); + } } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 5a70842a73..fbe68b4d92 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -54,7 +54,7 @@ #include "llcolorswatch.h" #include "lltexturectrl.h" #include "llcombobox.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llfocusmgr.h" #include "llmanipscale.h" #include "llpreviewscript.h" @@ -470,7 +470,7 @@ void LLPanelVolume::sendIsFlexible() if (is_flexible) { - LLFirstUse::useFlexible(); + //LLFirstUse::useFlexible(); if (objectp->getClickAction() == CLICK_ACTION_SIT) { diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index e2da4c4475..b049f914ad 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -70,7 +70,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - mAvatarListDoubleClickConnection = mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1)); mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); // Set onAvatarListDoubleClicked as default on_return action. mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); @@ -132,10 +132,15 @@ void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) mAvatarList->setSpeakingIndicatorsVisible(visible); }; -void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list) +void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl) { - // NOTE(EM): Should we check if there is multiple selection and start conference if it is so? - LLUUID clicked_id = list->getSelectedUUID(); + LLAvatarListItem* item = dynamic_cast(ctrl); + if(!item) + { + return; + } + + LLUUID clicked_id = item->getAvatarId(); if (clicked_id.isNull() || clicked_id == gAgent.getID()) return; @@ -166,7 +171,6 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { name.erase(found, moderator_indicator_len); item->setName(name); - item->reshapeAvatarName(); } } } @@ -188,7 +192,6 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) name += " "; name += moderator_indicator; item->setName(name); - item->reshapeAvatarName(); } } } @@ -279,6 +282,9 @@ bool LLParticipantList::onModeratorUpdateEvent(LLPointer e mModeratorList.erase(id); } } + + // apply changes immediately + onAvatarListRefreshed(mAvatarList, LLSD()); } } return true; @@ -576,7 +582,7 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - if (item == "can_mute_text" || "can_block" == item) + if (item == "can_mute_text" || "can_block" == item || "can_share" == item || "can_im" == item) { return mUUIDs.front() != gAgentID; } @@ -592,8 +598,7 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& if (speakerp.notNull()) { // not in voice participants can not be moderated - return speakerp->mStatus == LLSpeaker::STATUS_VOICE_ACTIVE - || speakerp->mStatus == LLSpeaker::STATUS_MUTED; + return speakerp->isInVoiceChannel(); } } return false; diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 70badbc40d..e1b1b5af00 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -232,7 +232,7 @@ class LLParticipantList }; private: - void onAvatarListDoubleClicked(LLAvatarList* list); + void onAvatarListDoubleClicked(LLUICtrl* ctrl); void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); /** diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 2a40cbaba0..84bdaafacf 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -364,6 +364,12 @@ BOOL LLPreviewGesture::postBuild() LLTextBox* text; LLCheckBoxCtrl* check; + edit = getChild("name"); + edit->setKeystrokeCallback(onKeystrokeCommit, this); + + edit = getChild("desc"); + edit->setKeystrokeCallback(onKeystrokeCommit, this); + edit = getChild("trigger_editor"); edit->setKeystrokeCallback(onKeystrokeCommit, this); edit->setCommitCallback(onCommitSetDirty, this); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 95756ac5f3..cc70360528 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -55,7 +55,6 @@ #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "lldir.h" -//#include "llfloaterchat.h" #include "llviewerstats.h" #include "llviewercontrol.h" // gSavedSettings #include "llappviewer.h" // app_abort_quit() diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 646c9fb6a4..fccf71f3cb 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -79,7 +79,6 @@ #include "llslider.h" #include "lldir.h" #include "llcombobox.h" -//#include "llfloaterchat.h" #include "llviewerstats.h" #include "llviewertexteditor.h" #include "llviewerwindow.h" -- cgit v1.2.3 From 0f61c00218a07a7d487e33256382c4a10561e0c1 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Mon, 22 Feb 2010 16:50:46 +0000 Subject: Enumerate available voice fonts. --- indra/newview/llvoiceclient.cpp | 124 ++++++++++++++++++++++++++++++++++++++++ indra/newview/llvoiceclient.h | 38 ++++++++++-- 2 files changed, 158 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 59606f17b2..92dfa6d30e 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -240,6 +240,12 @@ protected: std::string audioMediaString; std::string displayNameString; std::string deviceString; + std::string idString; + std::string descriptionString; + std::string expirationDateString; + bool hasExpired; + std::string fontTypeString; + std::string fontStatusString; int participantType; bool isLocallyMuted; bool isModeratorMuted; @@ -625,6 +631,34 @@ void LLVivoxProtocolParser::EndTag(const char *tag) autoAcceptMask = string; else if (!stricmp("AutoAddAsBuddy", tag)) autoAddAsBuddy = string; + else if (!stricmp("SessionFont", tag)) + { + gVoiceClient->addSessionFont(idString, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString); + } + else if (!stricmp("ID", tag)) + { + idString = string; + } + else if (!stricmp("Description", tag)) + { + descriptionString = string; + } + else if (!stricmp("ExpirationDate", tag)) + { + expirationDateString = string; + } + else if (!stricmp("Expired", tag)) + { + hasExpired = !stricmp(string.c_str(), "1"); + } + else if (!stricmp("Type", tag)) + { + fontTypeString = string; + } + else if (!stricmp("Status", tag)) + { + fontStatusString = string; + } else if (!stricmp("MessageHeader", tag)) messageHeader = string; else if (!stricmp("MessageBody", tag)) @@ -895,6 +929,10 @@ void LLVivoxProtocolParser::processResponse(std::string tag) { gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString); } + else if (!stricmp(actionCstr, "Account.GetSessionFonts.1")) + { + gVoiceClient->accountGetSessionFontsResponse(statusCode, statusString); + } else if (!stricmp(actionCstr, "Session.Set3DPosition.1")) { // We don't need to process these, but they're so spammy we don't want to log them. @@ -1243,6 +1281,9 @@ LLVoiceClient::LLVoiceClient() : mBuddyListMapPopulated(false), mBlockRulesListReceived(false), mAutoAcceptRulesListReceived(false), + + mSessionFontsReceived(false), + mCaptureDeviceDirty(false), mRenderDeviceDirty(false), mSpatialCoordsDirty(false), @@ -2156,6 +2197,9 @@ void LLVoiceClient::stateMachine() notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN); + // request the set of available voice fonts + accountGetSessionFontsSendMessage(); + // request the current set of block rules (we'll need them when updating the friends list) accountListBlockRulesSendMessage(); @@ -2641,6 +2685,24 @@ void LLVoiceClient::accountListAutoAcceptRulesSendMessage() } } +void LLVoiceClient::accountGetSessionFontsSendMessage() +{ + if(!mAccountHandle.empty()) + { + std::ostringstream stream; + + LL_DEBUGS("Voice") << "requesting session font list" << LL_ENDL; + + stream + << "" + << "" << mAccountHandle << "" + << "" + << "\n\n\n"; + + writeString(stream.str()); + } +} + void LLVoiceClient::sessionGroupCreateSendMessage() { if(!mAccountHandle.empty()) @@ -2691,6 +2753,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu stream << "" << (startAudio?"true":"false") << "" << "" << (startText?"true":"false") << "" +// << "0" << "" << mChannelName << "" << "\n\n\n"; writeString(stream.str()); @@ -2766,6 +2829,21 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) writeString(stream.str()); } +void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId) +{ + LL_DEBUGS("Voice") << "selecting voice font: " << fontId << " in session handle: " << session->mHandle << LL_ENDL; + + std::ostringstream stream; + + stream + << "" + << "" << session->mHandle << "" + << "" << fontId << "" + << "\n\n\n"; + + writeString(stream.str()); +} + void LLVoiceClient::sessionTerminate() { mSessionTerminateRequested = true; @@ -6958,6 +7036,46 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s } } +LLVoiceClient::voiceFontEntry::voiceFontEntry(const std::string &id) : + mID(id), + mHasExpired(false) +{ +} + +LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &id, + const std::string &name, + const std::string &description, + const std::string &expirationDate, + const bool hasExpired, + const std::string &fontType, + const std::string &fontStatus) +{ + voiceFontEntry *font = NULL; + + voiceFontMap::iterator iter = mSessionFontMap.find(&id); + if(iter != mSessionFontMap.end()) + { + // Found session font already in the map. + LL_DEBUGS("Voice") << "existing session font " << id << " : " << name << LL_ENDL; + font = iter->second; + } + + if(font == NULL) + { + LL_DEBUGS("Voice") << "adding session font " << id << " : " << name << (hasExpired?" (Expired)":"") << LL_ENDL; + font = new voiceFontEntry(id); + font->mName = name; + font->mDescription = description; + font->mExpirationDate = expirationDate; + font->mHasExpired = hasExpired; + font->mFontType = fontType; + font->mFontStatus = fontStatus; + + mSessionFontMap.insert(voiceFontMap::value_type(&(font->mID), font)); + } + return font; +} + void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString) { // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done. @@ -6970,6 +7088,12 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std mAutoAcceptRulesListReceived = true; } +void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString) +{ + // Session font list entries were updated via addSessionFont() during parsing. Just flag that we're done. + mSessionFontsReceived = true; +} + void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) { mParticipantObservers.insert(observer); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index a96cf18e27..05624bcefd 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -424,8 +424,32 @@ static void updatePosition(void); void deleteAllAutoAcceptRules(void); void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy); void accountListBlockRulesResponse(int statusCode, const std::string &statusString); - void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString); - + void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString); + + struct voiceFontEntry + { + voiceFontEntry(const std::string &id); + // *TODO: Decide which of these we don't need to store + std::string mID; + std::string mName; + std::string mDescription; + std::string mExpirationDate; + bool mHasExpired; + std::string mFontType; + std::string mFontStatus; + }; + + typedef std::map voiceFontMap; + + voiceFontEntry *addSessionFont(const std::string &id, + const std::string &name, + const std::string &description, + const std::string &expirationDate, + const bool hasExpired, + const std::string &fontType, + const std::string &fontStatus); + void accountGetSessionFontsResponse(int statusCode, const std::string &statusString); + ///////////////////////////// // session control messages void connectorCreate(); @@ -447,12 +471,15 @@ static void updatePosition(void); void accountListBlockRulesSendMessage(); void accountListAutoAcceptRulesSendMessage(); - + + void accountGetSessionFontsSendMessage(); + void sessionGroupCreateSendMessage(); void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false); void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false); void sessionMediaConnectSendMessage(sessionState *session); // just joins the audio session void sessionTextConnectSendMessage(sessionState *session); // just joins the text session + void sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId); void sessionTerminateSendMessage(sessionState *session); void sessionGroupTerminateSendMessage(sessionState *session); void sessionMediaDisconnectSendMessage(sessionState *session); @@ -653,7 +680,10 @@ static void updatePosition(void); bool mBlockRulesListReceived; bool mAutoAcceptRulesListReceived; buddyListMap mBuddyListMap; - + + bool mSessionFontsReceived; + voiceFontMap mSessionFontMap; + deviceList mCaptureDevices; deviceList mRenderDevices; -- cgit v1.2.3 From 5518e15f89359ba1627633f59f7299b69fc2bd69 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Mon, 22 Feb 2010 16:52:23 +0000 Subject: Added stateFontListReceived to the voice client state machine. This makes sure we have the voice font list before attempting to start a session. --- indra/newview/llvoiceclient.cpp | 11 +++++++++++ indra/newview/llvoiceclient.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 92dfa6d30e..de4e53f52c 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1622,6 +1622,7 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState) CASE(stateNeedsLogin); CASE(stateLoggingIn); CASE(stateLoggedIn); + CASE(stateFontListReceived); CASE(stateCreatingSessionGroup); CASE(stateNoChannel); CASE(stateJoiningSession); @@ -2231,6 +2232,11 @@ void LLVoiceClient::stateMachine() writeString(stream.str()); } } + + // accountGetSessionFontsResponse() will transition from here to stateFontListReceived. + + //MARK: stateFontListReceived + case stateFontListReceived: // font list received #if USE_SESSION_GROUPS // create the main session group @@ -7092,6 +7098,11 @@ void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::st { // Session font list entries were updated via addSessionFont() during parsing. Just flag that we're done. mSessionFontsReceived = true; + + if(getState() == stateLoggedIn) + { + setState(stateFontListReceived); + } } void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 05624bcefd..2d8fff5508 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -429,7 +429,6 @@ static void updatePosition(void); struct voiceFontEntry { voiceFontEntry(const std::string &id); - // *TODO: Decide which of these we don't need to store std::string mID; std::string mName; std::string mDescription; @@ -584,6 +583,7 @@ static void updatePosition(void); stateNeedsLogin, // send login request stateLoggingIn, // waiting for account handle stateLoggedIn, // account handle received + stateFontListReceived, // List of available voice fonts received stateCreatingSessionGroup, // Creating the main session group stateNoChannel, // stateJoiningSession, // waiting for session handle -- cgit v1.2.3 From 9f9b240dcee53a50b56a0ccb8d255a86d0ce62c9 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Tue, 6 Apr 2010 11:39:01 +0100 Subject: Added voice font selection to the voice floater. --- indra/newview/app_settings/logcontrol.xml | 1 + indra/newview/llcallfloater.cpp | 53 ++++++++++++++-- indra/newview/llcallfloater.h | 21 ++++--- indra/newview/llvoiceclient.cpp | 73 +++++++++++++++++----- indra/newview/llvoiceclient.h | 23 ++++--- .../default/xui/en/floater_voice_controls.xml | 38 ++++++++++- 6 files changed, 173 insertions(+), 36 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index d7bb64ce8a..d3fb958638 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -40,6 +40,7 @@ tags + Voice diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 76e058a1c3..52739184c0 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -52,6 +52,7 @@ #include "lltransientfloatermgr.h" #include "llviewerwindow.h" #include "llvoicechannel.h" +#include "llvoiceclient.h" // for Voice font list types #include "llviewerparcelmgr.h" static void get_voice_participants_uuids(std::vector& speakers_uuids); @@ -95,7 +96,7 @@ static void* create_non_avatar_caller(void*) return new LLNonAvatarCaller; } -LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL; +LLVoiceChannel* LLCallFloater::sCurrentVoiceChannel = NULL; LLCallFloater::LLCallFloater(const LLSD& key) : LLTransientDockableFloater(NULL, false, key) @@ -105,6 +106,7 @@ LLCallFloater::LLCallFloater(const LLSD& key) , mNonAvatarCaller(NULL) , mVoiceType(VC_LOCAL_CHAT) , mAgentPanel(NULL) +, mVoiceFont(NULL) , mSpeakingIndicator(NULL) , mIsModeratorMutedVoice(false) , mInitParticipantsVoiceState(false) @@ -146,6 +148,9 @@ BOOL LLCallFloater::postBuild() childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this)); + mVoiceFont = getChild("voice_font"); + childSetCommitCallback("voice_font", commitVoiceFont, this); // *FIX: childSetCommitCallback deprecated + mNonAvatarCaller = getChild("non_avatar_caller"); mNonAvatarCaller->setVisible(FALSE); @@ -157,7 +162,6 @@ BOOL LLCallFloater::postBuild() initAgentData(); - connectToChannel(LLVoiceChannel::getCurrentVoiceChannel()); setIsChrome(true); @@ -205,6 +209,9 @@ void LLCallFloater::draw() // virtual void LLCallFloater::onChange() { + // *FIX: Temporarily dumping this here till I decide where it should go + updateVoiceFont(); + if (NULL == mParticipants) return; updateParticipantsVoiceState(); @@ -231,6 +238,37 @@ void LLCallFloater::leaveCall() } } +/* static */ +void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata) +{ + LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue()); +} + +void LLCallFloater::updateVoiceFont() +{ + if (mVoiceFont) + { + mVoiceFont->removeall(); + mVoiceFont->add(getString("no_voice_font"), 0); + + if (LLVoiceClient::getInstance()->getVoiceFontsAvailable()) + { + const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList(); + + for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it) + { + mVoiceFont->add(*(it->second), it->first, ADD_BOTTOM); + } + mVoiceFont->setEnabled(true); + mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont()); + } + else + { + mVoiceFont->setEnabled(false); + } + } +} + void LLCallFloater::updateSession() { LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); @@ -369,7 +407,7 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) // *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO // it sill be sent for the same channel again (when state is changed). // So, lets ignore this call. - if (channel == sCurrentVoiceCanel) return; + if (channel == sCurrentVoiceChannel) return; LLCallFloater* call_floater = LLFloaterReg::getTypedInstance("voice_controls"); @@ -714,9 +752,9 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel) { mVoiceChannelStateChangeConnection.disconnect(); - sCurrentVoiceCanel = channel; + sCurrentVoiceChannel = channel; - mVoiceChannelStateChangeConnection = sCurrentVoiceCanel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2)); + mVoiceChannelStateChangeConnection = sCurrentVoiceChannel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2)); updateState(channel->getState()); } @@ -736,7 +774,7 @@ void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state) { - LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceCanel->getSessionName() << LL_ENDL; + LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceChannel->getSessionName() << LL_ENDL; if (LLVoiceChannel::STATE_CONNECTED == new_state) { updateSession(); @@ -745,6 +783,9 @@ void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state) { reset(new_state); } + + // *FIX: Dumped here till I decide where to put it + updateVoiceFont(); } void LLCallFloater::reset(const LLVoiceChannel::EState& new_state) diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 0a8ea7de39..9a13d853c9 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -40,6 +40,7 @@ class LLAvatarList; class LLAvatarListItem; +class LLComboBox; class LLNonAvatarCaller; class LLOutputMonitorCtrl; class LLParticipantList; @@ -47,15 +48,15 @@ class LLSpeakerMgr; class LLSpeakersDelayActionsStorage; /** - * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button. - * It can be torn-off and freely positioned onscreen. + * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron + * on the Speak button. It can be torn-off and freely positioned onscreen. * - * When the Resident is engaged in Nearby Voice Chat, the Voice Control Panel provides control over - * the Resident's own microphone input volume, the audible volume of each of the other participants, - * the Resident's own Voice Morphing settings (if she has subscribed to enable the feature), and Voice Recording. + * When the Resident is engaged in Voice Chat, the Voice Control Panel provides control + * over the audible volume of each of the other participants, the Resident's own Voice + * Morphing settings (if she has subscribed to enable the feature), and Voice Recording. * - * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an - * 'Leave Call' button to allow the Resident to leave that voice channel. + * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel + * also provides a 'Leave Call' button to allow the Resident to leave that voice channel. */ class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver { @@ -101,6 +102,9 @@ private: void leaveCall(); + static void commitVoiceFont(LLUICtrl*,void* userdata); + void updateVoiceFont(); + /** * Updates mSpeakerManager and list according to current Voice Channel * @@ -230,6 +234,7 @@ private: LLNonAvatarCaller* mNonAvatarCaller; EVoiceControls mVoiceType; LLPanel* mAgentPanel; + LLComboBox* mVoiceFont; LLOutputMonitorCtrl* mSpeakingIndicator; bool mIsModeratorMutedVoice; @@ -259,7 +264,7 @@ private: * * @see sOnCurrentChannelChanged() */ - static LLVoiceChannel* sCurrentVoiceCanel; + static LLVoiceChannel* sCurrentVoiceChannel; /* virtual */ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index de4e53f52c..5502744882 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -240,7 +240,7 @@ protected: std::string audioMediaString; std::string displayNameString; std::string deviceString; - std::string idString; + S32 id; std::string descriptionString; std::string expirationDateString; bool hasExpired; @@ -503,7 +503,20 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) { gVoiceClient->deleteAllAutoAcceptRules(); } - + else if (!stricmp("SessionFonts", tag)) + { + LLVoiceClient::getInstance()->clearSessionFonts(); + } + else if (!stricmp("SessionFont", tag)) + { + id = 0; + nameString.clear(); + descriptionString.clear(); + expirationDateString.clear(); + hasExpired.clear(); + fontTypeString.clear(); + fontStatusString.clear(); + } } } responseDepth++; @@ -633,11 +646,11 @@ void LLVivoxProtocolParser::EndTag(const char *tag) autoAddAsBuddy = string; else if (!stricmp("SessionFont", tag)) { - gVoiceClient->addSessionFont(idString, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString); + LLVoiceClient::getInstance()->addSessionFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString); } else if (!stricmp("ID", tag)) { - idString = string; + id = strtol(string.c_str(), NULL, 10); } else if (!stricmp("Description", tag)) { @@ -860,6 +873,8 @@ void LLVivoxProtocolParser::processResponse(std::string tag) } else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent")) { + // *TODO: Receive the current SessionFontID? + /* c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0 @@ -931,7 +946,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag) } else if (!stricmp(actionCstr, "Account.GetSessionFonts.1")) { - gVoiceClient->accountGetSessionFontsResponse(statusCode, statusString); + LLVoiceClient::getInstance()->accountGetSessionFontsResponse(statusCode, statusString); } else if (!stricmp(actionCstr, "Session.Set3DPosition.1")) { @@ -1283,6 +1298,7 @@ LLVoiceClient::LLVoiceClient() : mAutoAcceptRulesListReceived(false), mSessionFontsReceived(false), + mFontID(0), mCaptureDeviceDirty(false), mRenderDeviceDirty(false), @@ -2759,7 +2775,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu stream << "" << (startAudio?"true":"false") << "" << "" << (startText?"true":"false") << "" -// << "0" + << "" << mFontID << "" << "" << mChannelName << "" << "\n\n\n"; writeString(stream.str()); @@ -2835,16 +2851,17 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) writeString(stream.str()); } -void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId) +void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session) { - LL_DEBUGS("Voice") << "selecting voice font: " << fontId << " in session handle: " << session->mHandle << LL_ENDL; + llassert(session); + LL_DEBUGS("Voice") << "requesting voice font: " << mFontID << " in session handle: " << session->mHandle << LL_ENDL; std::ostringstream stream; stream - << "" + << "" << "" << session->mHandle << "" - << "" << fontId << "" + << "" << mFontID << "" << "\n\n\n"; writeString(stream.str()); @@ -7042,13 +7059,13 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s } } -LLVoiceClient::voiceFontEntry::voiceFontEntry(const std::string &id) : +LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) : mID(id), mHasExpired(false) { } -LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &id, +LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id_t &id, const std::string &name, const std::string &description, const std::string &expirationDate, @@ -7058,7 +7075,7 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string & { voiceFontEntry *font = NULL; - voiceFontMap::iterator iter = mSessionFontMap.find(&id); + voice_font_map_t::iterator iter = mSessionFontMap.find(id); if(iter != mSessionFontMap.end()) { // Found session font already in the map. @@ -7077,11 +7094,39 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string & font->mFontType = fontType; font->mFontStatus = fontStatus; - mSessionFontMap.insert(voiceFontMap::value_type(&(font->mID), font)); + mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName))); + mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font)); } return font; } +bool LLVoiceClient::setVoiceFont(voice_font_id_t id) +{ + if (!mAudioSession || !mAudioSession->mVoiceEnabled || !mSessionFontsReceived) + { + LL_DEBUGS("Voice") << "Session fonts not available" << LL_ENDL; + return false; + } + + if(id == 0 || mSessionFontMap.find(id) != mSessionFontMap.end()) + { + mFontID = id; + } + else + { + LL_DEBUGS("Voice") << "Invalid session font " << id << LL_ENDL; + return false; + } + + sessionSetVoiceFontSendMessage(mAudioSession); + return true; +} + +const LLVoiceClient::voice_font_id_t LLVoiceClient::getVoiceFont() const +{ + return mFontID; +} + void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString) { // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done. diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 2d8fff5508..05e9dcc896 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -428,8 +428,8 @@ static void updatePosition(void); struct voiceFontEntry { - voiceFontEntry(const std::string &id); - std::string mID; + voiceFontEntry(S32 id); + S32 mID; std::string mName; std::string mDescription; std::string mExpirationDate; @@ -438,9 +438,16 @@ static void updatePosition(void); std::string mFontStatus; }; - typedef std::map voiceFontMap; + typedef S32 voice_font_id_t; + typedef std::map voice_font_list_t; + typedef std::map voice_font_map_t; - voiceFontEntry *addSessionFont(const std::string &id, + bool getVoiceFontsAvailable() const { return mSessionFontsReceived; }; + bool setVoiceFont(voice_font_id_t id); + const voice_font_id_t getVoiceFont() const; + const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; }; + + voiceFontEntry *addSessionFont(const voice_font_id_t &id, const std::string &name, const std::string &description, const std::string &expirationDate, @@ -478,7 +485,7 @@ static void updatePosition(void); void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false); void sessionMediaConnectSendMessage(sessionState *session); // just joins the audio session void sessionTextConnectSendMessage(sessionState *session); // just joins the text session - void sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId); + void sessionSetVoiceFontSendMessage(sessionState *session); void sessionTerminateSendMessage(sessionState *session); void sessionGroupTerminateSendMessage(sessionState *session); void sessionMediaDisconnectSendMessage(sessionState *session); @@ -510,7 +517,7 @@ static void updatePosition(void); deviceList *getCaptureDevices(); deviceList *getRenderDevices(); - + void setNonSpatialChannel( const std::string &uri, const std::string &credentials); @@ -682,7 +689,9 @@ static void updatePosition(void); buddyListMap mBuddyListMap; bool mSessionFontsReceived; - voiceFontMap mSessionFontMap; + S32 mFontID; + voice_font_list_t mSessionFontList; + voice_font_map_t mSessionFontMap; // *TODO: make private deviceList mCaptureDevices; deviceList mRenderDevices; diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index c4411db8c5..100a060557 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -33,6 +33,9 @@ name="no_one_near"> No one near has voice enabled + + No Voice Effect + - + + + + + + + Date: Fri, 9 Apr 2010 01:29:03 +0100 Subject: Added a method to clear the session font list --- indra/newview/llvoiceclient.cpp | 25 ++++++++++++++++--------- indra/newview/llvoiceclient.h | 15 ++++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 4ea4d9c16e..8fe734030f 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -527,7 +527,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) nameString.clear(); descriptionString.clear(); expirationDateString.clear(); - hasExpired.clear(); + hasExpired = false; fontTypeString.clear(); fontStatusString.clear(); } @@ -7157,13 +7157,21 @@ LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) : { } -LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id_t &id, - const std::string &name, - const std::string &description, - const std::string &expirationDate, - const bool hasExpired, - const std::string &fontType, - const std::string &fontStatus) +void LLVoiceClient::clearSessionFonts() +{ + // *FIX: Currently set voice font will be invalid + mSessionFontsReceived = false; + mSessionFontList.clear(); + mSessionFontMap.clear(); +} + +void LLVoiceClient::addSessionFont(const voice_font_id_t &id, + const std::string &name, + const std::string &description, + const std::string &expirationDate, + const bool hasExpired, + const std::string &fontType, + const std::string &fontStatus) { voiceFontEntry *font = NULL; @@ -7189,7 +7197,6 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName))); mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font)); } - return font; } bool LLVoiceClient::setVoiceFont(voice_font_id_t id) diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 0df4e4bb3b..9409e19644 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -452,13 +452,14 @@ static void updatePosition(void); const voice_font_id_t getVoiceFont() const; const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; }; - voiceFontEntry *addSessionFont(const voice_font_id_t &id, - const std::string &name, - const std::string &description, - const std::string &expirationDate, - const bool hasExpired, - const std::string &fontType, - const std::string &fontStatus); + void clearSessionFonts(); + void addSessionFont(const voice_font_id_t &id, + const std::string &name, + const std::string &description, + const std::string &expirationDate, + const bool hasExpired, + const std::string &fontType, + const std::string &fontStatus); void accountGetSessionFontsResponse(int statusCode, const std::string &statusString); ///////////////////////////// -- cgit v1.2.3 From e9b613e8d4362412a03b8c141614553f902a24b3 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Mon, 19 Apr 2010 15:16:48 +0100 Subject: Identify fonts with UUIDs rather than using the font indexes directly as they are not guaranteed unique across sessions. Replaced all references to "Font" with "Voice Font" where possible to reduce confusion for anyone grepping code in future. --- indra/newview/llcallfloater.cpp | 6 +- indra/newview/llvoicechannel.cpp | 6 +- indra/newview/llvoiceclient.cpp | 253 ++++++++++++++++++++++++++------------- indra/newview/llvoiceclient.h | 97 +++++++++------ 4 files changed, 241 insertions(+), 121 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index f13e74679d..30f211d46d 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -250,15 +250,15 @@ void LLCallFloater::updateVoiceFont() if (mVoiceFont) { mVoiceFont->removeall(); - mVoiceFont->add(getString("no_voice_font"), 0); + mVoiceFont->add(getString("no_voice_font"), LLUUID::null); - if (LLVoiceClient::getInstance()->getVoiceFontsAvailable()) + if (LLVoiceClient::getInstance()->hasVoiceFonts()) { const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList(); for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it) { - mVoiceFont->add(*(it->second), it->first, ADD_BOTTOM); + mVoiceFont->add(*(it->first), *(it->second), ADD_BOTTOM); } mVoiceFont->setEnabled(true); mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont()); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 7bb1006e93..9ab0bf9552 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -887,9 +887,9 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s else { LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL; - // In case of incoming AvaLine call generated URI will be differ from original one. - // This is because Avatar-2-Avatar URI is based on avatar UUID but Avaline is not. - // See LLVoiceClient::sessionAddedEvent() -> setUUIDFromStringHash() + // In the case of an incoming AvaLine call, the generated URI will be different from the + // original one. This is because the P2P URI is based on avatar UUID but Avaline is not. + // See LLVoiceClient::sessionAddedEvent() setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID)); } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 8fe734030f..00f0c70c17 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -73,15 +73,11 @@ #include "llvoavatarself.h" #include "llvoicechannel.h" +#include "stringize.h" + // for base64 decoding #include "apr_base64.h" -// for SHA1 hash -#include "apr_sha1.h" - -// for MD5 hash -#include "llmd5.h" - #define USE_SESSION_GROUPS 0 static bool sConnectingToAgni = false; @@ -116,14 +112,6 @@ const int MAX_LOGIN_RETRIES = 12; // blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability. const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50; -static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str) -{ - LLMD5 md5_uuid; - md5_uuid.update((const unsigned char*)str.data(), str.size()); - md5_uuid.finalize(); - md5_uuid.raw_digest(uuid.mData); -} - static int scale_mic_volume(float volume) { // incoming volume has the range [0.0 ... 2.0], with 1.0 as the default. @@ -258,8 +246,8 @@ protected: std::string descriptionString; std::string expirationDateString; bool hasExpired; - std::string fontTypeString; - std::string fontStatusString; + S32 fontType; + S32 fontStatus; int participantType; bool isLocallyMuted; bool isModeratorMuted; @@ -519,7 +507,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) } else if (!stricmp("SessionFonts", tag)) { - LLVoiceClient::getInstance()->clearSessionFonts(); + LLVoiceClient::getInstance()->deleteAllVoiceFonts(); } else if (!stricmp("SessionFont", tag)) { @@ -528,8 +516,8 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) descriptionString.clear(); expirationDateString.clear(); hasExpired = false; - fontTypeString.clear(); - fontStatusString.clear(); + fontType = 0; + fontStatus = 0; } } } @@ -660,7 +648,7 @@ void LLVivoxProtocolParser::EndTag(const char *tag) autoAddAsBuddy = string; else if (!stricmp("SessionFont", tag)) { - LLVoiceClient::getInstance()->addSessionFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString); + LLVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontType, fontStatus); } else if (!stricmp("ID", tag)) { @@ -680,11 +668,11 @@ void LLVivoxProtocolParser::EndTag(const char *tag) } else if (!stricmp("Type", tag)) { - fontTypeString = string; + fontType = strtol(string.c_str(), NULL, 10); } else if (!stricmp("Status", tag)) { - fontStatusString = string; + fontStatus = strtol(string.c_str(), NULL, 10); } else if (!stricmp("MessageHeader", tag)) messageHeader = string; @@ -887,8 +875,6 @@ void LLVivoxProtocolParser::processResponse(std::string tag) } else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent")) { - // *TODO: Receive the current SessionFontID? - /* c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0 @@ -1391,9 +1377,6 @@ LLVoiceClient::LLVoiceClient() : mBlockRulesListReceived(false), mAutoAcceptRulesListReceived(false), - mSessionFontsReceived(false), - mFontID(0), - mCaptureDeviceDirty(false), mRenderDeviceDirty(false), mSpatialCoordsDirty(false), @@ -1874,7 +1857,8 @@ void LLVoiceClient::stateMachine() // Clean up and reset everything. closeSocket(); deleteAllSessions(); - deleteAllBuddies(); + deleteAllBuddies(); + deleteAllVoiceFonts(); mConnectorHandle.clear(); mAccountHandle.clear(); @@ -2640,6 +2624,7 @@ void LLVoiceClient::stateMachine() mAccountHandle.clear(); deleteAllSessions(); deleteAllBuddies(); + deleteAllVoiceFonts(); if(mVoiceEnabled && !mRelogRequested) { @@ -2829,7 +2814,7 @@ void LLVoiceClient::accountGetSessionFontsSendMessage() { std::ostringstream stream; - LL_DEBUGS("Voice") << "requesting session font list" << LL_ENDL; + LL_DEBUGS("Voice") << "Requesting voice font list." << LL_ENDL; stream << "" @@ -2863,7 +2848,10 @@ void LLVoiceClient::sessionGroupCreateSendMessage() void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText) { LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; - + + S32 font_index = getVoiceFontIndex(session->mVoiceFontID); + LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL; + session->mCreateInProgress = true; if(startAudio) { @@ -2887,11 +2875,11 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu << "" << LLURI::escape(session->mHash, allowed_chars) << "" << "SHA1UserName"; } - + stream << "" << (startAudio?"true":"false") << "" << "" << (startText?"true":"false") << "" - << "" << mFontID << "" + << "" << font_index << "" << "" << mChannelName << "" << "\n\n\n"; writeString(stream.str()); @@ -2900,7 +2888,10 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText) { LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; - + + S32 font_index = getVoiceFontIndex(session->mVoiceFontID); + LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL; + session->mCreateInProgress = true; if(startAudio) { @@ -2926,6 +2917,7 @@ void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, boo << "" << mChannelName << "" << "" << (startAudio?"true":"false") << "" << "" << (startText?"true":"false") << "" + << "" << font_index << "" << "" << password << "" << "SHA1UserName" << "\n\n\n" @@ -2938,6 +2930,9 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) { LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; + S32 font_index = getVoiceFontIndex(session->mVoiceFontID); + LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL; + session->mMediaConnectInProgress = true; std::ostringstream stream; @@ -2946,6 +2941,7 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) << "mHandle << "\" action=\"Session.MediaConnect.1\">" << "" << session->mGroupHandle << "" << "" << session->mHandle << "" + << "" << font_index << "" << "Audio" << "\n\n\n"; @@ -2969,15 +2965,15 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session) { - llassert(session); - LL_DEBUGS("Voice") << "requesting voice font: " << mFontID << " in session handle: " << session->mHandle << LL_ENDL; + S32 font_index = getVoiceFontIndex(session->mVoiceFontID); + LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << "), session handle: " << session->mHandle << LL_ENDL; std::ostringstream stream; stream << "" << "" << session->mHandle << "" - << "" << mFontID << "" + << "" << font_index << "" << "\n\n\n"; writeString(stream.str()); @@ -4272,7 +4268,7 @@ void LLVoiceClient::sessionAddedEvent( else { LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL; - setUUIDFromStringHash(session->mCallerID, session->mSIPURI); + session->mCallerID.generate(session->mSIPURI); session->mSynthesizedCallerID = true; // Can't look up the name in this case -- we have to extract it from the URI. @@ -5252,7 +5248,7 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con { // Create a UUID by hashing the URI, but do NOT set mAvatarIDValid. // This tells both code in LLVoiceClient and code in llfloateractivespeakers.cpp that the ID will not be in the name cache. - setUUIDFromStringHash(result->mAvatarID, uri); + result->mAvatarID.generate(uri); } } @@ -6637,7 +6633,8 @@ LLVoiceClient::sessionState::sessionState() : mReconnect(false), mVolumeDirty(false), mMuteDirty(false), - mParticipantsChanged(false) + mParticipantsChanged(false), + mVoiceFontID(0) { } @@ -7151,69 +7148,128 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s } } -LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) : +LLVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) : mID(id), - mHasExpired(false) + mFontIndex(0), + mHasExpired(false), + mFontType(VOICE_FONT_TYPE_NONE), + mFontStatus(VOICE_FONT_STATUS_NONE) { } -void LLVoiceClient::clearSessionFonts() +LLVoiceClient::voiceFontEntry::~voiceFontEntry() { - // *FIX: Currently set voice font will be invalid - mSessionFontsReceived = false; - mSessionFontList.clear(); - mSessionFontMap.clear(); } -void LLVoiceClient::addSessionFont(const voice_font_id_t &id, - const std::string &name, - const std::string &description, - const std::string &expirationDate, - const bool hasExpired, - const std::string &fontType, - const std::string &fontStatus) +void LLVoiceClient::deleteAllVoiceFonts() { + // All sessions should be removed first as FontIDs will be invalid + llassert(mSessions.empty()); + + LL_DEBUGS("Voice") << "Clearing voice font list." << LL_ENDL; + + mVoiceFontList.clear(); + + voice_font_map_t::iterator iter; + + for (iter = mVoiceFontMap.begin(); iter == mVoiceFontMap.end(); ++iter) + { + delete iter->second; + } + mVoiceFontMap.clear(); +} + +void LLVoiceClient::addVoiceFont(const S32 font_index, + const std::string &name, + const std::string &description, + const std::string &expiration_date, + const bool has_expired, + const S32 font_type, + const S32 font_status) +{ + // Vivox SessionFontIDs are not guaranteed to remain the same between + // sessions or grids so use a UUID for the name. + + // If received name is not a UUID, fudge one by hashing the name and type + LLUUID font_id; + if (LLUUID::validate(name)) + { + font_id = LLUUID(name); + } + else + { + font_id.generate(STRINGIZE(font_type << ":" << name)); + } + voiceFontEntry *font = NULL; - voice_font_map_t::iterator iter = mSessionFontMap.find(id); - if(iter != mSessionFontMap.end()) + // Hopefully won't happen, but behave gracefully if there is a duplicate + // by Replacing the previous one unless this one has expired. + // *TODO: Should maybe check for the later expiry date if neither has + // expired, and favour user fonts over root fonts? But as we shouldn't + // have duplicates anyway, it's probably not worth the effort. + voice_font_map_t::iterator iter = mVoiceFontMap.find(&font_id); + bool duplicate = (iter != mVoiceFontMap.end()); + if (duplicate) { - // Found session font already in the map. - LL_DEBUGS("Voice") << "existing session font " << id << " : " << name << LL_ENDL; - font = iter->second; + LL_DEBUGS("Voice") << "Voice font " << font_index << " duplicates " << iter->second->mFontIndex << "!" << LL_ENDL; + + if (!has_expired) + { + font = iter->second; + } + } + else + { + font = new voiceFontEntry(font_id); } - if(font == NULL) + if (font) { - LL_DEBUGS("Voice") << "adding session font " << id << " : " << name << (hasExpired?" (Expired)":"") << LL_ENDL; - font = new voiceFontEntry(id); - font->mName = name; - font->mDescription = description; - font->mExpirationDate = expirationDate; - font->mHasExpired = hasExpired; - font->mFontType = fontType; - font->mFontStatus = fontStatus; + font->mFontIndex = font_index; + // Use the description for the human readable name if available, as the + // "name" will probably be a UUID. + font->mName = description.empty() ? name : description; + font->mExpirationDate = expiration_date; + font->mHasExpired = has_expired; + font->mFontType = font_type; + font->mFontStatus = font_status; + + LL_DEBUGS("Voice") << "Adding voice font : " << font_id << " (" << font_index << ") : " << name << (has_expired?" (Expired)":"") << LL_ENDL; + + if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN) + { + LL_DEBUGS("Voice") << "Unknown voice font type: " << font_type << LL_ENDL; + } + if (font_status < VOICE_FONT_STATUS_NONE || font_status >= VOICE_FONT_STATUS_UNKNOWN) + { + LL_DEBUGS("Voice") << "Unknown voice font status: " << font_status << LL_ENDL; + } - mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName))); - mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font)); + if (!duplicate) + { + mVoiceFontMap.insert(voice_font_map_t::value_type(&(font->mID), font)); + mVoiceFontList.insert(voice_font_list_t::value_type(&(font->mName), &(font->mID))); + } } } -bool LLVoiceClient::setVoiceFont(voice_font_id_t id) +bool LLVoiceClient::setVoiceFont(const LLUUID& id) { - if (!mAudioSession || !mAudioSession->mVoiceEnabled || !mSessionFontsReceived) + if (!mAudioSession || !mAudioSession->mVoiceEnabled || !hasVoiceFonts()) { - LL_DEBUGS("Voice") << "Session fonts not available" << LL_ENDL; + LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL; return false; } - if(id == 0 || mSessionFontMap.find(id) != mSessionFontMap.end()) + if (id.isNull() || (mVoiceFontMap.find(&id) != mVoiceFontMap.end())) { - mFontID = id; + // *TODO: Check for expired fonts + mAudioSession->mVoiceFontID = id; } else { - LL_DEBUGS("Voice") << "Invalid session font " << id << LL_ENDL; + LL_DEBUGS("Voice") << "Invalid voice font " << id << LL_ENDL; return false; } @@ -7221,9 +7277,48 @@ bool LLVoiceClient::setVoiceFont(voice_font_id_t id) return true; } -const LLVoiceClient::voice_font_id_t LLVoiceClient::getVoiceFont() const +const LLUUID LLVoiceClient::getVoiceFont() +{ + if (mAudioSession) + { + return getVoiceFont(mAudioSession->mHandle); + } + else + { + return LLUUID::null; + } +} + +const LLUUID LLVoiceClient::getVoiceFont(const std::string &session_handle) +{ + LLUUID result; + if (hasVoiceFonts()) + { + sessionState *session = findSession(session_handle); + if (session) + { + result = mAudioSession->mVoiceFontID; + } + } + return result; +} + +S32 LLVoiceClient::getVoiceFontIndex(const LLUUID& id) const { - return mFontID; + S32 result = 0; + if (!id.isNull()) + { + voice_font_map_t::const_iterator it = mVoiceFontMap.find(&id); + if (it != mVoiceFontMap.end()) + { + result = it->second->mFontIndex; + } + else + { + LL_DEBUGS("Voice") << "Selected voice font " << id << " is not available." << LL_ENDL; + } + } + return result; } void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString) @@ -7240,9 +7335,7 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString) { - // Session font list entries were updated via addSessionFont() during parsing. Just flag that we're done. - mSessionFontsReceived = true; - + // Voice font list entries were updated via addVoiceFont() during parsing. if(getState() == stateLoggedIn) { setState(stateFontListReceived); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 9409e19644..f6af389b60 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -358,6 +358,8 @@ static void updatePosition(void); bool mParticipantsChanged; participantMap mParticipantsByURI; participantUUIDMap mParticipantsByUUID; + + LLUUID mVoiceFontID; }; participantState *findParticipantByID(const LLUUID& id); @@ -431,35 +433,24 @@ static void updatePosition(void); void accountListBlockRulesResponse(int statusCode, const std::string &statusString); void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString); - struct voiceFontEntry - { - voiceFontEntry(S32 id); - S32 mID; - std::string mName; - std::string mDescription; - std::string mExpirationDate; - bool mHasExpired; - std::string mFontType; - std::string mFontStatus; - }; - - typedef S32 voice_font_id_t; - typedef std::map voice_font_list_t; - typedef std::map voice_font_map_t; - - bool getVoiceFontsAvailable() const { return mSessionFontsReceived; }; - bool setVoiceFont(voice_font_id_t id); - const voice_font_id_t getVoiceFont() const; - const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; }; - - void clearSessionFonts(); - void addSessionFont(const voice_font_id_t &id, - const std::string &name, - const std::string &description, - const std::string &expirationDate, - const bool hasExpired, - const std::string &fontType, - const std::string &fontStatus); + ///////////////////////////// + // Voice Fonts + bool hasVoiceFonts() const { return !mVoiceFontMap.empty(); }; + bool setVoiceFont(const LLUUID& id); + const LLUUID getVoiceFont(); + const LLUUID getVoiceFont(const std::string &session_handle); + + typedef std::multimap voice_font_list_t; + + const voice_font_list_t &getVoiceFontList() const { return mVoiceFontList; }; + + void addVoiceFont(const S32 id, + const std::string &name, + const std::string &description, + const std::string &expiration_date, + const bool has_expired, + const S32 font_type, + const S32 font_status); void accountGetSessionFontsResponse(int statusCode, const std::string &statusString); ///////////////////////////// @@ -698,10 +689,46 @@ static void updatePosition(void); bool mAutoAcceptRulesListReceived; buddyListMap mBuddyListMap; - bool mSessionFontsReceived; - S32 mFontID; - voice_font_list_t mSessionFontList; - voice_font_map_t mSessionFontMap; // *TODO: make private + // Voice Fonts + + S32 getVoiceFontIndex(const LLUUID& id) const; + void deleteAllVoiceFonts(); + + typedef enum e_voice_font_type + { + VOICE_FONT_TYPE_NONE = 0, + VOICE_FONT_TYPE_ROOT = 1, + VOICE_FONT_TYPE_USER = 2, + VOICE_FONT_TYPE_UNKNOWN + } EVoiceFontType; + + typedef enum e_voice_font_status + { + VOICE_FONT_STATUS_NONE = 0, + VOICE_FONT_STATUS_FREE = 1, + VOICE_FONT_STATUS_NOT_FREE = 2, + VOICE_FONT_STATUS_UNKNOWN + } EVoiceFontStatus; + + struct voiceFontEntry + { + voiceFontEntry(LLUUID& id); + ~voiceFontEntry(); + + LLUUID mID; + S32 mFontIndex; + std::string mName; + std::string mExpirationDate; + bool mHasExpired; + S32 mFontType; + S32 mFontStatus; + }; + typedef std::map voice_font_map_t; + + voice_font_map_t mVoiceFontMap; + voice_font_list_t mVoiceFontList; + + // Audio devices deviceList mCaptureDevices; deviceList mRenderDevices; @@ -714,8 +741,8 @@ static void updatePosition(void); // This should be called when the code detects we have changed parcels. // It initiates the call to the server that gets the parcel channel. void parcelChanged(); - - void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = ""); + + void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = ""); void joinSession(sessionState *session); static std::string nameFromAvatar(LLVOAvatar *avatar); -- cgit v1.2.3 From d6549677fb0a1f1816813db8be6a04ee55e8b8e1 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Mon, 19 Apr 2010 15:38:17 +0100 Subject: Removed left over initialization to 0 of mVoiceFontID from when it was an integer rather than a UUID. --- indra/newview/llvoiceclient.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 8b88fd46a3..6205617016 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -6633,8 +6633,7 @@ LLVoiceClient::sessionState::sessionState() : mReconnect(false), mVolumeDirty(false), mMuteDirty(false), - mParticipantsChanged(false), - mVoiceFontID(0) + mParticipantsChanged(false) { } -- cgit v1.2.3 From 7fc33646853e6853f4afb26079afe1512198c24e Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Tue, 20 Apr 2010 03:23:03 +0100 Subject: Sort out the state machine in LLVoiceClient to wait for voice fonts properly. --- indra/newview/llvoiceclient.cpp | 34 +++++++++++++++++----------------- indra/newview/llvoiceclient.h | 3 ++- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 6205617016..b1f0380029 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1715,7 +1715,8 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState) CASE(stateNeedsLogin); CASE(stateLoggingIn); CASE(stateLoggedIn); - CASE(stateFontListReceived); + CASE(stateVoiceFontsWait); + CASE(stateVoiceFontsReceived); CASE(stateCreatingSessionGroup); CASE(stateNoChannel); CASE(stateJoiningSession); @@ -2293,6 +2294,7 @@ void LLVoiceClient::stateMachine() notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN); // request the set of available voice fonts + setState(stateVoiceFontsWait); accountGetSessionFontsSendMessage(); // request the current set of block rules (we'll need them when updating the friends list) @@ -2326,17 +2328,21 @@ void LLVoiceClient::stateMachine() writeString(stream.str()); } } - - // accountGetSessionFontsResponse() will transition from here to stateFontListReceived. - - //MARK: stateFontListReceived - case stateFontListReceived: // font list received + break; + //MARK: stateVoiceFontsWait + case stateVoiceFontsWait: // Await voice font list + // accountGetSessionFontsResponse() will transition from here to + // stateVoiceFontsReceived, to ensure we have the voice font list + // before attempting to create a session. + break; + + //MARK: stateVoiceFontsReceived + case stateVoiceFontsReceived: // Voice font list received #if USE_SESSION_GROUPS // create the main session group - sessionGroupCreateSendMessage(); - setState(stateCreatingSessionGroup); + sessionGroupCreateSendMessage(); #else // Not using session groups -- skip the stateCreatingSessionGroup state. setState(stateNoChannel); @@ -7162,16 +7168,10 @@ LLVoiceClient::voiceFontEntry::~voiceFontEntry() void LLVoiceClient::deleteAllVoiceFonts() { - // All sessions should be removed first as FontIDs will be invalid - llassert(mSessions.empty()); - - LL_DEBUGS("Voice") << "Clearing voice font list." << LL_ENDL; - mVoiceFontList.clear(); voice_font_map_t::iterator iter; - - for (iter = mVoiceFontMap.begin(); iter == mVoiceFontMap.end(); ++iter) + for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter) { delete iter->second; } @@ -7335,9 +7335,9 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString) { // Voice font list entries were updated via addVoiceFont() during parsing. - if(getState() == stateLoggedIn) + if(getState() == stateVoiceFontsWait) { - setState(stateFontListReceived); + setState(stateVoiceFontsReceived); } } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index f6af389b60..16fcb1d3f6 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -587,7 +587,8 @@ static void updatePosition(void); stateNeedsLogin, // send login request stateLoggingIn, // waiting for account handle stateLoggedIn, // account handle received - stateFontListReceived, // List of available voice fonts received + stateVoiceFontsWait, // Awaiting the list of voice fonts + stateVoiceFontsReceived, // List of voice fonts received stateCreatingSessionGroup, // Creating the main session group stateNoChannel, // stateJoiningSession, // waiting for session handle -- cgit v1.2.3 From cacfa18643092547e7665b36d482ad9c8c5dfc54 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 28 Apr 2010 03:33:15 +0100 Subject: Persist Voice Font selection. Added 'VoiceFontDefault' saved setting. Implemented LLVoiceClientFontsObserver to update the UI when the voice font list is received. Renamed LLVoiceClientParticipantObserver::onChange() to onParticipantsChanged to avoid ambiguity and make the code more readable. Made the Voice Font combo in the VCP auto resize to make best use of the available space when the 'Leave Call button is not visible. --- indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llcallfloater.cpp | 64 ++++++++++------------ indra/newview/llcallfloater.h | 10 +++- indra/newview/llparticipantlist.cpp | 2 +- indra/newview/llspeakingindicatormanager.cpp | 4 +- indra/newview/llvoicechannel.h | 2 +- indra/newview/llvoiceclient.cpp | 35 +++++++++++- indra/newview/llvoiceclient.h | 17 +++++- .../default/xui/en/floater_voice_controls.xml | 12 ++-- 9 files changed, 106 insertions(+), 51 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4ca23e14a1..63e8775d04 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10405,6 +10405,17 @@ Value 0 + VoiceFontDefault + + Comment + Selected voice font + Persist + 1 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + AutoDisengageMic Comment diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index f41875f67b..703c7dd435 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -115,7 +115,8 @@ LLCallFloater::LLCallFloater(const LLSD& key) mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay); mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); - LLVoiceClient::getInstance()->addObserver(this); + LLVoiceClient::instance().addObserver(dynamic_cast(this)); + LLVoiceClient::instance().addObserver(dynamic_cast(this)); LLTransientFloaterMgr::getInstance()->addControlView(this); // force docked state since this floater doesn't save it between recreations @@ -135,7 +136,8 @@ LLCallFloater::~LLCallFloater() if(LLVoiceClient::instanceExists()) { - LLVoiceClient::instance().removeObserver(this); + LLVoiceClient::instance().removeObserver(dynamic_cast(this)); + LLVoiceClient::instance().removeObserver(dynamic_cast(this)); } LLTransientFloaterMgr::getInstance()->removeControlView(this); } @@ -208,11 +210,8 @@ void LLCallFloater::draw() } // virtual -void LLCallFloater::onChange() +void LLCallFloater::onParticipantsChanged() { - // *FIX: Temporarily dumping this here till I decide where it should go - updateVoiceFont(); - if (NULL == mParticipants) return; updateParticipantsVoiceState(); @@ -226,42 +225,23 @@ void LLCallFloater::onChange() } } -////////////////////////////////////////////////////////////////////////// -/// PRIVATE SECTION -////////////////////////////////////////////////////////////////////////// - -void LLCallFloater::leaveCall() -{ - LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); - if (voice_channel) - { - gIMMgr->endCall(voice_channel->getSessionID()); - } -} - -/* static */ -void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata) -{ - LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue()); -} - -void LLCallFloater::updateVoiceFont() +// virtual +void LLCallFloater::onVoiceFontsChanged() { if (mVoiceFont) { mVoiceFont->removeall(); mVoiceFont->add(getString("no_voice_font"), LLUUID::null); - if (LLVoiceClient::getInstance()->hasVoiceFonts()) + if (LLVoiceClient::instance().hasVoiceFonts()) { - const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList(); - + const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::instance().getVoiceFontList(); for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it) { mVoiceFont->add(*(it->first), *(it->second), ADD_BOTTOM); } mVoiceFont->setEnabled(true); - mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont()); + mVoiceFont->setValue(LLVoiceClient::instance().getVoiceFont()); } else { @@ -270,6 +250,25 @@ void LLCallFloater::updateVoiceFont() } } +////////////////////////////////////////////////////////////////////////// +/// PRIVATE SECTION +////////////////////////////////////////////////////////////////////////// + +void LLCallFloater::leaveCall() +{ + LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (voice_channel) + { + gIMMgr->endCall(voice_channel->getSessionID()); + } +} + +/* static */ +void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata) +{ + LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue()); +} + void LLCallFloater::updateSession() { LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); @@ -334,7 +333,7 @@ void LLCallFloater::updateSession() } updateTitle(); - + //hide "Leave Call" button for nearby chat bool is_local_chat = mVoiceType == VC_LOCAL_CHAT; childSetVisible("leave_call_btn_panel", !is_local_chat); @@ -787,9 +786,6 @@ void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state) { reset(new_state); } - - // *FIX: Dumped here till I decide where to put it - updateVoiceFont(); } void LLCallFloater::reset(const LLVoiceChannel::EState& new_state) diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 9a13d853c9..160eff312c 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -58,7 +58,9 @@ class LLSpeakersDelayActionsStorage; * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel * also provides a 'Leave Call' button to allow the Resident to leave that voice channel. */ -class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver +class LLCallFloater : public LLTransientDockableFloater, + LLVoiceClientParticipantObserver, + LLVoiceClientFontsObserver { public: @@ -76,7 +78,10 @@ public: * * Refreshes list to display participants not in voice as disabled. */ - /*virtual*/ void onChange(); + /*virtual*/ void onParticipantsChanged(); + + /// Called by LLVoiceClient::notifyVoiceFontObservers when voice font list is changed. + /*virtual*/ void onVoiceFontsChanged(); static void sOnCurrentChannelChanged(const LLUUID& session_id); @@ -103,7 +108,6 @@ private: void leaveCall(); static void commitVoiceFont(LLUICtrl*,void* userdata); - void updateVoiceFont(); /** * Updates mSpeakerManager and list according to current Voice Channel diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index c3748ca81d..d0c882e16e 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -92,7 +92,7 @@ public: mAvalineCallers.insert(avaline_caller_id); } - void onChange() + void onParticipantsChanged() { uuid_set_t participant_uuids; LLVoiceClient::getInstance()->getParticipantsUUIDSet(participant_uuids); diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index cc06179481..70028dc21b 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -107,7 +107,7 @@ private: * So, method does not calculate difference between these list it only switches off already * switched on indicators and switches on indicators of voice channel participants */ - void onChange(); + void onParticipantsChanged(); /** * Changes state of indicators specified by LLUUIDs @@ -205,7 +205,7 @@ void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_ mSwitchedIndicatorsOn.clear(); } -void SpeakingIndicatorManager::onChange() +void SpeakingIndicatorManager::onParticipantsChanged() { LL_DEBUGS("SpeakingIndicator") << "Voice participant list was changed, updating indicators" << LL_ENDL; diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 941cccacc3..5236b11853 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -112,7 +112,7 @@ protected: void doSetState(const EState& state); void setURI(std::string uri); - // there can be two directions ICOMING and OUTGOING + // there can be two directions INCOMING and OUTGOING EDirection mCallDirection; std::string mURI; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index b1f0380029..d131285512 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -6641,6 +6641,7 @@ LLVoiceClient::sessionState::sessionState() : mMuteDirty(false), mParticipantsChanged(false) { + mVoiceFontID = LLUUID(gSavedSettings.getString("VoiceFontDefault")); } LLVoiceClient::sessionState::~sessionState() @@ -7263,8 +7264,11 @@ bool LLVoiceClient::setVoiceFont(const LLUUID& id) if (id.isNull() || (mVoiceFontMap.find(&id) != mVoiceFontMap.end())) { - // *TODO: Check for expired fonts + // *TODO: Check for expired fonts? mAudioSession->mVoiceFontID = id; + + // *TODO: Separate voice font defaults for spatial chat and IM? + gSavedSettings.setString("VoiceFontDefault", id.asString()); } else { @@ -7273,6 +7277,7 @@ bool LLVoiceClient::setVoiceFont(const LLUUID& id) } sessionSetVoiceFontSendMessage(mAudioSession); + notifyVoiceFontObservers(); return true; } @@ -7339,6 +7344,7 @@ void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::st { setState(stateVoiceFontsReceived); } + notifyVoiceFontObservers(); } void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) @@ -7358,12 +7364,35 @@ void LLVoiceClient::notifyParticipantObservers() ) { LLVoiceClientParticipantObserver* observer = *it; - observer->onChange(); - // In case onChange() deleted an entry. + observer->onParticipantsChanged(); + // In case onParticipantsChanged() deleted an entry. it = mParticipantObservers.upper_bound(observer); } } +void LLVoiceClient::addObserver(LLVoiceClientFontsObserver* observer) +{ + mVoiceFontObservers.insert(observer); +} + +void LLVoiceClient::removeObserver(LLVoiceClientFontsObserver* observer) +{ + mVoiceFontObservers.erase(observer); +} + +void LLVoiceClient::notifyVoiceFontObservers() +{ + for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); + it != mVoiceFontObservers.end(); + ) + { + LLVoiceClientFontsObserver* observer = *it; + observer->onVoiceFontsChanged(); + // In case onVoiceFontsChanged() deleted an entry. + it = mVoiceFontObservers.upper_bound(observer); + } +} + void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer) { mStatusObservers.insert(observer); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 16fcb1d3f6..a1083652aa 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -49,7 +49,14 @@ class LLVoiceClientParticipantObserver { public: virtual ~LLVoiceClientParticipantObserver() { } - virtual void onChange() = 0; + virtual void onParticipantsChanged() = 0; +}; + +class LLVoiceClientFontsObserver +{ +public: + virtual ~LLVoiceClientFontsObserver() { } + virtual void onVoiceFontsChanged() = 0; }; class LLVoiceClientStatusObserver @@ -500,6 +507,9 @@ static void updatePosition(void); void addObserver(LLVoiceClientParticipantObserver* observer); void removeObserver(LLVoiceClientParticipantObserver* observer); + void addObserver(LLVoiceClientFontsObserver* observer); + void removeObserver(LLVoiceClientFontsObserver* observer); + void addObserver(LLVoiceClientStatusObserver* observer); void removeObserver(LLVoiceClientStatusObserver* observer); @@ -832,6 +842,11 @@ static std::string nameFromsipURI(const std::string &uri); void notifyParticipantObservers(); + typedef std::set voice_font_observer_set_t; + voice_font_observer_set_t mVoiceFontObservers; + + void notifyVoiceFontObservers(); + typedef std::set status_observer_set_t; status_observer_set_t mStatusObservers; diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index e7c5770a08..885c8304eb 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -101,20 +101,20 @@ orientation="horizontal" width="263"> + width="150"> + width="150"> + + + + -- cgit v1.2.3 From 04ef90ceb0829e660d9c89a13ef526b3d30c732c Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Tue, 18 May 2010 15:55:22 +0100 Subject: EXT-7390 WIP Created SLapp secondlife:///app/voice/effects/refresh to update the voice effect list with new effects. --- indra/newview/llvoiceclient.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 52a7de61a0..d44b47707e 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -35,6 +35,7 @@ #include "llviewerwindow.h" #include "llvoicevivox.h" #include "llviewernetwork.h" +#include "llcommandhandler.h" #include "llhttpnode.h" #include "llnotificationsutil.h" #include "llsdserialize.h" @@ -46,6 +47,39 @@ const F32 LLVoiceClient::VOLUME_MIN = 0.f; const F32 LLVoiceClient::VOLUME_DEFAULT = 0.5f; const F32 LLVoiceClient::VOLUME_MAX = 1.0f; + +// Support for secondlife:///app/voice SLapps +class LLVoiceHandler : public LLCommandHandler +{ +public: + // requests will be throttled from a non-trusted browser + LLVoiceHandler() : LLCommandHandler("voice", UNTRUSTED_THROTTLE) {} + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + if (params[0].asString() == "effects") + { + LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); + // If the voice client doesn't support voice effects, we can't handle effects SLapps + if (!effect_interface) + { + return false; + } + + // Support secondlife:///app/voice/effects/refresh to update the voice effect list with new effects + if (params[1].asString() == "refresh") + { + effect_interface->refreshVoiceEffectLists(false); + return true; + } + } + return false; + } +}; +LLVoiceHandler gVoiceHandler; + + + std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus) { std::string result = "UNKNOWN"; @@ -77,7 +111,6 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv - /////////////////////////////////////////////////////////////////////////////////////////////// LLVoiceClient::LLVoiceClient() : -- cgit v1.2.3 From be0662234565f772fc4c89e47400dc9df8277800 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 19 May 2010 16:25:52 +0100 Subject: EXT-7337 WIP Voice font previewing Added LLVoiceEffectInterface::getVoiceEffectProperties Added LLVivoxVoiceClient::getVoiceFontTemplateIndex --- indra/newview/llvoicevivox.cpp | 50 +++++++++++++++++++++++++++++++++++++++++- indra/newview/llvoicevivox.h | 2 ++ 2 files changed, 51 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index ee67879d3d..2df9152a17 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6378,6 +6378,36 @@ const LLUUID LLVivoxVoiceClient::getVoiceEffect() return mAudioSession ? mAudioSession->mVoiceFontID : LLUUID::null; } +LLSD LLVivoxVoiceClient::getVoiceEffectProperties(const LLUUID& id) +{ + LLSD sd; + + voice_font_map_t::iterator iter = mVoiceFontMap.find(id); + if (iter != mVoiceFontMap.end()) + { + sd["template_only"] = false; + } + else + { + // Voice effect is not in the voice font map, see if there is a template + iter = mVoiceFontTemplateMap.find(id); + if (iter == mVoiceFontTemplateMap.end()) + { + LL_WARNS("Voice") << "Voice effect " << id << "not found." << LL_ENDL; + return sd; + } + sd["template_only"] = true; + } + + voiceFontEntry *font = iter->second; + sd["name"] = font->mName; + sd["expired"] = font->mHasExpired; + sd["expiry_date"] = font->mExpirationDate; + sd["is_new"] = font->mIsNew; + + return sd; +} + LLVivoxVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) : mID(id), mFontIndex(0), @@ -6536,6 +6566,24 @@ S32 LLVivoxVoiceClient::getVoiceFontIndex(const LLUUID& id) const return result; } +S32 LLVivoxVoiceClient::getVoiceFontTemplateIndex(const LLUUID& id) const +{ + S32 result = 0; + if (!id.isNull()) + { + voice_font_map_t::const_iterator it = mVoiceFontTemplateMap.find(id); + if (it != mVoiceFontTemplateMap.end()) + { + result = it->second->mFontIndex; + } + else + { + LL_DEBUGS("Voice") << "Selected voice font template " << id << " is not available." << LL_ENDL; + } + } + return result; +} + void LLVivoxVoiceClient::accountGetSessionFontsSendMessage() { if(!mAccountHandle.empty()) @@ -6753,7 +6801,7 @@ void LLVivoxVoiceClient::captureBufferPlayStartSendMessage(const LLUUID& voice_f LL_DEBUGS("Voice") << "Starting audio buffer playback." << LL_ENDL; - S32 font_index = getVoiceFontIndex(voice_font_id); + S32 font_index = getVoiceFontTemplateIndex(voice_font_id); LL_DEBUGS("Voice") << "With voice font: " << voice_font_id << " (" << font_index << ")" << LL_ENDL; stream diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 6c302962a3..1047d2e5ed 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -240,6 +240,7 @@ public: //@{ virtual bool setVoiceEffect(const LLUUID& id); virtual const LLUUID getVoiceEffect(); + virtual LLSD getVoiceEffectProperties(const LLUUID& id); virtual void refreshVoiceEffectLists(bool clear_lists); virtual const voice_effect_list_t& getVoiceEffectList() const; @@ -859,6 +860,7 @@ private: void deleteVoiceFontTemplates(); S32 getVoiceFontIndex(const LLUUID& id) const; + S32 getVoiceFontTemplateIndex(const LLUUID& id) const; void accountGetSessionFontsSendMessage(); void accountGetTemplateFontsSendMessage(); -- cgit v1.2.3 From 95ed59a9dec737ffe8d566595e1a74f662fe1e43 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 19 May 2010 16:28:03 +0100 Subject: EXT-7337 WIP Added template voice fonts to the voice font list for previewing --- indra/newview/llfloatervoiceeffect.cpp | 91 ++++++++++++++++++---- indra/newview/llvoiceclient.h | 1 + .../skins/default/xui/en/floater_voice_effect.xml | 89 ++++++++++++++++----- 3 files changed, 150 insertions(+), 31 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 5a579f5aeb..de12e8d12a 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -99,29 +99,94 @@ void LLFloaterVoiceEffect::update() return; } + LL_DEBUGS("Voice")<< "Rebuilding voice effect list."<< LL_ENDL; + + // Preserve selected items and scroll position + S32 scroll_pos = mVoiceEffectList->getScrollPos(); + uuid_vec_t selected_items; + std::vector items = mVoiceEffectList->getAllSelected(); + for(std::vector::const_iterator it = items.begin(); it != items.end(); it++) + { + selected_items.push_back((*it)->getUUID()); + } + mVoiceEffectList->deleteAllItems(); - LLSD element; - element["id"] = LLUUID::null; - element["columns"][1]["column"] = "name"; - element["columns"][1]["value"] = getString("no_voice_effect"); - mVoiceEffectList->addElement(element, ADD_BOTTOM); - - const voice_effect_list_t& effect_list = effect_interface->getVoiceEffectList(); - if (!effect_list.empty()) + { - for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) + // Add the "No Voice Effect" entry + LLSD element; + + element["id"] = LLUUID::null; + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = getString("no_voice_effect"); + element["columns"][0]["font"]["name"] = "SANSSERIF"; + element["columns"][0]["font"]["style"] = "BOLD"; + + LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); + // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( + if(sl_item) { + ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(LLFontGL::BOLD); + } + } + + const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList(); + if (!template_list.empty()) + { + for (voice_effect_list_t::const_iterator it = template_list.begin(); it != template_list.end(); ++it) + { + const LLUUID& effect_id = it->second; + std::string effect_name = it->first; + + LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id); + bool is_template_only = effect_properties["template_only"].asBoolean(); + bool is_new = effect_properties["is_new"].asBoolean(); + std::string expiry_date = effect_properties["expiry_date"].asString(); + + std::string font_style = "NORMAL"; + if (!is_template_only) + { + font_style = "BOLD"; + } LLSD element; - element["id"] = it->second; - element["columns"][1]["column"] = "name"; - element["columns"][1]["value"] = it->first; - mVoiceEffectList->addElement(element, ADD_BOTTOM); + element["id"] = effect_id; + + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = effect_name; + element["columns"][0]["font"]["name"] = "SANSSERIF"; + element["columns"][0]["font"]["style"] = font_style; + element["columns"][1]["column"] = "new"; + element["columns"][1]["value"] = is_new ? getString("new_voice_effect") : ""; + element["columns"][1]["font"]["name"] = "SANSSERIF"; + element["columns"][1]["font"]["style"] = font_style; + + element["columns"][2]["column"] = "expires"; + element["columns"][2]["value"] = !is_template_only ? expiry_date : ""; + element["columns"][2]["font"]["name"] = "SANSSERIF"; + element["columns"][2]["font"]["style"] = font_style; + + LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); + // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( + if(sl_item) + { + LLFontGL::StyleFlags style = is_template_only ? LLFontGL::NORMAL : LLFontGL::BOLD; + ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(style); + } } } + // Re-select items that were selected before, and restore the scroll position + for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++) + { + mVoiceEffectList->selectByID(*it); + } + mVoiceEffectList->setScrollPos(scroll_pos); + mVoiceEffectList->setValue(effect_interface->getVoiceEffect()); mVoiceEffectList->setEnabled(true); + // Update button states + // *TODO: Should separate this from rebuilding the effects list, to avoid rebuilding it unnecessarily bool recording = effect_interface->isPreviewRecording(); getChild("record_btn")->setVisible(!recording); getChild("record_stop_btn")->setVisible(recording); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 8d898378d6..5caf26c492 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -289,6 +289,7 @@ public: //@{ virtual bool setVoiceEffect(const LLUUID& id) = 0; virtual const LLUUID getVoiceEffect() = 0; + virtual LLSD getVoiceEffectProperties(const LLUUID& id) = 0; virtual void refreshVoiceEffectLists(bool clear_lists) = 0; virtual const voice_effect_list_t &getVoiceEffectList() const = 0; diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 5627eb3aff..8f2f13dffe 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -16,6 +16,9 @@ No Voice Effect + + New! + - + - - + + + + - + --> @@ -92,19 +145,19 @@ left_delta="0" name="record_stop_btn" top_delta="0" - width="83"> + width="135"> @@ -116,7 +169,7 @@ left_delta="0" name="play_stop_btn" top_delta="0" - width="83"> + width="135"> -- cgit v1.2.3 From 2930b805d3a5aa88efdbe9eadfec210c461edfa9 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 19 May 2010 17:35:53 +0100 Subject: EXT-7337 WIP Fix formatting in floater_voice_effect.xml (no functional change) --- .../skins/default/xui/en/floater_voice_effect.xml | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 8f2f13dffe..8452fb55b7 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -41,31 +41,31 @@ name="expires" width="100" /> - + -- cgit v1.2.3 From 49d8b3f5195e854f8b87fd08098b54eeda51b0ae Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Sun, 23 May 2010 02:31:46 +0100 Subject: EXT-7337 WIP Voice morph previewing - Remove redundant play button now single-click preview is possible. --- indra/newview/skins/default/xui/en/floater_voice_effect.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 9a6c21c7f2..d0c503f7b8 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -155,6 +155,7 @@ + -- cgit v1.2.3 From 6e98ca08300fad1fa8a4a5ab3996e1a6f8318564 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Sun, 23 May 2010 04:35:31 +0100 Subject: EXT-7337 WIP Voice morph previewing. Remove the activate button in the preview floater for now, it doesn't work in capture mode. Remove the remains of the play button. --- indra/newview/llfloatervoiceeffect.cpp | 45 +++++++-------- indra/newview/llfloatervoiceeffect.h | 2 +- .../skins/default/xui/en/floater_voice_effect.xml | 65 +++------------------- 3 files changed, 30 insertions(+), 82 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 0fa6135da2..1afea66d91 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -45,7 +45,7 @@ LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key) mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); mCommitCallbackRegistrar.add("VoiceEffect.Stop", boost::bind(&LLFloaterVoiceEffect::onClickStop, this)); mCommitCallbackRegistrar.add("VoiceEffect.Add", boost::bind(&LLFloaterVoiceEffect::onClickAdd, this)); - mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); +// mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); } // virtual @@ -70,7 +70,7 @@ BOOL LLFloaterVoiceEffect::postBuild() if (mVoiceEffectList) { mVoiceEffectList->setCommitCallback(boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); - mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); +// mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); } LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); @@ -133,7 +133,7 @@ void LLFloaterVoiceEffect::refreshEffectList() element["columns"][0]["column"] = "name"; element["columns"][0]["value"] = getString("no_voice_effect"); element["columns"][0]["font"]["name"] = "SANSSERIF"; - element["columns"][0]["font"]["style"] = "BOLD"; + element["columns"][0]["font"]["style"] = "ITALIC"; LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( @@ -152,9 +152,16 @@ void LLFloaterVoiceEffect::refreshEffectList() std::string effect_name = it->first; LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id); + + // Tag the active effect. + if (effect_id == LLVoiceClient::instance().getVoiceEffectDefault()) + { + effect_name += " " + getString("active_voice_effect"); + } + + std::string expiry_date = effect_properties["expiry_date"].asString(); bool is_template_only = effect_properties["template_only"].asBoolean(); bool is_new = effect_properties["is_new"].asBoolean(); - std::string expiry_date = effect_properties["expiry_date"].asString(); std::string font_style = "NORMAL"; if (!is_template_only) @@ -168,6 +175,7 @@ void LLFloaterVoiceEffect::refreshEffectList() element["columns"][0]["value"] = effect_name; element["columns"][0]["font"]["name"] = "SANSSERIF"; element["columns"][0]["font"]["style"] = font_style; + element["columns"][1]["column"] = "new"; element["columns"][1]["value"] = is_new ? getString("new_voice_effect") : ""; element["columns"][1]["font"]["name"] = "SANSSERIF"; @@ -194,8 +202,6 @@ void LLFloaterVoiceEffect::refreshEffectList() mVoiceEffectList->selectByID(*it); } mVoiceEffectList->setScrollPos(scroll_pos); - - mVoiceEffectList->setValue(effect_interface->getVoiceEffect()); mVoiceEffectList->setEnabled(true); } @@ -213,16 +219,6 @@ void LLFloaterVoiceEffect::updateControls() getChild("record_btn")->setVisible(!recording); getChild("record_stop_btn")->setVisible(recording); - - getChild("play_btn")->setVisible(!playing); - getChild("play_stop_btn")->setVisible(playing); - - getChild("play_btn")->setEnabled(effect_interface->isPreviewReady()); - - if (!mVoiceEffectList) - { - mVoiceEffectList->setValue(effect_interface->getVoiceEffect()); - } } // virtual @@ -281,11 +277,12 @@ void LLFloaterVoiceEffect::onClickAdd() LLWeb::loadURL(getString("get_voice_effects_url")); } -void LLFloaterVoiceEffect::onClickActivate() -{ - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface && mVoiceEffectList) - { - effect_interface->setVoiceEffect(mVoiceEffectList->getCurrentID()); - } -} +//void LLFloaterVoiceEffect::onClickActivate() +//{ +// LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +// if (effect_interface && mVoiceEffectList) +// { +// effect_interface->setVoiceEffect(mVoiceEffectList->getCurrentID()); +// } +//} + diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h index 060ffc99e9..ed38cd6925 100644 --- a/indra/newview/llfloatervoiceeffect.h +++ b/indra/newview/llfloatervoiceeffect.h @@ -63,7 +63,7 @@ private: void onClickPlay(); void onClickStop(); void onClickAdd(); - void onClickActivate(); +// void onClickActivate(); LLUUID mSelectedID; LLScrollListCtrl* mVoiceEffectList; diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index d0c503f7b8..728beece6b 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -14,11 +14,14 @@ min_width="240" width="313"> - No Voice Effect + (No Voice Effect) http://secondlife.com/landing/v0icem0rphingt3st + + (Active) + New! @@ -38,8 +41,8 @@ - + @@ -86,6 +89,7 @@ + - - -- cgit v1.2.3 From 234b3edc26db7cf87a11fc16d9720bf4a9c20177 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Sun, 23 May 2010 14:11:48 +0100 Subject: EXT-7337 WIP Added explanatory note to the voice morph preview floater --- indra/newview/llfloatervoiceeffect.cpp | 2 ++ .../skins/default/xui/en/floater_voice_effect.xml | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 1afea66d91..49dd6fa4d9 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -65,6 +65,8 @@ LLFloaterVoiceEffect::~LLFloaterVoiceEffect() BOOL LLFloaterVoiceEffect::postBuild() { setDefaultBtn("record_btn"); + getChild("record_btn")->setFocus(true); + mVoiceEffectList = getChild("voice_effect_list"); if (mVoiceEffectList) diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 728beece6b..acd70bce8e 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -2,7 +2,7 @@ --> + + Record a sample of your voice, and then select an effect to preview. Close this window to return to in-world voice. + - - + right="-10" + top="25"> Record a sample of your voice, and then select an effect to preview. Close this window to return to in-world voice. + + + + + + + [[URL] Get Voice Morphing] + -- cgit v1.2.3 From 1077ab49c171c0f310f9b76b360ea2ad162a31ff Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 15:19:33 -0700 Subject: Just enough hackery to get minidumps into Wind'ohs crash reports. Code clean up needed. --- indra/newview/llappviewerwin32.cpp | 5 +++-- indra/newview/llwindebug.cpp | 28 +++++++++++----------------- 2 files changed, 14 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 60a6d2f072..4bee8d9ac5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -529,8 +529,9 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } bool LLAppViewerWin32::restoreErrorTrap() -{ - return LLWinDebug::checkExceptionHandler(); +{ + return true; + //return LLWinDebug::checkExceptionHandler(); } void LLAppViewerWin32::handleSyncCrashTrace() diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index 59bc9dc62b..9f8585f163 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -718,7 +718,8 @@ BOOL PreventSetUnhandledExceptionFilter() // static void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) { - + return; +#if 0 static bool s_first_run = true; // Load the dbghelp dll now, instead of waiting for the crash. // Less potential for stack mangling @@ -762,34 +763,27 @@ void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(filter_func); - - // *REMOVE:Mani - //PreventSetUnhandledExceptionFilter(); + PVOID added_filter = + AddVectoredExceptionHandler(0, filter_func); - if(prev_filter != gFilterFunc) + if(added_filter == 0) { LL_WARNS("AppInit") - << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; + << "Failed to add exception handler (" << added_filter << ") !" << LL_ENDL; } gFilterFunc = filter_func; +#endif } bool LLWinDebug::checkExceptionHandler() { bool ok = true; - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(gFilterFunc); - if (prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; - ok = false; - } + RemoveVectoredExceptionHandler(gFilterFunc); + PVOID filter = AddVectoredExceptionHandler(0, gFilterFunc); - if (prev_filter == NULL) + if (filter == NULL) { ok = FALSE; if (gFilterFunc == NULL) @@ -798,7 +792,7 @@ bool LLWinDebug::checkExceptionHandler() } else { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; + LL_WARNS("AppInit") << "Failed to add exception handler (" << (void *)gFilterFunc << ")!" << LL_ENDL; } } -- cgit v1.2.3 From f24c312f8369fbc6ec4eb0607e7e8ea636aacb82 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 15:59:26 -0700 Subject: so long llwindebug, we hardly knew ye. --- indra/newview/CMakeLists.txt | 3 - indra/newview/llappviewer.cpp | 5 - indra/newview/llappviewerwin32.cpp | 55 --- indra/newview/llstartup.cpp | 1 - indra/newview/llviewermessage.cpp | 4 - indra/newview/llwindebug.cpp | 906 ------------------------------------- indra/newview/llwindebug.h | 75 --- 7 files changed, 1049 deletions(-) delete mode 100644 indra/newview/llwindebug.cpp delete mode 100644 indra/newview/llwindebug.h (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f2bed843c9..4571aa1074 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1055,7 +1055,6 @@ set(viewer_HEADER_FILES llwearabletype.h llweb.h llwind.h - llwindebug.h llwlanimator.h llwldaycycle.h llwlparammanager.h @@ -1130,12 +1129,10 @@ endif (LINUX) if (WINDOWS) list(APPEND viewer_SOURCE_FILES llappviewerwin32.cpp - llwindebug.cpp ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h - llwindebug.h ) # precompiled header configuration diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 56486c788b..e9ec0b8b77 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -104,7 +104,6 @@ #include #if LL_WINDOWS - #include "llwindebug.h" # include // For _SH_DENYWR in initMarkerFile #else # include // For initMarkerFile support @@ -3288,10 +3287,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; -#if LL_WINDOWS - // Generates the minidump. - LLWinDebug::generateCrashStacks(NULL); -#endif LLAppViewer::handleSyncViewerCrash(); LLAppViewer::handleViewerCrash(); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4bee8d9ac5..88d8dba8af 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -57,8 +57,6 @@ #include "llweb.h" #include "llsecondlifeurls.h" -#include "llwindebug.h" - #include "llviewernetwork.h" #include "llmd5.h" #include "llfindlocale.h" @@ -81,51 +79,6 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); - // *TODO: Translate the signals/exceptions into cross-platform stuff - // Windows implementation - _tprintf( _T("Entering Windows Exception Handler...\n") ); - llinfos << "Entering Windows Exception Handler..." << llendl; - - // Make sure the user sees something to indicate that the app crashed. - LONG retval; - - if (LLApp::isError()) - { - _tprintf( _T("Got another fatal signal while in the error handler, die now!\n") ); - llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; - } - - // Generate a minidump if we can. - // Before we wake the error thread... - // Which will start the crash reporting. - LLWinDebug::generateCrashStacks(exception_infop); - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); - } - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; -} - // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -191,8 +144,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - - LLWinDebug::initExceptionHandler(viewer_windows_exception_handler); viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); @@ -405,12 +356,6 @@ bool LLAppViewerWin32::cleanup() bool LLAppViewerWin32::initLogging() { - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // *NOTE: This should happen before the we send a 'previous instance froze' - // crash report, but it must happen after we initialize the DirUtil. - LLWinDebug::clearCrashStacks(); - return LLAppViewer::initLogging(); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a84bb98a90..e43b3b84c8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,7 +199,6 @@ #include "llstartuplistener.h" #if LL_WINDOWS -#include "llwindebug.h" #include "lldxhardware.h" #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fb87e2d3b9..c677406223 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -110,10 +110,6 @@ #include // #include -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h" // For the invalid message handler -#endif - #include "llnotificationmanager.h" // #if LL_MSVC diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp deleted file mode 100644 index 9f8585f163..0000000000 --- a/indra/newview/llwindebug.cpp +++ /dev/null @@ -1,906 +0,0 @@ -/** - * @file llwindebug.cpp - * @brief Windows debugging functions - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include -#include -#include "llwindebug.h" -#include "llviewercontrol.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" - -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - - -/* -LLSD Block for Windows Dump Information - - - Platform - - Process - - Module - - DateModified - - ExceptionCode - - ExceptionRead/WriteAddress - - Instruction - - Registers - - - EIP - ... - - - Call Stack - - - - ModuleName - - ModuleBaseAddress - - ModuleOffsetAddress - - Parameters - - - - - - - - - -*/ - - -extern void (*gCrashCallback)(void); - -// based on dbghelp.h -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - -MINIDUMPWRITEDUMP f_mdwp = NULL; - -#undef UNICODE - -static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; - -HMODULE hDbgHelp; - -// Tool Help functions. -typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); -typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); -typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - -CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; -MODULE32_FIRST Module32First_; -MODULE32_NEST Module32Next_; - -#define DUMP_SIZE_MAX 8000 //max size of our dump -#define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls -#define NL L"\r\n" //new line - - -typedef struct STACK -{ - STACK * Ebp; - PBYTE Ret_Addr; - DWORD Param[0]; -} STACK, * PSTACK; - -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr); -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info); - -void printError( CHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg ); -} - -BOOL GetProcessThreadIDs(DWORD process_id, std::vector& thread_ids) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if( hThreadSnap == INVALID_HANDLE_VALUE ) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if( !Thread32First( hThreadSnap, &te32 ) ) - { - printError( "Thread32First" ); // Show cause of failure - CloseHandle( hThreadSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if( te32.th32OwnerProcessID == process_id ) - { - thread_ids.push_back(te32.th32ThreadID); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - -// Don't forget to clean up the snapshot object. - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -BOOL GetThreadCallStack(DWORD thread_id, LLSD& info) -{ - if(GetCurrentThreadId() == thread_id) - { - // Early exit for the current thread. - // Suspending the current thread would be a bad idea. - // Plus you can't retrieve a valid current thread context. - return false; - } - - HANDLE thread_handle = INVALID_HANDLE_VALUE; - thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); - if(INVALID_HANDLE_VALUE == thread_handle) - { - return FALSE; - } - - BOOL result = false; - if(-1 != SuspendThread(thread_handle)) - { - CONTEXT context_struct; - context_struct.ContextFlags = CONTEXT_FULL; - if(GetThreadContext(thread_handle, &context_struct)) - { - Get_Call_Stack(NULL, &context_struct, info); - result = true; - } - ResumeThread(thread_handle); - } - else - { - // Couldn't suspend thread. - } - - CloseHandle(thread_handle); - return result; -} - - -//Windows Call Stack Construction idea from -//http://www.codeproject.com/tools/minidump.asp - -//**************************************************************************************** -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr) -//**************************************************************************************** -// Find module by Ret_Addr (address in the module). -// Return Module_Name (full path) and Module_Addr (start address). -// Return TRUE if found. -{ - MODULEENTRY32 M = {sizeof(M)}; - HANDLE hSnapshot; - - bool found = false; - - if (CreateToolhelp32Snapshot_) - { - hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); - - if ((hSnapshot != INVALID_HANDLE_VALUE) && - Module32First_(hSnapshot, &M)) - { - do - { - if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) - { - lstrcpyn(Module_Name, M.szExePath, MAX_PATH); - Module_Addr = M.modBaseAddr; - found = true; - break; - } - } while (Module32Next_(hSnapshot, &M)); - } - - CloseHandle(hSnapshot); - } - - return found; -} //Get_Module_By_Ret_Addr - -bool has_valid_call_before(PDWORD cur_stack_loc) -{ - PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1); - PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2); - PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5); - PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6); - - // make sure we can read it - if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE))) - { - return false; - } - - // check for 9a + 4 bytes - if(*p_fifth_byte == 0x9A) - { - return true; - } - - // Check for E8 + 4 bytes and last byte is 00 or FF - if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF)) - { - return true; - } - - // the other is six bytes - if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF) - { - return true; - } - - return false; -} - -PBYTE get_valid_frame(PBYTE esp) -{ - PDWORD cur_stack_loc = NULL; - const int max_search = 400; - WCHAR module_name[MAX_PATH]; - PBYTE module_addr = 0; - - // round to highest multiple of four - esp = (esp + (4 - ((int)esp % 4)) % 4); - - // scroll through stack a few hundred places. - for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1) - { - // if you can read the pointer, - if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD))) - { - continue; - } - - // check if it's in a module - if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr)) - { - continue; - } - - // check if the code before the instruction ptr is a call - if(!has_valid_call_before(cur_stack_loc)) - { - continue; - } - - // if these all pass, return that ebp, otherwise continue till we're dead - return (PBYTE)(cur_stack_loc - 1); - } - - return NULL; -} - -bool shouldUseStackWalker(PSTACK Ebp, int max_depth) -{ - WCHAR Module_Name[MAX_PATH]; - PBYTE Module_Addr = 0; - int depth = 0; - - while (depth < max_depth) - { - if (IsBadReadPtr(Ebp, sizeof(PSTACK)) || - IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || - Ebp->Ebp < Ebp || - Ebp->Ebp - Ebp > 0xFFFFFF || - IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) || - !Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - return true; - } - depth++; - Ebp = Ebp->Ebp; - } - - return false; -} - -//****************************************************************** -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info) -//****************************************************************** -// Fill Str with call stack info. -// pException can be either GetExceptionInformation() or NULL. -// If pException = NULL - get current call stack. -{ - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr = 0; - LLSD params; - PBYTE Esp = NULL; - LLSD tmp_info; - - bool fake_frame = false; - bool ebp_used = false; - const int HEURISTIC_MAX_WALK = 20; - int heuristic_walk_i = 0; - int Ret_Addr_I = 0; - - STACK Stack = {0, 0}; - PSTACK Ebp; - - if (exception_record && context_record) //fake frame for exception address - { - Stack.Ebp = (PSTACK)(context_record->Ebp); - Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; - Ebp = &Stack; - Esp = (PBYTE) context_record->Esp; - fake_frame = true; - } - else if(context_record) - { - Ebp = (PSTACK)(context_record->Ebp); - Esp = (PBYTE)(context_record->Esp); - } - else - { - Ebp = (PSTACK)&exception_record - 1; //frame addr of Get_Call_Stack() - Esp = (PBYTE)&exception_record; - - // Skip frame of Get_Call_Stack(). - if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) - Ebp = Ebp->Ebp; //caller ebp - } - - // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. - // Break trace on wrong stack frame. - for (Ret_Addr_I = 0; - heuristic_walk_i < HEURISTIC_MAX_WALK && - Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); - Ret_Addr_I++) - { - // If module with Ebp->Ret_Addr found. - if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); - tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; - tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); - - // Save 5 params of the call. We don't know the real number of params. - if (fake_frame && !Ret_Addr_I) //fake frame for exception address - params[0] = "Exception Offset"; - else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) - { - for(int j = 0; j < 5; ++j) - { - params[j] = (int)Ebp->Param[j]; - } - } - tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; - } - - tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; - - // get ready for next frame - // Set ESP to just after return address. Not the real esp, but just enough after the return address - if(!fake_frame) { - Esp = (PBYTE)Ebp + 8; - } - else - { - fake_frame = false; - } - - // is next ebp valid? - // only run if we've never found a good ebp - // and make sure the one after is valid as well - if( !ebp_used && - shouldUseStackWalker(Ebp, 2)) - { - heuristic_walk_i++; - PBYTE new_ebp = get_valid_frame(Esp); - if (new_ebp != NULL) - { - Ebp = (PSTACK)new_ebp; - } - } - else - { - ebp_used = true; - Ebp = Ebp->Ebp; - } - } -/* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer - // Now go back through and edit out heuristic stacks that could very well be bogus. - // Leave the top and the last 3 stack chosen by the heuristic, however. - if(heuristic_walk_i > 2) - { - info["CallStack"][0] = tmp_info["CallStack"][0]; - std::string ttest = info["CallStack"][0]["ModuleName"]; - for(int cur_frame = 1; - (cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); - ++cur_frame) - { - // edit out the middle heuristic found frames - info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; - } - } - else - { - info = tmp_info; - } -*/ - info = tmp_info; - info["HeuristicWalkI"] = heuristic_walk_i; - info["EbpUsed"] = ebp_used; - -} //Get_Call_Stack - -//*********************************** -void WINAPI Get_Version_Str(LLSD& info) -//*********************************** -// Fill Str with Windows version. -{ - OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later - - if (!GetVersionEx((POSVERSIONINFO)&V)) - { - ZeroMemory(&V, sizeof(V)); - V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx((POSVERSIONINFO)&V); - } - - if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) - V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx - - info["Platform"] = llformat("Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,... - V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType); -} //Get_Version_Str - -//************************************************************* -LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) -//************************************************************* -// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. -{ - LLSD info; - LPWSTR Str; - int Str_Len; -// int i; - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr; - HANDLE hFile; - FILETIME Last_Write_Time; - FILETIME Local_File_Time; - SYSTEMTIME T; - - Str = new WCHAR[DUMP_SIZE_MAX]; - Str_Len = 0; - if (!Str) - return NULL; - - Get_Version_Str(info); - - GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); - info["ThreadID"] = (S32)GetCurrentThreadId(); - - // If exception occurred. - if (pException) - { - EXCEPTION_RECORD & E = *pException->ExceptionRecord; - CONTEXT & C = *pException->ContextRecord; - - // If module with E.ExceptionAddress found - save its path and date. - if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) - { - info["Module"] = ll_convert_wide_to_string(Module_Name); - - if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) - { - if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) - { - FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); - FileTimeToSystemTime(&Local_File_Time, &T); - - info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); - } - CloseHandle(hFile); - } - } - else - { - info["ExceptionAddr"] = (int)E.ExceptionAddress; - } - - info["ExceptionCode"] = (int)E.ExceptionCode; - - /* - //TODO: Fix this - if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - { - // Access violation type - Write/Read. - LLSD exception_info; - exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; - exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); - info["Exception Information"] = exception_info; - } - */ - - - // Save instruction that caused exception. - /* - std::string str; - for (i = 0; i < 16; i++) - str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); - info["Instruction"] = str; - */ - LLSD registers; - registers["EAX"] = (int)C.Eax; - registers["EBX"] = (int)C.Ebx; - registers["ECX"] = (int)C.Ecx; - registers["EDX"] = (int)C.Edx; - registers["ESI"] = (int)C.Esi; - registers["EDI"] = (int)C.Edi; - registers["ESP"] = (int)C.Esp; - registers["EBP"] = (int)C.Ebp; - registers["EIP"] = (int)C.Eip; - registers["EFlags"] = (int)C.EFlags; - info["Registers"] = registers; - } //if (pException) - - // Save call stack info. - Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); - - return info; -} //Get_Exception_Info - -#define UNICODE - - -class LLMemoryReserve { -public: - LLMemoryReserve(); - ~LLMemoryReserve(); - void reserve(); - void release(); -protected: - unsigned char *mReserve; - static const size_t MEMORY_RESERVATION_SIZE; -}; - -LLMemoryReserve::LLMemoryReserve() : - mReserve(NULL) -{ -}; - -LLMemoryReserve::~LLMemoryReserve() -{ - release(); -} - -// I dunno - this just seemed like a pretty good value. -const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024; - -void LLMemoryReserve::reserve() -{ - if(NULL == mReserve) - mReserve = new unsigned char[MEMORY_RESERVATION_SIZE]; -}; - -void LLMemoryReserve::release() -{ - delete [] mReserve; - mReserve = NULL; -}; - -static LLMemoryReserve gEmergencyMemoryReserve; - -#ifndef _M_IX86 - #error "The following code only works for x86!" -#endif -LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( - LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ - if(lpTopLevelExceptionFilter == gFilterFunc) - return gFilterFunc; - - llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl; - LLSD cs_info; - Get_Call_Stack(NULL, NULL, cs_info); - - if(cs_info.has("CallStack") && cs_info["CallStack"].isArray()) - { - LLSD cs = cs_info["CallStack"]; - for(LLSD::array_iterator i = cs.beginArray(); - i != cs.endArray(); - ++i) - { - llinfos << "Module: " << (*i)["ModuleName"] << llendl; - } - } - - return gFilterFunc; -} - -BOOL PreventSetUnhandledExceptionFilter() -{ - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); - if (hKernel32 == NULL) - return FALSE; - - void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); - if(pOrgEntry == NULL) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory(GetCurrentProcess(), - pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); - return bRet; -} - -// static -void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) -{ - return; -#if 0 - static bool s_first_run = true; - // Load the dbghelp dll now, instead of waiting for the crash. - // Less potential for stack mangling - - if (s_first_run) - { - // First, try loading from the directory that the app resides in. - std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); - - HMODULE hDll = NULL; - hDll = LoadLibraryA(local_dll_name.c_str()); - if (!hDll) - { - hDll = LoadLibrary(L"dbghelp.dll"); - } - - if (!hDll) - { - LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; - } - else - { - f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); - - if (!f_mdwp) - { - FreeLibrary(hDll); - hDll = NULL; - } - } - - gEmergencyMemoryReserve.reserve(); - - s_first_run = false; - } - - // Try to get Tool Help library functions. - HMODULE hKernel32; - hKernel32 = GetModuleHandle(_T("KERNEL32")); - CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); - Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); - Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - - PVOID added_filter = - AddVectoredExceptionHandler(0, filter_func); - - if(added_filter == 0) - { - LL_WARNS("AppInit") - << "Failed to add exception handler (" << added_filter << ") !" << LL_ENDL; - } - - gFilterFunc = filter_func; -#endif -} - -bool LLWinDebug::checkExceptionHandler() -{ - bool ok = true; - - RemoveVectoredExceptionHandler(gFilterFunc); - PVOID filter = AddVectoredExceptionHandler(0, gFilterFunc); - - if (filter == NULL) - { - ok = FALSE; - if (gFilterFunc == NULL) - { - LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; - } - else - { - LL_WARNS("AppInit") << "Failed to add exception handler (" << (void *)gFilterFunc << ")!" << LL_ENDL; - } - } - - return ok; -} - -void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename) -{ - if(f_mdwp == NULL || gDirUtilp == NULL) - { - return; - //write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n"); - } - else - { - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - - HANDLE hFile = CreateFileA(dump_path.c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile != INVALID_HANDLE_VALUE) - { - // Write the dump, ignoring the return value - f_mdwp(GetCurrentProcess(), - GetCurrentProcessId(), - hFile, - type, - ExInfop, - NULL, - NULL); - - CloseHandle(hFile); - } - - } -} - -// static -void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - This method is no longer the exception handler. - // Its called from viewer_windows_exception_handler() and other places. - - // - // Let go of a bunch of reserved memory to give library calls etc - // a chance to execute normally in the case that we ran out of - // memory. - // - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SecondLifeException"); - std::string log_path = dump_path + ".log"; - - if (exception_infop) - { - // Since there is exception info... Release the hounds. - gEmergencyMemoryReserve.release(); - - if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - - ExInfo.ThreadId = ::GetCurrentThreadId(); - ExInfo.ExceptionPointers = exception_infop; - ExInfo.ClientPointers = NULL; - - writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp"); - writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); - } - - info = Get_Exception_Info(exception_infop); - } - - LLSD threads; - std::vector thread_ids; - GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); - - for(std::vector::iterator th_itr = thread_ids.begin(); - th_itr != thread_ids.end(); - ++th_itr) - { - LLSD thread_info; - if(*th_itr != GetCurrentThreadId()) - { - GetThreadCallStack(*th_itr, thread_info); - } - - if(thread_info) - { - threads[llformat("ID %d", *th_itr)] = thread_info; - } - } - - info["Threads"] = threads; - - llofstream out_file(log_path); - LLSDSerialize::toPrettyXML(info, out_file); - out_file.close(); -} - -void LLWinDebug::clearCrashStacks() -{ - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException.log"); - LLFile::remove(dump_path); -} diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h deleted file mode 100644 index f4a6a2d54d..0000000000 --- a/indra/newview/llwindebug.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file llwindebug.h - * @brief LLWinDebug class header file - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWINDEBUG_H -#define LL_LLWINDEBUG_H - -#include "stdtypes.h" -#include - -class LLWinDebug -{ -public: - - /** - * @brief initialize the llwindebug exception filter callback - * - * Hand a windows unhandled exception filter to LLWinDebug - * This method should only be called to change the - * exception filter used by llwindebug. - * - * Setting filter_func to NULL will clear any custom filters. - **/ - static void initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func); - - /** - * @brief check the status of the exception filter. - * - * Resets unhandled exception filter to the filter specified - * w/ initExceptionFilter). - * Returns false if the exception filter was modified. - * - * *NOTE:Mani In the past mozlib has been accused of - * overriding the exception filter. If the mozlib filter - * is required, perhaps we can chain calls from our - * filter to mozlib's. - **/ - static bool checkExceptionHandler(); - - static void generateCrashStacks(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); - static void clearCrashStacks(); // Delete the crash stack file(s). - - static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); -private: -}; - -#endif // LL_LLWINDEBUG_H -- cgit v1.2.3 From 563ae1c7e029ceef2aed0b85623c2f0a95d38b46 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Tue, 25 May 2010 02:47:28 +0100 Subject: EXT-7337 WIP Replace the new column with a (New!) tag after the voice effect name --- indra/newview/llfloatervoiceeffect.cpp | 24 ++++++++++++---------- .../skins/default/xui/en/floater_voice_effect.xml | 12 ++++------- 2 files changed, 17 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 9529f947c1..46356cf161 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -145,6 +145,7 @@ void LLFloaterVoiceEffect::refreshEffectList() } } + // Add each Voice Effect template, if there are any (template list includes all usable effects) const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList(); if (!template_list.empty()) { @@ -161,15 +162,21 @@ void LLFloaterVoiceEffect::refreshEffectList() effect_name += " " + getString("active_voice_effect"); } + // Tag available effects that are new this session + if (effect_properties["is_new"].asBoolean()) + { + effect_name += " " + getString("new_voice_effect"); + } + LLDate expiry_date = effect_properties["expiry_date"].asDate(); bool is_template_only = effect_properties["template_only"].asBoolean(); - bool is_new = effect_properties["is_new"].asBoolean(); std::string font_style = "NORMAL"; if (!is_template_only) { font_style = "BOLD"; } + LLSD element; element["id"] = effect_id; @@ -178,21 +185,16 @@ void LLFloaterVoiceEffect::refreshEffectList() element["columns"][0]["font"]["name"] = "SANSSERIF"; element["columns"][0]["font"]["style"] = font_style; - element["columns"][1]["column"] = "new"; - element["columns"][1]["value"] = is_new ? getString("new_voice_effect") : ""; - element["columns"][1]["font"]["name"] = "SANSSERIF"; - element["columns"][1]["font"]["style"] = font_style; - - element["columns"][2]["column"] = "expires"; + element["columns"][1]["column"] = "expires"; if (!is_template_only) { - element["columns"][2]["value"] = expiry_date; + element["columns"][1]["value"] = expiry_date; } else { - element["columns"][2]["value"] = ""; + element["columns"][1]["value"] = ""; } - element["columns"][2]["font"]["name"] = "SANSSERIF"; - element["columns"][2]["font"]["style"] = font_style; + element["columns"][1]["font"]["name"] = "SANSSERIF"; + element["columns"][1]["font"]["style"] = font_style; LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 73e4a694eb..f79d4fd35c 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -20,7 +20,7 @@ (Active) - New! + (New!) - + dynamic_width="true" + label="Voice Effect" + name="name"/> Date: Tue, 25 May 2010 03:36:36 +0100 Subject: EXT-7337 WIP Further tweaking of Voice Effect preview layout --- indra/newview/llfloatervoiceeffect.cpp | 5 ++- .../skins/default/xui/en/floater_voice_effect.xml | 51 +++++++++++----------- 2 files changed, 29 insertions(+), 27 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index 46356cf161..b47d562995 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -189,19 +189,20 @@ void LLFloaterVoiceEffect::refreshEffectList() if (!is_template_only) { element["columns"][1]["value"] = expiry_date; + element["columns"][1]["type"] = "date"; } else { element["columns"][1]["value"] = ""; } element["columns"][1]["font"]["name"] = "SANSSERIF"; - element["columns"][1]["font"]["style"] = font_style; + element["columns"][1]["font"]["style"] = "NORMAL"; LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( if(sl_item) { LLFontGL::StyleFlags style = is_template_only ? LLFontGL::NORMAL : LLFontGL::BOLD; - ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(style); + dynamic_cast(sl_item->getColumn(0))->setFontStyle(style); } } } diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index f79d4fd35c..4f4b20066d 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -11,8 +11,8 @@ label="Places" layout="topleft" min_height="350" - min_width="240" - width="300"> + min_width="300" + width="455"> (No Voice Effect) @@ -33,18 +33,19 @@ name="status_text" right="-10" top="25"> - Record a sample of your voice, and then select an effect to preview. Close this window to return to in-world voice. +Record a sample of your voice, and then select an effect to preview. +Close this window to return to in-world voice. @@ -56,41 +57,41 @@ left_delta="0" name="record_stop_btn" top_delta="0" - width="135"> + width="150"> + + [[URL] Get Voice Morphing] + + name="name" relative_width="0.41"/> + relative_width="0.59" /> - - [[URL] Get Voice Morphing] - -- cgit v1.2.3 From 76fc600e948f8c8ae9723f8ec5559408de5dc87f Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Tue, 25 May 2010 13:51:28 +0100 Subject: EXT-7138 WIP Made selecting voice effects while the Voice Control Panel is docked work properly. --- indra/newview/llpanelvoiceeffect.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index f4f0ea3ee7..518afc5eb3 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -39,6 +39,7 @@ #include "llfloaterreg.h" #include "llpanel.h" #include "lltrans.h" +#include "lltransientfloatermgr.h" #include "llvoiceclient.h" static LLRegisterPanelClassWrapper t_panel_voice_effect("panel_voice_effect"); @@ -51,6 +52,9 @@ LLPanelVoiceEffect::LLPanelVoiceEffect() LLPanelVoiceEffect::~LLPanelVoiceEffect() { + LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); + LLTransientFloaterMgr::getInstance()->removeControlView(combo_list_view); + if(LLVoiceClient::instanceExists()) { LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); @@ -66,6 +70,11 @@ BOOL LLPanelVoiceEffect::postBuild() { mVoiceEffectCombo = getChild("voice_effect"); + // Need to tell LLTransientFloaterMgr about the combo list, otherwise it can't + // be clicked while in a docked floater as it extends outside the floater area. + LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); + LLTransientFloaterMgr::getInstance()->addControlView(combo_list_view); + LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); if (effect_interface) { -- cgit v1.2.3 From 5a52c5eb8a5cc4e1215911bac9121891dd802d45 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 25 May 2010 13:32:12 -0700 Subject: Mac crash behavior matches windows and linux: report on crash (not after restart). This is OK because we use Breakpad generated minidumps instead of OS generated ones. --- indra/newview/llappviewer.cpp | 26 ++++---------------------- indra/newview/llappviewermacosx.cpp | 32 -------------------------------- 2 files changed, 4 insertions(+), 54 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e9ec0b8b77..418b587321 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -102,6 +102,8 @@ // Third party library includes #include +#include + #if LL_WINDOWS # include // For _SH_DENYWR in initMarkerFile @@ -2281,17 +2283,7 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS - //*NOTE:Mani The current state of the crash handler has the MacOSX - // sending all crash reports as freezes, in order to let - // the MacOSX CrashRepoter generate stacks before spawning the - // SL crash logger. - // The Linux and Windows clients generate their own stacks and - // spawn the SL crash logger immediately. This may change in the future. -#if LL_DARWIN - if(gLastExecEvent != LAST_EXEC_NORMAL) -#else if (gLastExecEvent == LAST_EXEC_FROZE) -#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2552,9 +2544,6 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Make sure the watchdog gets turned off... -// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what @@ -2665,10 +2654,6 @@ void LLAppViewer::handleViewerCrash() LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2681,8 +2666,6 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); - -#endif //!LL_DARWIN return; } @@ -3287,9 +3270,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; - LLAppViewer::handleSyncViewerCrash(); - LLAppViewer::handleViewerCrash(); - std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3302,6 +3282,8 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); + + LLApp::instance()->getExceptionHandler()->WriteMinidump(); } // This routine may get called more than once during the shutdown process. diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 0b5f18c330..2f12ad7e38 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -384,38 +384,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) } } - - if(!reportFreeze) - { - _exit(1); - } - - // TODO from palmer: Find a better way to handle managing old crash logs - // when this is a separate imbedable module. Ideally just sort crash stack - // logs based on date, and grab the latest one as opposed to deleting them - // for thoughts on what the module would look like. - // See: https://wiki.lindenlab.com/wiki/Viewer_Crash_Reporter_Round_4 - - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // The old crash stack is invalid for the next crash report. - char path[MAX_PATH]; - FSRef folder; - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - std::string pathname = std::string(path) + std::string("/CrashReporter/"); - std::string mask = "Second Life*"; - std::string file_name; - while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) - { - LLFile::remove(pathname + file_name); - } - } - } - } std::string LLAppViewerMacOSX::generateSerialNumber() -- cgit v1.2.3 From 6a39149fec72e3a105d7a47b8a9f5aa2a0bfba87 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 25 May 2010 15:08:36 -0700 Subject: Added configuration setting to send crash reports to configured url rather than through the grid. --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 7 +++++++ 2 files changed, 18 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f71662a7c8..6dcbb4e57a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,6 +1,17 @@ + CrashHostUrl + + Comment + A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler. + Persist + 1 + Type + String + Value + + AFKTimeout Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 418b587321..7cdd8ca309 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2545,6 +2545,13 @@ void LLAppViewer::handleViewerCrash() } pApp->mReportedCrash = TRUE; + // Insert crash host url (url to post crash log to) if configured. + std::string crashHostUrl = gSavedSettings.get("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } + //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); -- cgit v1.2.3 From 80b9e6b3fb5086a8d4506a95787a9e84d0e46fb8 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 26 May 2010 12:55:30 +0100 Subject: EXT-7138 WIP Improved debug logging around voice font expiry --- indra/newview/llvoicevivox.cpp | 54 ++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 17f4b661be..9ce6ae521e 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6551,35 +6551,36 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, voice_font_map_t::iterator iter = font_map.find(font_id); bool new_font = (iter == font_map.end()); - // If it is a new (unexpired) font create a new entry, otherwise update the existing one. if (new_font) { - if (!has_expired) - { - font = new voiceFontEntry(font_id); - } - else + if (has_expired) { - LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id - << " (" << font_index << ") : " << name << " has expired." << LL_ENDL; + // If it's new and already marked expired, ignore it. + return; } + // If it is a new (unexpired) font create a new entry. + font = new voiceFontEntry(font_id); } else { + // Not a new font, update the existing entry font = iter->second; } if (font) { - // Remove fonts that have expired since we last saw them. + // Remove existing fonts that have expired since we last saw them. if (has_expired) { - LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id - << " (" << font_index << ") : " << name << " has expired, removing." - << LL_ENDL; + LL_DEBUGS("Voice") << "Expired " << (template_font ? "Template: " : ":") + << font->mExpirationDate.asString() << font_id + << " (" << font_index << ") " << name << LL_ENDL; - deleteVoiceFont(font_id); + if (!template_font) + { + deleteVoiceFont(font_id); + } return; } @@ -6591,10 +6592,22 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, font->mFontType = font_type; font->mFontStatus = font_status; + LL_DEBUGS("Voice") << (template_font ? "Template: " : "") + << font->mExpirationDate.asString() << font->mID + << " (" << font->mFontIndex << ") " << name << LL_ENDL; + // Set the expiry timer to trigger a notification when the voice font can no longer be used. font->mExpiryTimer.start(); font->mExpiryTimer.setExpiryAt(expiration_date.secondsSinceEpoch()); + if (font->mExpiryTimer.hasExpired()) + { + // Should never happen, but check anyway. + LL_DEBUGS("Voice") << "Voice font " << font->mID + << " expired " << font->mExpirationDate.asString() + << " but is not marked expired!" << LL_ENDL; + } + // Set the warning timer to some interval before actual expiry. S32 warning_time = gSavedSettings.getS32("VoiceEffectExpiryWarningTime"); if (warning_time != 0) @@ -6624,9 +6637,6 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, // Debugging stuff - LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id - << " (" << font_index << ") : " << name << LL_ENDL; - if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN) { LL_DEBUGS("Voice") << "Unknown voice font type: " << font_type << LL_ENDL; @@ -6717,6 +6727,7 @@ void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id) { if (list_iter->second == id) { + LL_DEBUGS("Voice") << "Removing " << id << " from the voice font list." << LL_ENDL; mVoiceFontList.erase(list_iter++); } else @@ -6884,6 +6895,8 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) void LLVivoxVoiceClient::notifyVoiceFontObservers(bool lists_changed) { + LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << lists_changed << LL_ENDL; + for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); it != mVoiceFontObservers.end(); ) @@ -7504,8 +7517,9 @@ LLDate LLVivoxProtocolParser::vivoxTimeStampToLLDate(const std::string& vivox_ts { LLDate ts; - // First check to see if it actually already is a parseable ISO8601 date, - // in case the format miraculously changes in future ;) + // First check to see if it actually already is an ISO 8601 date that + // LLDate::fromString() can parse. + // In case the format miraculously changes in future ;) if (ts.fromString(vivox_ts)) { return ts; @@ -7527,8 +7541,8 @@ LLDate LLVivoxProtocolParser::vivoxTimeStampToLLDate(const std::string& vivox_ts ts.fromString(time_stamp); if(!ts.fromString(time_stamp)) { - LL_WARNS_ONCE("Voice") << "Failed to parse Vivox timestamp: " << vivox_ts - << " to ISO 8601 date: " << time_stamp << LL_ENDL; + LL_WARNS_ONCE("VivoxProtocolParser") << "Failed to parse Vivox timestamp: " + << vivox_ts << " to ISO 8601 date: " << time_stamp << LL_ENDL; return LLDate(); } -- cgit v1.2.3 From 3c7df727eeb10a1e6adf27b7aa352afddfcd5d6d Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Wed, 26 May 2010 14:42:18 +0100 Subject: EXT-7138 WIP Simplify and improve detection and notification of changes to the Voice font list --- indra/newview/llvoicevivox.cpp | 98 +++++++++++++++++++++--------------------- indra/newview/llvoicevivox.h | 3 +- 2 files changed, 52 insertions(+), 49 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 9ce6ae521e..c8e4630e24 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -348,6 +348,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mVoiceFontsReceived(false), mVoiceFontsNew(false), + mVoiceFontListDirty(false), mCaptureBufferMode(false), mCaptureBufferRecording(false), @@ -1173,7 +1174,7 @@ void LLVivoxVoiceClient::stateMachine() mCaptureTimer.setTimerExpirySec(CAPTURE_BUFFER_MAX_TIME); // Update UI, should really use a separate callback. - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); setState(stateCaptureBufferRecording); break; @@ -1188,7 +1189,7 @@ void LLVivoxVoiceClient::stateMachine() mCaptureBufferRecording = false; // Update UI, should really use a separate callback. - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); setState(stateCaptureBufferPaused); } @@ -1202,7 +1203,7 @@ void LLVivoxVoiceClient::stateMachine() mPreviewVoiceFontLast = mPreviewVoiceFont; // Update UI, should really use a separate callback. - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); setState(stateCaptureBufferPlaying); break; @@ -1221,7 +1222,7 @@ void LLVivoxVoiceClient::stateMachine() mCaptureBufferPlaying = false; // Update UI, should really use a separate callback. - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); setState(stateCaptureBufferPaused); } @@ -1769,7 +1770,7 @@ void LLVivoxVoiceClient::stateMachine() { mAudioSessionChanged = false; notifyParticipantObservers(); - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); } else if (mAudioSession && mAudioSession->mParticipantsChanged) { @@ -6442,7 +6443,7 @@ bool LLVivoxVoiceClient::setVoiceEffect(const LLUUID& id) gSavedPerAccountSettings.setString("VoiceEffectDefault", id.asString()); sessionSetVoiceFontSendMessage(mAudioSession); - notifyVoiceFontObservers(false); + notifyVoiceFontObservers(); return true; } @@ -6551,15 +6552,26 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, voice_font_map_t::iterator iter = font_map.find(font_id); bool new_font = (iter == font_map.end()); - if (new_font) + if (has_expired) { - if (has_expired) + // Remove existing session fonts that have expired since we last saw them. + if (!new_font) { - // If it's new and already marked expired, ignore it. - return; + LL_DEBUGS("Voice") << "Expired " << (template_font ? "Template " : "") + << expiration_date.asString() << " " << font_id + << " (" << font_index << ") " << name << LL_ENDL; + + if (!template_font) + { + deleteVoiceFont(font_id); + } } + return; + } - // If it is a new (unexpired) font create a new entry. + if (new_font) + { + // If it is a new font create a new entry. font = new voiceFontEntry(font_id); } else @@ -6570,20 +6582,6 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, if (font) { - // Remove existing fonts that have expired since we last saw them. - if (has_expired) - { - LL_DEBUGS("Voice") << "Expired " << (template_font ? "Template: " : ":") - << font->mExpirationDate.asString() << font_id - << " (" << font_index << ") " << name << LL_ENDL; - - if (!template_font) - { - deleteVoiceFont(font_id); - } - return; - } - font->mFontIndex = font_index; // Use the description for the human readable name if available, as the // "name" may be a UUID. @@ -6592,8 +6590,8 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, font->mFontType = font_type; font->mFontStatus = font_status; - LL_DEBUGS("Voice") << (template_font ? "Template: " : "") - << font->mExpirationDate.asString() << font->mID + LL_DEBUGS("Voice") << (template_font ? "Template " : "") + << font->mExpirationDate.asString() << " " << font->mID << " (" << font->mFontIndex << ") " << name << LL_ENDL; // Set the expiry timer to trigger a notification when the voice font can no longer be used. @@ -6622,7 +6620,7 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, font->mExpiryWarningTimer.stop(); } - // Only flag it as a new font if we have already seen the font list. + // Only flag new session fonts. if (!template_font && mVoiceFontsReceived && new_font) { font->mIsNew = true; @@ -6635,6 +6633,8 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, font_list.insert(voice_effect_list_t::value_type(font->mName, font->mID)); } + mVoiceFontListDirty = true; + // Debugging stuff if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN) @@ -6706,7 +6706,7 @@ void LLVivoxVoiceClient::expireVoiceFonts() } // Refresh voice font lists in the UI. - notifyVoiceFontObservers(true); + notifyVoiceFontObservers(); } // Give a warning notification if any voice fonts are due to expire. @@ -6729,6 +6729,7 @@ void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id) { LL_DEBUGS("Voice") << "Removing " << id << " from the voice font list." << LL_ENDL; mVoiceFontList.erase(list_iter++); + mVoiceFontListDirty = true; } else { @@ -6866,22 +6867,15 @@ void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const st { setState(stateVoiceFontsReceived); } - mVoiceFontsReceived = true; - - // If new Voice Fonts have been found notify the user. - if (mVoiceFontsNew) - { - LLNotificationsUtil::add("VoiceEffectsNew"); - mVoiceFontsNew = false; - } - notifyVoiceFontObservers(true); + notifyVoiceFontObservers(); + mVoiceFontsReceived = true; } void LLVivoxVoiceClient::accountGetTemplateFontsResponse(int statusCode, const std::string &statusString) { // Voice font list entries were updated via addVoiceFont() during parsing. - notifyVoiceFontObservers(true); + notifyVoiceFontObservers(); } void LLVivoxVoiceClient::addObserver(LLVoiceEffectObserver* observer) { @@ -6893,19 +6887,30 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) mVoiceFontObservers.erase(observer); } -void LLVivoxVoiceClient::notifyVoiceFontObservers(bool lists_changed) +void LLVivoxVoiceClient::notifyVoiceFontObservers() { - LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << lists_changed << LL_ENDL; + LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL; for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); it != mVoiceFontObservers.end(); ) { LLVoiceEffectObserver* observer = *it; - observer->onVoiceEffectChanged(lists_changed); + observer->onVoiceEffectChanged(mVoiceFontListDirty); // In case onVoiceEffectChanged() deleted an entry. it = mVoiceFontObservers.upper_bound(observer); } + mVoiceFontListDirty = false; + + // If new Voice Fonts have been added notify the user. + if (mVoiceFontsNew) + { + if(mVoiceFontsReceived) + { + LLNotificationsUtil::add("VoiceEffectsNew"); + } + mVoiceFontsNew = false; + } } void LLVivoxVoiceClient::enablePreviewBuffer(bool enable) @@ -7528,14 +7533,11 @@ LLDate LLVivoxProtocolParser::vivoxTimeStampToLLDate(const std::string& vivox_ts std::string time_stamp = vivox_ts; // Vivox's format is missing a T from being standard ISO 8601, - // so add it. It is the only space in their result. + // so add it instead of the only space after the date. LLStringUtil::replaceChar(time_stamp, ' ', 'T'); - // Also need to remove the hours away from GMT to be compatible - // with LLDate, as well as the fractions of seconds. - time_stamp = time_stamp.substr(0, time_stamp.length() - 5); - - // It also needs a 'Z' at the end + // LLDate can't handle offsets from UTC, so remove it, and add a Z + time_stamp = time_stamp.substr(0, time_stamp.length() - 3); time_stamp += "Z"; ts.fromString(time_stamp); diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index debc03377f..5424e352f8 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -869,7 +869,7 @@ private: void accountGetTemplateFontsSendMessage(); void sessionSetVoiceFontSendMessage(sessionState *session); - void notifyVoiceFontObservers(bool lists_changed = false); + void notifyVoiceFontObservers(); typedef enum e_voice_font_type { @@ -906,6 +906,7 @@ private: bool mVoiceFontsReceived; bool mVoiceFontsNew; + bool mVoiceFontListDirty; voice_effect_list_t mVoiceFontList; voice_effect_list_t mVoiceFontTemplateList; -- cgit v1.2.3 From a63b6dd93c1ef78e647dbd221a5a3b14ff363102 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Wed, 26 May 2010 14:43:27 +0100 Subject: Hooked up Google Breakpad for the Linux client too. Using Alain's Darwin reporter callback was all that was needed. Also replaced the call that exposed the breakpad exception class with a call to just write out the minidump, as that was the only reason for exposing it. Now clients don't need to know about Google Breakpad. --- indra/newview/llappviewer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7cdd8ca309..0484659793 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -102,7 +102,6 @@ // Third party library includes #include -#include #if LL_WINDOWS @@ -2582,7 +2581,10 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); - if(pApp->minidump_path[0] != 0) gDebugInfo["MinidumpPath"] = pApp->minidump_path; + if(pApp->minidump_path[0] != 0) + { + gDebugInfo["MinidumpPath"] = pApp->minidump_path; + } if(gLogoutInProgress) { @@ -3290,7 +3292,7 @@ void LLAppViewer::badNetworkHandler() "www.secondlife.com/support"; forceDisconnect(message.str()); - LLApp::instance()->getExceptionHandler()->WriteMinidump(); + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. -- cgit v1.2.3 From 4dec1430202d1c5578c4e0a6d4107c88f1050ab3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 May 2010 16:07:16 -0400 Subject: VPLAT-268: Add libexception_handler.dylib to viewer_manifest.py. Without this, the viewer fails to start because it can't find the new libexception_handler.dylib. --- indra/newview/viewer_manifest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 96541088b5..cf66fbc383 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -636,7 +636,9 @@ class DarwinManifest(ViewerManifest): if dylibs["llcommon"]: for libfile in ("libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): self.path(os.path.join(libdir, libfile), libfile) #libfmodwrapper.dylib -- cgit v1.2.3 From d821d371e30cb7fcf32b6fae12ef4557e729bca3 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Thu, 27 May 2010 11:41:07 +0100 Subject: EXT-7138 WIP Removed now redundant onClickAdd callback from the Voice Effect preview floater. Cleaned up comments. --- indra/newview/llfloatervoiceeffect.cpp | 8 +------- indra/newview/llfloatervoiceeffect.h | 6 +++--- indra/newview/llpanelvoiceeffect.cpp | 2 +- indra/newview/llpanelvoiceeffect.h | 2 +- 4 files changed, 6 insertions(+), 12 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index b47d562995..d27adfcea1 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -1,5 +1,6 @@ /** * @file llfloatervoiceeffect.cpp + * @author Aimee * @brief Selection and preview of voice effect. * * $LicenseInfo:firstyear=2010&license=viewergpl$ @@ -44,7 +45,6 @@ LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key) mCommitCallbackRegistrar.add("VoiceEffect.Record", boost::bind(&LLFloaterVoiceEffect::onClickRecord, this)); mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); mCommitCallbackRegistrar.add("VoiceEffect.Stop", boost::bind(&LLFloaterVoiceEffect::onClickStop, this)); - mCommitCallbackRegistrar.add("VoiceEffect.Add", boost::bind(&LLFloaterVoiceEffect::onClickAdd, this)); // mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); } @@ -280,12 +280,6 @@ void LLFloaterVoiceEffect::onClickStop() updateControls(); } -void LLFloaterVoiceEffect::onClickAdd() -{ - // Open the voice morphing info web page - LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); -} - //void LLFloaterVoiceEffect::onClickActivate() //{ // LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h index 46b241bd17..2a8330c72a 100644 --- a/indra/newview/llfloatervoiceeffect.h +++ b/indra/newview/llfloatervoiceeffect.h @@ -1,5 +1,6 @@ /** * @file llfloatervoiceeffect.h + * @author Aimee * @brief Selection and preview of voice effects. * * $LicenseInfo:firstyear=2010&license=viewergpl$ @@ -62,9 +63,8 @@ private: void onClickRecord(); void onClickPlay(); void onClickStop(); - void onClickAdd(); -// void onClickActivate(); - +// void onClickActivate(); + LLUUID mSelectedID; LLScrollListCtrl* mVoiceEffectList; }; diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 518afc5eb3..707e05048e 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -1,6 +1,6 @@ /** * @file llpanelvoiceeffect.cpp - * @author Aimee Walton + * @author Aimee * @brief Panel to select Voice Effects. * * $LicenseInfo:firstyear=2010&license=viewergpl$ diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h index 235db5a9e4..c773b4ce94 100644 --- a/indra/newview/llpanelvoiceeffect.h +++ b/indra/newview/llpanelvoiceeffect.h @@ -1,6 +1,6 @@ /** * @file llpanelvoiceeffect.h - * @author Aimee Walton + * @author Aimee * @brief Panel to select Voice Effects. * * $LicenseInfo:firstyear=2010&license=viewergpl$ -- cgit v1.2.3 From 485f9abde6b728a923070e392e40c16ea9f05226 Mon Sep 17 00:00:00 2001 From: Aimee Linden Date: Thu, 27 May 2010 12:53:53 +0100 Subject: EXT-7138 WIP Changed UI text to use "Voice Morph" everywhere instead of "Voice Effect". Revised wording in preview floater (DEV-50573). Added tool-tip for Voice Morphing control in Nearby Voice (DEV-50608). --- indra/newview/app_settings/settings.xml | 4 ++-- indra/newview/app_settings/settings_per_account.xml | 2 +- indra/newview/llfloatervoiceeffect.cpp | 6 +++--- indra/newview/llpanelvoiceeffect.cpp | 10 +++++----- indra/newview/llpanelvoiceeffect.h | 2 +- .../skins/default/xui/en/floater_voice_effect.xml | 17 +++++++++-------- indra/newview/skins/default/xui/en/notifications.xml | 14 +++++++------- .../newview/skins/default/xui/en/panel_voice_effect.xml | 5 +++-- 8 files changed, 31 insertions(+), 29 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 505403b155..4dd121fd22 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10609,7 +10609,7 @@ VoiceEffectExpiryWarningTime Comment - How much notice to give of voice effect subscriptions expiry, in seconds. + How much notice to give of Voice Morph subscriptions expiry, in seconds. Persist 1 Type @@ -10620,7 +10620,7 @@ VoiceMorphingEnabled Comment - Whether or not to enable Voice Effects and show the UI. + Whether or not to enable Voice Morphs and show the UI. Persist 0 Type diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index c94ae1fca1..d4000e9253 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -102,7 +102,7 @@ VoiceEffectDefault Comment - Selected voice effect + Selected Voice Morph Persist 1 Type diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index d27adfcea1..22392dca8b 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -114,7 +114,7 @@ void LLFloaterVoiceEffect::refreshEffectList() return; } - LL_DEBUGS("Voice")<< "Rebuilding voice effect list."<< LL_ENDL; + LL_DEBUGS("Voice")<< "Rebuilding Voice Morph list."<< LL_ENDL; // Preserve selected items and scroll position S32 scroll_pos = mVoiceEffectList->getScrollPos(); @@ -128,7 +128,7 @@ void LLFloaterVoiceEffect::refreshEffectList() mVoiceEffectList->deleteAllItems(); { - // Add the "No Voice Effect" entry + // Add the "No Voice Morph" entry LLSD element; element["id"] = LLUUID::null; @@ -145,7 +145,7 @@ void LLFloaterVoiceEffect::refreshEffectList() } } - // Add each Voice Effect template, if there are any (template list includes all usable effects) + // Add each Voice Morph template, if there are any (template list includes all usable effects) const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList(); if (!template_list.empty()) { diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 707e05048e..fd470798ee 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -1,7 +1,7 @@ /** * @file llpanelvoiceeffect.cpp * @author Aimee - * @brief Panel to select Voice Effects. + * @brief Panel to select Voice Morphs. * * $LicenseInfo:firstyear=2010&license=viewergpl$ * @@ -102,7 +102,7 @@ void LLPanelVoiceEffect::onCommitVoiceEffect() LLSD value = mVoiceEffectCombo->getValue(); if (value.asInteger() == PREVIEW_VOICE_EFFECTS) { - // Open the voice effects management floater + // Open the Voice Morph preview floater LLFloaterReg::showInstance("voice_effect"); } else if (value.asInteger() == GET_VOICE_EFFECTS) @@ -131,12 +131,12 @@ void LLPanelVoiceEffect::update(bool list_updated) LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); if (list_updated) { - // Add the default "No Voice Effect" entry. + // Add the default "No Voice Morph" entry. mVoiceEffectCombo->removeall(); mVoiceEffectCombo->add(getString("no_voice_effect"), LLUUID::null); mVoiceEffectCombo->addSeparator(); - // Add entries for each Voice Effect. + // Add entries for each Voice Morph. const voice_effect_list_t& effect_list = effect_interface->getVoiceEffectList(); if (!effect_list.empty()) { @@ -155,7 +155,7 @@ void LLPanelVoiceEffect::update(bool list_updated) if (effect_interface && LLVoiceClient::instance().isVoiceWorking()) { - // Select the current voice effect. + // Select the current Voice Morph. mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect()); mVoiceEffectCombo->setEnabled(true); } diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h index c773b4ce94..79f9d2fe75 100644 --- a/indra/newview/llpanelvoiceeffect.h +++ b/indra/newview/llpanelvoiceeffect.h @@ -58,7 +58,7 @@ private: /// Called by voice effect provider when voice effect list is changed. virtual void onVoiceEffectChanged(bool effect_list_updated); - // Fixed entries in the voice effect list + // Fixed entries in the Voice Morph list typedef enum e_voice_effect_combo_items { NO_VOICE_EFFECT = 0, diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml index 4f4b20066d..207397d3dc 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -2,7 +2,7 @@ - (No Voice Effect) + (No Voice Morph) (Active) @@ -23,7 +23,7 @@ (New!) -Record a sample of your voice, and then select an effect to preview. -Close this window to return to in-world voice. +To preview any of the Voice Morphing effects, click the Record button to record a short snippet of voice, then click any Voice Morph in the list to hear how it will sound. + +To reconnect to Nearby Voice simply close this window. - - + + Date: Wed, 16 Jun 2010 16:54:14 -0700 Subject: web browser test should always use internal browser --- indra/newview/llviewermenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2c7ae539ce..cc33dfcfef 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7209,7 +7209,7 @@ void handle_web_browser_test(const LLSD& param) { url = "about:blank"; } - LLWeb::loadURL(url); + LLWeb::loadURLInternal(url); } void handle_buy_currency_test(void*) -- cgit v1.2.3 From 4aef5f54de70a8d729c93f7eb11995a7d23feed0 Mon Sep 17 00:00:00 2001 From: Richard Nelson Date: Wed, 16 Jun 2010 17:32:51 -0700 Subject: EXT-7734 FIX In-world object properteis often don't show correct information reviewed by Leyla --- indra/newview/llinventoryfunctions.cpp | 5 ++ indra/newview/llinventoryfunctions.h | 1 + indra/newview/llpanelobjectinventory.cpp | 12 +-- indra/newview/llselectmgr.h | 15 ++-- indra/newview/llsidepaneltaskinfo.cpp | 27 ++++++- indra/newview/llsidepaneltaskinfo.h | 4 +- .../skins/default/xui/en/sidepanel_item_info.xml | 89 +++++++++++----------- 7 files changed, 86 insertions(+), 67 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 68fc86467c..3913e1805f 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -327,6 +327,11 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) return FALSE; } +void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id) +{ + LLSideTray::getInstance()->showPanel("sidepanel_inventory", LLSD().with("id", item_uuid).with("object", object_id)); +} + void show_item_profile(const LLUUID& item_uuid) { LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid); diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 93c56e1b8a..aa4ac98241 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -53,6 +53,7 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id); BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id); void show_item_profile(const LLUUID& item_uuid); +void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index da809b7baa..f683cbc8d0 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -176,17 +176,7 @@ LLInventoryItem* LLTaskInvFVBridge::findItem() const void LLTaskInvFVBridge::showProperties() { - show_item_profile(mUUID); - - // Disable old properties floater; this is replaced by the sidepanel. - /* - LLFloaterProperties* floater = LLFloaterReg::showTypedInstance("properties", mUUID); - if (floater) - { - floater->setObjectID(mPanel->getTaskUUID()); - } - */ - + show_task_item_profile(mUUID, mPanel->getTaskUUID()); } struct LLBuyInvItemData diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index d315f40ff3..668c04cf15 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -257,7 +257,6 @@ public: LLObjectSelection(); void updateEffects(); - void cleanupNodes(); BOOL isEmpty() const; @@ -281,11 +280,6 @@ public: template bool getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res); template bool isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value); - void addNode(LLSelectNode *nodep); - void addNodeAtEnd(LLSelectNode *nodep); - void moveNodeToFront(LLSelectNode *nodep); - void removeNode(LLSelectNode *nodep); - void deleteAllNodes(); // Delete all nodes S32 getNumNodes(); LLSelectNode* findNode(LLViewerObject* objectp); @@ -312,6 +306,15 @@ public: ESelectType getSelectType() const { return mSelectType; } +private: + void addNode(LLSelectNode *nodep); + void addNodeAtEnd(LLSelectNode *nodep); + void moveNodeToFront(LLSelectNode *nodep); + void removeNode(LLSelectNode *nodep); + void deleteAllNodes(); + void cleanupNodes(); + + private: list_t mList; const LLObjectSelection &operator=(const LLObjectSelection &); diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index e76397671b..3ab71eac64 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -80,6 +80,7 @@ static LLRegisterPanelClassWrapper t_task_info("sidepanel_t LLSidepanelTaskInfo::LLSidepanelTaskInfo() { setMouseOpaque(FALSE); + LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLSidepanelTaskInfo::refreshAll, this)); } @@ -271,7 +272,6 @@ void LLSidepanelTaskInfo::refresh() // BUG: fails if a root and non-root are both single-selected. const BOOL is_perm_modify = (mObjectSelection->getFirstRootNode() && LLSelectMgr::getInstance()->selectGetRootsModify()) || LLSelectMgr::getInstance()->selectGetModify(); - const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); S32 string_index = 0; std::string MODIFY_INFO_STRINGS[] = @@ -365,14 +365,14 @@ void LLSidepanelTaskInfo::refresh() if (is_one_object) { - if (keyboard_focus_view != LineEditorObjectName) + if (!LineEditorObjectName->hasFocus()) { childSetText("Object Name",nodep->mName); } if (LineEditorObjectDesc) { - if (keyboard_focus_view != LineEditorObjectDesc) + if (!LineEditorObjectDesc->hasFocus()) { LineEditorObjectDesc->setText(nodep->mDescription); } @@ -1178,9 +1178,30 @@ void LLSidepanelTaskInfo::save() onCommitIncludeInSearch(getChild("search_check"), this); } +// removes keyboard focus so that all fields can be updated +// and then restored focus +void LLSidepanelTaskInfo::refreshAll() +{ + // update UI as soon as we have an object + // but remove keyboard focus first so fields are free to update + LLFocusableElement* focus = NULL; + if (hasFocus()) + { + focus = gFocusMgr.getKeyboardFocus(); + setFocus(FALSE); + } + refresh(); + if (focus) + { + focus->setFocus(TRUE); + } +} + + void LLSidepanelTaskInfo::setObjectSelection(LLObjectSelectionHandle selection) { mObjectSelection = selection; + refreshAll(); } LLSidepanelTaskInfo* LLSidepanelTaskInfo::getActivePanel() diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h index 15274c90db..010173e84e 100644 --- a/indra/newview/llsidepaneltaskinfo.h +++ b/indra/newview/llsidepaneltaskinfo.h @@ -67,6 +67,8 @@ protected: /*virtual*/ void save(); /*virtual*/ void updateVerbs(); + void refreshAll(); // ignore current keyboard focus and update all fields + // statics static void onClickClaim(void*); static void onClickRelease(void*); @@ -120,7 +122,7 @@ protected: LLViewerObject* getObject(); private: LLViewerObject* mObject; - LLObjectSelectionHandle mObjectSelection; + LLObjectSelectionHandle mObjectSelection; static LLSidepanelTaskInfo* sActivePanel; }; diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index e2bd6f375e..b3bc618eec 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -159,51 +159,49 @@ name="LabelCreatorName" top_delta="6" width="140"> - Nicole Linden - - @@ -61,22 +73,22 @@ To reconnect to Nearby Voice simply close this window. left_delta="0" name="record_stop_btn" top_delta="0" - width="150"> + width="100"> - [[URL] Get Voice Morphing] + right="-10"> + [[URL] Subscribe Now] + top="95"> + label="Voice Name" + name="name" + relative_width="0.60" /> + relative_width="0.30" /> + diff --git a/indra/newview/skins/default/xui/en/panel_voice_effect.xml b/indra/newview/skins/default/xui/en/panel_voice_effect.xml index c575ca468c..93e79b7328 100644 --- a/indra/newview/skins/default/xui/en/panel_voice_effect.xml +++ b/indra/newview/skins/default/xui/en/panel_voice_effect.xml @@ -6,7 +6,7 @@ name="panel_voice_effect" width="200"> - No Voice Morph + Voice Morphing Off Preview Voice Morphing ▶ @@ -19,11 +19,11 @@ follows="left|top|right" height="23" name="voice_effect" - tool_tip="Select a Voice Morphing effect to change your voice." + tool_tip="Select a Voice Morph to change your voice" top_pad="0" width="200"> -- cgit v1.2.3 From cc0d5eae4d59adf41d59248e1b481a66db791b07 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 18 Jun 2010 16:17:34 +0100 Subject: Fix llpreviewgesture.h build borkage. --- indra/newview/llpreviewgesture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 1814f0d403..b141b14445 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -35,8 +35,8 @@ #include "llassettype.h" #include "llpreview.h" +#include "llmultigesture.h" -class LLMultiGesture; class LLLineEditor; class LLTextBox; class LLCheckBoxCtrl; -- cgit v1.2.3 From c7f0cabc0eb530efdbbc0bf74bf33979be23e6fa Mon Sep 17 00:00:00 2001 From: Vladimir Pchelko Date: Fri, 18 Jun 2010 20:30:52 +0300 Subject: EXT-7821 FIXED Editor type was changed to the type as in "Name:" editor in "My Inventory"->"Object Profile". Fix details: Using line_editor instead of text_editor. Enabled ascii filter for entering, because (for example) Russian charters corrupts outfit items and makes Edit Outfit very buggy. Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/608/ --HG-- branch : product-engine --- indra/newview/llpaneleditwearable.cpp | 16 ++++++++-------- indra/newview/llpaneleditwearable.h | 4 ++-- .../skins/default/xui/en/panel_edit_wearable.xml | 20 +++++++++++--------- 3 files changed, 21 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 1aedfec86f..4402b2130f 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -652,7 +652,7 @@ BOOL LLPanelEditWearable::postBuild() // handled at appearance panel level? //mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); - mTextEditor = getChild("description"); + mNameEditor = getChild("description"); mPanelTitle = getChild("edit_wearable_title"); mDescTitle = getChild("description_text"); @@ -758,7 +758,7 @@ BOOL LLPanelEditWearable::isDirty() const if (mWearablePtr) { if (mWearablePtr->isDirty() || - mWearablePtr->getName().compare(mTextEditor->getText()) != 0) + mWearablePtr->getName().compare(mNameEditor->getText()) != 0) { isDirty = TRUE; } @@ -796,7 +796,7 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata) void LLPanelEditWearable::onSaveAsButtonClicked() { LLSD args; - args["DESC"] = mTextEditor->getText(); + args["DESC"] = mNameEditor->getText(); LLNotificationsUtil::add("SaveWearableAs", args, LLSD(), boost::bind(&LLPanelEditWearable::saveAsCallback, this, _1, _2)); } @@ -810,7 +810,7 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r LLStringUtil::trim(wearable_name); if( !wearable_name.empty() ) { - mTextEditor->setText(wearable_name); + mNameEditor->setText(wearable_name); saveChanges(); } } @@ -956,10 +956,10 @@ void LLPanelEditWearable::saveChanges() U32 index = gAgentWearables.getWearableIndex(mWearablePtr); - if (mWearablePtr->getName().compare(mTextEditor->getText()) != 0) + if (mWearablePtr->getName().compare(mNameEditor->getText()) != 0) { // the name of the wearable has changed, re-save wearable with new name - gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mTextEditor->getText(), FALSE); + gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mNameEditor->getText(), FALSE); } else { @@ -976,7 +976,7 @@ void LLPanelEditWearable::revertChanges() } mWearablePtr->revertValues(); - mTextEditor->setText(mWearablePtr->getName()); + mNameEditor->setText(mWearablePtr->getName()); } void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show) @@ -1018,7 +1018,7 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show) mDescTitle->setText(description_title); // set name - mTextEditor->setText(wearable->getName()); + mNameEditor->setText(wearable->getName()); updatePanelPickerControls(type); updateTypeSpecificControls(type); diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index c63671fcc9..61441435cd 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -41,7 +41,6 @@ class LLCheckBoxCtrl; class LLWearable; -class LLTextEditor; class LLTextBox; class LLViewerInventoryItem; class LLViewerVisualParam; @@ -49,6 +48,7 @@ class LLVisualParamHint; class LLViewerJointMesh; class LLAccordionCtrlTab; class LLJoint; +class LLLineEditor; class LLPanelEditWearable : public LLPanel { @@ -140,7 +140,7 @@ private: // This text editor reference will change each time we edit a new wearable - // it will be grabbed from the currently visible panel - LLTextEditor *mTextEditor; + LLLineEditor *mNameEditor; // The following panels will be shown/hidden based on what wearable we're editing // body parts diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 950c4a5fdb..3106ed34ff 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -225,15 +225,17 @@ left="0" tool_tip="Female" top="7" width="16" /> - + Date: Fri, 18 Jun 2010 12:33:17 -0500 Subject: EXT-7910 allow GPU and feature table to load from a custom location --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llfeaturemanager.cpp | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2244f05104..1d635ef18a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2840,6 +2840,17 @@ Boolean Value 0 + + FeatureManagerHTTPTable + + Comment + Base directory for HTTP feature/gpu table fetches + Persist + 1 + Type + String + Value + http://viewer-settings.secondlife.com FPSLogFrequency diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 4fdb010162..f32fcd6b7f 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -496,11 +496,11 @@ private: void fetch_table(std::string table) { - const std::string base = "http://viewer-settings.s3.amazonaws.com/"; + const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable"); const std::string filename = llformat(table.c_str(), LLVersionInfo::getVersion().c_str()); - const std::string url = base + filename; + const std::string url = base + "/" + filename; const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); -- cgit v1.2.3 From d8ec78e325ee3add1a5968ea0a3051de16958404 Mon Sep 17 00:00:00 2001 From: Leyla Farazha Date: Fri, 18 Jun 2010 10:51:45 -0700 Subject: EXT-7152 TOS breaks Critical Message in 2.0.0 and 2.0.1 removed cancel button --- indra/newview/skins/default/xui/en/floater_critical.xml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml index 7b5451553f..05c958e051 100644 --- a/indra/newview/skins/default/xui/en/floater_critical.xml +++ b/indra/newview/skins/default/xui/en/floater_critical.xml @@ -6,6 +6,7 @@ height="500" layout="topleft" name="modal container" + open_centered="true" width="600">