From db5cda26676f376f18816013c0c5e3fbad5b20d0 Mon Sep 17 00:00:00 2001 From: Steven Bennetts <steve@lindenlab.com> Date: Mon, 3 Aug 2009 22:25:48 +0000 Subject: [PATCH] merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0@1211 https://svn.aws.productengine.com/secondlife/pe/stable-1@1228 -> viewer-2.0.0-3 QA: New movement and camera controls. Test all movement and camera behavior against spec and expected behaviors, including sitting & standing. Many other changes to the bottom bar. Changes to local chat behavior. --- indra/newview/CMakeLists.txt | 12 +- indra/newview/app_settings/settings.xml | 35 +- indra/newview/llagent.cpp | 100 ++-- indra/newview/llagent.h | 6 + indra/newview/llappviewer.cpp | 2 - indra/newview/llavatarlist.cpp | 18 + indra/newview/llavatarlist.h | 8 + indra/newview/llbottomtray.cpp | 49 +- indra/newview/llbottomtray.h | 5 - indra/newview/llchannelmanager.cpp | 8 +- indra/newview/llchannelmanager.h | 2 + indra/newview/llfloatercamera.cpp | 286 +++++++++- indra/newview/llfloatercamera.h | 80 ++- indra/newview/llfloaterinventory.cpp | 1 - indra/newview/llgroupactions.cpp | 127 +++++ indra/newview/llgroupactions.h | 5 + indra/newview/lllocationhistory.cpp | 8 +- indra/newview/lllocationinputctrl.cpp | 15 +- indra/newview/lllocationinputctrl.h | 1 + indra/newview/llmoveview.cpp | 498 ++++++++++++++++-- indra/newview/llmoveview.h | 98 +++- indra/newview/llnavigationbar.cpp | 46 +- indra/newview/llnavigationbar.h | 2 +- indra/newview/llnearbychat.cpp | 3 +- indra/newview/llnearbychatbar.cpp | 97 +++- indra/newview/llnearbychatbar.h | 2 + indra/newview/lloverlaybar.cpp | 2 +- indra/newview/llpanelavatar.cpp | 14 +- indra/newview/llpanelpeople.cpp | 27 +- indra/newview/llpanelpeople.h | 2 - indra/newview/llpanelplaceinfo.cpp | 21 + indra/newview/llpanelplaceinfo.h | 4 + indra/newview/llpanelplaces.cpp | 257 ++++++++- indra/newview/llpanelplaces.h | 23 +- indra/newview/llpanelprofile.cpp | 48 +- indra/newview/llpanelprofile.h | 2 +- indra/newview/llpanelprofileview.cpp | 29 +- indra/newview/llscreenchannel.cpp | 16 +- indra/newview/llscreenchannel.h | 3 +- indra/newview/llsidetray.cpp | 14 + indra/newview/llsidetray.h | 1 + indra/newview/llsidetraypanelcontainer.cpp | 89 ++++ indra/newview/llsidetraypanelcontainer.h | 95 ++++ indra/newview/llsplitbutton.cpp | 275 ++++++++++ indra/newview/llsplitbutton.h | 112 ++++ indra/newview/lltoast.cpp | 24 +- indra/newview/lltoast.h | 2 + indra/newview/lltoolbar.cpp | 2 +- indra/newview/lltoolfocus.cpp | 8 +- indra/newview/lltoolpie.cpp | 5 +- indra/newview/llviewerfloaterreg.cpp | 5 +- indra/newview/llviewerinventory.cpp | 17 +- indra/newview/llviewerkeyboard.cpp | 35 +- indra/newview/llviewermenu.cpp | 38 +- indra/newview/llviewermessage.cpp | 12 +- indra/newview/llviewertexteditor.cpp | 6 +- indra/newview/llviewerwindow.cpp | 34 +- indra/newview/llviewerwindow.h | 1 - indra/newview/llvoavatar.cpp | 23 +- indra/newview/llvoavatar.h | 5 + indra/newview/llvoavatarself.cpp | 9 + indra/newview/macview_Prefix.h | 1 - .../textures/quick_tips/avatar_free_mode.png | Bin 0 -> 1447 bytes .../textures/quick_tips/camera_free_mode.png | Bin 0 -> 2267 bytes .../textures/quick_tips/camera_orbit_mode.png | Bin 0 -> 2381 bytes .../textures/quick_tips/camera_pan_mode.png | Bin 0 -> 2418 bytes .../quick_tips/camera_preset_front_view.png | Bin 0 -> 2365 bytes .../quick_tips/camera_preset_group_view.png | Bin 0 -> 2595 bytes .../quick_tips/camera_preset_rear_view.png | Bin 0 -> 2221 bytes .../textures/quick_tips/move_fly_first.png | Bin 0 -> 1528 bytes .../textures/quick_tips/move_fly_second.png | Bin 0 -> 2128 bytes .../textures/quick_tips/move_run_first.png | Bin 0 -> 1554 bytes .../textures/quick_tips/move_run_second.png | Bin 0 -> 2534 bytes .../textures/quick_tips/move_walk_first.png | Bin 0 -> 2106 bytes .../textures/quick_tips/move_walk_second.png | Bin 0 -> 3108 bytes .../skins/default/xui/en/floater_camera.xml | 160 ++++-- .../default/xui/en/floater_first_time_tip.xml | 20 + .../skins/default/xui/en/floater_moveview.xml | 286 ++++++---- .../skins/default/xui/en/menu_navbar.xml | 19 +- .../skins/default/xui/en/menu_viewer.xml | 9 + .../skins/default/xui/en/panel_bottomtray.xml | 115 +++- .../skins/default/xui/en/panel_people.xml | 12 - .../skins/default/xui/en/panel_places.xml | 102 ++-- .../skins/default/xui/en/panel_profile.xml | 2 +- .../default/xui/en/panel_profile_view.xml | 5 +- .../skins/default/xui/en/panel_side_tray.xml | 15 +- .../xui/en/panel_stand_stop_flying.xml | 28 + .../newview/skins/default/xui/en/strings.xml | 2 +- .../default/xui/en/widgets/split_button.xml | 24 + 89 files changed, 3010 insertions(+), 564 deletions(-) create mode 100644 indra/newview/llsidetraypanelcontainer.cpp create mode 100644 indra/newview/llsidetraypanelcontainer.h create mode 100644 indra/newview/llsplitbutton.cpp create mode 100644 indra/newview/llsplitbutton.h create mode 100644 indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_free_mode.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png create mode 100644 indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_fly_first.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_fly_second.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_run_first.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_run_second.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_walk_first.png create mode 100644 indra/newview/skins/default/textures/quick_tips/move_walk_second.png create mode 100644 indra/newview/skins/default/xui/en/floater_first_time_tip.xml create mode 100644 indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/split_button.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9a0c9d9c7b..899d0a8293 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -130,13 +130,13 @@ set(viewer_SOURCE_FILES llfeaturemanager.cpp llfilepicker.cpp llfirstuse.cpp + llfirsttimetipmanager.cpp llflexibleobject.cpp llfloaterabout.cpp llfloateractivespeakers.cpp llfloateraddlandmark.cpp llfloateranimpreview.cpp llfloaterauction.cpp - llfloateravatarinfo.cpp llfloateravatarpicker.cpp llfloateravatartextures.cpp llfloaterbeacons.cpp @@ -158,6 +158,7 @@ set(viewer_SOURCE_FILES llfloaterdirectory.cpp llfloaterenvsettings.cpp llfloaterevent.cpp + llfloaterfirsttimetip.cpp llfloaterfriends.cpp llfloaterfonttest.cpp llfloatergesture.cpp @@ -283,6 +284,7 @@ set(viewer_SOURCE_FILES llpanelavatar.cpp llpanelavatarrow.cpp llpanelclassified.cpp + llsidetraypanelcontainer.cpp llpanelcontents.cpp llpaneldirbrowser.cpp llpaneldirclassified.cpp @@ -308,6 +310,7 @@ set(viewer_SOURCE_FILES llpanellogin.cpp llpanelmedia.cpp llpanelmeprofile.cpp + llpanelmovetip.cpp llpanelobject.cpp llpanelpeople.cpp llpanelpermissions.cpp @@ -345,6 +348,7 @@ set(viewer_SOURCE_FILES llsky.cpp llslurl.cpp llspatialpartition.cpp + llsplitbutton.cpp llsprite.cpp llsrv.cpp llstartup.cpp @@ -569,13 +573,13 @@ set(viewer_HEADER_FILES llfeaturemanager.h llfilepicker.h llfirstuse.h + llfirsttimetipmanager.h llflexibleobject.h llfloaterabout.h llfloateractivespeakers.h llfloateraddlandmark.h llfloateranimpreview.h llfloaterauction.h - llfloateravatarinfo.h llfloateravatarpicker.h llfloateravatartextures.h llfloaterbeacons.h @@ -597,6 +601,7 @@ set(viewer_HEADER_FILES llfloaterdirectory.h llfloaterenvsettings.h llfloaterevent.h + llfloaterfirsttimetip.h llfloaterfonttest.h llfloaterfriends.h llfloatergesture.h @@ -721,6 +726,7 @@ set(viewer_HEADER_FILES llpanelavatar.h llpanelavatarrow.h llpanelclassified.h + llsidetraypanelcontainer.h llpanelcontents.h llpaneldirbrowser.h llpaneldirclassified.h @@ -746,6 +752,7 @@ set(viewer_HEADER_FILES llpanellogin.h llpanelmedia.h llpanelmeprofile.h + llpanelmovetip.h llpanelobject.h llpanelpeople.h llpanelpermissions.h @@ -785,6 +792,7 @@ set(viewer_HEADER_FILES llsky.h llslurl.h llspatialpartition.h + llsplitbutton.h llsprite.h llsrv.h llstartup.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index edcd288b7d..3baf37826f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4760,6 +4760,17 @@ <key>Value</key> <integer>5</integer> </map> + <key>ToastOpaqueTime</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>4</integer> + </map> <key>StartUpToastTime</key> <map> <key>Comment</key> @@ -4769,7 +4780,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>10</integer> + <integer>5</integer> </map> <key>ToastMargin</key> <map> @@ -6763,6 +6774,17 @@ <integer>0</integer> </map> <key>ShowCrosshairs</key> + <map> + <key>Comment</key> + <string>Show Coordinates in Location Input Field</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowCoordinatesOption</key> <map> <key>Comment</key> <string>Display crosshairs when in mouselook mode</string> @@ -9623,5 +9645,16 @@ <key>Value</key> <integer>0</integer> </map> + <key>GroupTeleportMembersLimit</key> + <map> + <key>Comment</key> + <string>Max number of members of group to offer teleport</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>100</integer> + </map> </map> </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f527719a7a..ce8b05d97a 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -42,7 +42,6 @@ #include "llfirstuse.h" #include "llfloaterreg.h" #include "llfloateractivespeakers.h" -#include "llfloateravatarinfo.h" #include "llfloatercamera.h" #include "llfloatercustomize.h" #include "llfloaterdirectory.h" @@ -499,12 +498,16 @@ void LLAgent::resetView(BOOL reset_camera, BOOL change_camera) LLViewerJoystick::getInstance()->moveAvatar(true); } - LLFloaterReg::hideInstance("build"); + //Camera Tool is needed for Free Camera Control Mode + if (!LLFloaterCamera::inFreeCameraMode()) + { + LLFloaterReg::hideInstance("build"); + + // Switch back to basic toolset + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } gViewerWindow->showCursor(); - - // Switch back to basic toolset - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); } @@ -755,7 +758,7 @@ void LLAgent::setFlying(BOOL fly) } // don't allow taking off while sitting - if (fly && mAvatarObject->mIsSitting) + if (fly && mAvatarObject->isSitting()) { return; } @@ -784,6 +787,11 @@ void LLAgent::setFlying(BOOL fly) clearControlFlags(AGENT_CONTROL_FLY); gSavedSettings.setBOOL("FlyBtnState", FALSE); } + + + // Update Movement Controls according to Fly mode + LLFloaterMove::setFlyingMode(fly); + mbFlagsDirty = TRUE; } @@ -807,11 +815,16 @@ bool LLAgent::enableFlying() BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } return !sitting; } +void LLAgent::standUp() +{ + setControlFlags(AGENT_CONTROL_STAND_UP); +} + //----------------------------------------------------------------------------- // setRegion() @@ -1242,7 +1255,7 @@ F32 LLAgent::clampPitchToLimits(F32 angle) F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward ); - if (mAvatarObject.notNull() && mAvatarObject->mIsSitting) + if (mAvatarObject.notNull() && mAvatarObject->isSitting()) { look_down_limit = 130.f * DEG_TO_RAD; } @@ -2488,13 +2501,11 @@ void LLAgent::autoPilot(F32 *delta_yaw) void LLAgent::propagate(const F32 dt) { // Update UI based on agent motion - LLFloaterMove *floater_move = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); + LLFloaterMove *floater_move = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); if (floater_move) { floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 ); floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 ); - floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 ); - floater_move->mSlideRightButton->setToggleState( mLeftKey < 0 ); floater_move->mTurnLeftButton ->setToggleState( mYawKey > 0.f ); floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f ); floater_move->mMoveUpButton ->setToggleState( mUpKey > 0 ); @@ -2579,7 +2590,7 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y) else { // *FIX: rotate mframeagent by sit object's rotation? - LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation + LLQuaternion look_rotation = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset); } @@ -2815,6 +2826,8 @@ void LLAgent::endAnimationUpdateUI() LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + LLFloaterCamera::toPrevModeIfInAvatarViewMode(); + // Only pop if we have pushed... if (TRUE == mViewsPushed) { @@ -2909,6 +2922,10 @@ 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; @@ -3019,7 +3036,7 @@ void LLAgent::updateCamera() validateFocusObject(); if (mAvatarObject.notNull() && - mAvatarObject->mIsSitting && + mAvatarObject->isSitting() && camera_mode == CAMERA_MODE_MOUSELOOK) { //Ventrella @@ -3050,24 +3067,24 @@ void LLAgent::updateCamera() } // Update UI with our camera inputs - LLFloaterCamera* camera_instance = LLFloaterReg::getTypedInstance<LLFloaterCamera>("camera"); - if(camera_instance) + LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera"); + if (camera_floater) { - camera_instance->mRotate->setToggleState( - mOrbitRightKey > 0.f, // left - mOrbitUpKey > 0.f, // top - mOrbitLeftKey > 0.f, // right - mOrbitDownKey > 0.f); // bottom + camera_floater->mRotate->setToggleState( + mOrbitRightKey > 0.f, // left + mOrbitUpKey > 0.f, // top + mOrbitLeftKey > 0.f, // right + mOrbitDownKey > 0.f); // bottom - camera_instance->mZoom->setToggleState( - mOrbitInKey > 0.f, // top - mOrbitOutKey > 0.f); // bottom + camera_floater->mZoom->setToggleState( + mOrbitInKey > 0.f, // top + mOrbitOutKey > 0.f); // bottom - camera_instance->mTrack->setToggleState( - mPanLeftKey > 0.f, // left - mPanUpKey > 0.f, // top - mPanRightKey > 0.f, // right - mPanDownKey > 0.f); // bottom + camera_floater->mTrack->setToggleState( + mPanLeftKey > 0.f, // left + mPanUpKey > 0.f, // top + mPanRightKey > 0.f, // right + mPanDownKey > 0.f); // bottom } // Handle camera movement based on keyboard. @@ -3144,7 +3161,7 @@ void LLAgent::updateCamera() // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. //-------------------------------------------------------------------------------- // *TODO: use combined rotation of frameagent and sit object - LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); + LLQuaternion avatarRotationForFollowCam = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams(); if (current_cam) @@ -3324,7 +3341,7 @@ void LLAgent::updateCamera() } mLastPositionGlobal = global_pos; - if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook()) + if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->isSitting() && cameraMouselook()) { LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + @@ -3504,7 +3521,7 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal() } return mFocusTargetGlobal; } - else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull()) + else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull()) { // sit camera LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); @@ -3628,7 +3645,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) return LLVector3d::zero; } head_offset.clearVec(); - if (mAvatarObject->mIsSitting && mAvatarObject->getParent()) + if (mAvatarObject->isSitting() && mAvatarObject->getParent()) { mAvatarObject->updateHeadOffset(); head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX]; @@ -3642,7 +3659,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) else { head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ]; - if (mAvatarObject->mIsSitting) + if (mAvatarObject->isSitting()) { head_offset.mdV[VZ] += 0.1; } @@ -3658,7 +3675,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (mSitCameraEnabled && mAvatarObject.notNull() - && mAvatarObject->mIsSitting + && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull()) { // sit camera @@ -3690,7 +3707,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset ); } - if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->mIsSitting)) + if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->isSitting())) { LLVector3 plane_normal; plane_normal.setVec(mCameraCollidePlane.mV); @@ -4116,7 +4133,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate) if (mAvatarObject.notNull()) { - if (!mAvatarObject->mIsSitting) + if (!mAvatarObject->isSitting()) { mAvatarObject->mPelvisp->setPosition(LLVector3::zero); } @@ -4198,7 +4215,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani return; } - setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up + standUp(); // force stand up gViewerWindow->getWindow()->resetBusyCount(); if (gFaceEditToolset) @@ -5478,13 +5495,8 @@ void update_group_floaters(const LLUUID& group_id) { LLFloaterGroupInfo::refreshGroup(group_id); - //*TODO Implement group update for Profile View - // update avatar info -// LLFloaterAvatarInfo* fa = LLFloaterReg::findTypedInstance<LLFloaterAvatarInfo>("preview_avatar", LLSD(gAgent.getID())); -// if(fa) -// { -// fa->resetGroupList(); -// } + //*TODO Implement group update for Profile View + // still actual as of July 31, 2009 (DZ) if (gIMMgr) { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index e25bb0a578..0b1ff2e76b 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -373,6 +373,12 @@ private: bool mbAlwaysRun; // Should the avatar run by default rather than walk? bool mbRunning; // Is the avatar trying to run right now? + //-------------------------------------------------------------------- + // Sit and stand + //-------------------------------------------------------------------- +public: + void standUp(); + //-------------------------------------------------------------------- // Busy //-------------------------------------------------------------------- diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 245e358d80..7834e7b2ef 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3997,8 +3997,6 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs) void LLAppViewer::handleLoginComplete() { - gViewerWindow->handleLoginComplete(); - initMainloopTimeout("Mainloop Init"); // Store some data to DebugInfo in case of a freeze. diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index a85f8710c7..40dd20dfa4 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -117,6 +117,24 @@ void LLAvatarList::draw() } } +//virtual +BOOL LLAvatarList::handleMouseDown(S32 x, S32 y, MASK mask) +{ + LLScrollListItem* hit_item = hitItem(x, y); + if (NULL == hit_item) + { + std::vector<LLScrollListItem*> selectedItems = getAllSelected(); + std::vector<LLScrollListItem*>::const_iterator it = selectedItems.begin(); + + for (; it != selectedItems.end(); ++it) + { + (*it)->setSelected(FALSE); + } + return TRUE; + } + return LLScrollListCtrl::handleMouseDown(x, y, mask); +} + std::vector<LLUUID> LLAvatarList::getSelectedIDs() { LLUUID selected_id; diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 8b419dbb57..991e9fa145 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -59,6 +59,14 @@ public: virtual ~LLAvatarList() {} /*virtual*/ void draw(); + /** + * Overrides base-class behavior of Mouse Down Event. + * + * LLScrollListCtrl::handleMouseDown version calls setFocus which select the first item if nothing selected. + * We need to deselect all items if perform click not over the any item. Otherwise calls base method. + * See EXT-246 + */ + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); BOOL update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter = LLStringUtil::null); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 1781e6b3f1..8e1ae7d4f2 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -38,17 +38,14 @@ #include "llfloaterreg.h" #include "llflyoutbutton.h" #include "llnearbychatbar.h" - -//FIXME: temporary, for stand up proto -#include "llselectmgr.h" -#include "llvoavatarself.h" +#include "llsplitbutton.h" +#include "llfloatercamera.h" LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL) , mIMWell(NULL) , mSysWell(NULL) , mTalkBtn(NULL) - , mStandUpBtn(NULL) ////FIXME: temporary, for stand up proto , mNearbyChatBar(NULL) { mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); @@ -61,13 +58,9 @@ LLBottomTray::LLBottomTray(const LLSD&) mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); - ////FIXME: temporary, for stand up proto - mStandUpBtn = getChild<LLButton> ("stand", TRUE, FALSE); - if (mStandUpBtn) - { - mStandUpBtn->setCommitCallback(boost::bind(&LLBottomTray::onCommitStandUp, this, _1)); - } - + LLSplitButton* presets = getChild<LLSplitButton>("presets", TRUE, FALSE); + if (presets) presets->setSelectionCallback(LLFloaterCamera::onClickCameraPresets); + LLIMMgr::getInstance()->addSessionObserver(this); //this is to fix a crash that occurs because LLBottomTray is a singleton @@ -99,6 +92,7 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl) //// Show after comm window so it is frontmost (and hence will not //// auto-hide) //LLIMFloater::show(chiclet->getSessionId()); + chiclet->setCounter(0); } } @@ -113,37 +107,6 @@ void* LLBottomTray::createNearbyChatBar(void* userdata) return bt->mNearbyChatBar; } -//virtual -void LLBottomTray::draw() -{ - refreshStandUp(); - LLPanel::draw(); -} - -void LLBottomTray::refreshStandUp() -{ - //FIXME: temporary, for stand up proto - BOOL sitting = FALSE; - if (gAgent.getAvatarObject()) - { - sitting = gAgent.getAvatarObject()->mIsSitting; - } - - if (mStandUpBtn && mStandUpBtn->getVisible() != sitting) - { - mStandUpBtn->setVisible(sitting); - sendChildToFront(mStandUpBtn); - moveChildToBackOfTabGroup(mStandUpBtn); - } -} - -//FIXME: temporary, for stand up proto -void LLBottomTray::onCommitStandUp(LLUICtrl* ctrl) -{ - LLSelectMgr::getInstance()->deselectAllForStandingUp(); - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); -} - //virtual void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index e5848f72dc..a100124e02 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -56,11 +56,7 @@ public: LLNotificationChiclet* getSysWell() {return mSysWell;} LLNearbyChatBar* getNearbyChatBar() {return mNearbyChatBar;} - /*virtual*/void draw(); - void refreshStandUp(); - void onCommitGesture(LLUICtrl* ctrl); - void onCommitStandUp(LLUICtrl* ctrl); void refreshGestures(); // LLIMSessionObserver observe triggers @@ -82,7 +78,6 @@ protected: LLNotificationChiclet* mIMWell; LLNotificationChiclet* mSysWell; LLTalkButton* mTalkBtn; - LLButton* mStandUpBtn; LLNearbyChatBar* mNearbyChatBar; }; diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 0eb0801a2c..118385ab58 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -45,6 +45,8 @@ using namespace LLNotificationsUI; LLChannelManager::LLChannelManager() { LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLChannelManager::onLoginCompleted, this)); + mChannelList.clear(); + mStartUpChannel = NULL; } //-------------------------------------------------------------------------- @@ -74,7 +76,6 @@ void LLChannelManager::onLoginCompleted() p.id = LLUUID(STARTUP_CHANNEL_ID); p.channel_right_bound = getRootView()->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mStartUpChannel = NULL; mStartUpChannel = createChannel(p); if(!mStartUpChannel) @@ -90,6 +91,7 @@ void LLChannelManager::enableShowToasts() { LLScreenChannel::setStartUpToastShown(); delete mStartUpChannel; + mStartUpChannel = NULL; } //-------------------------------------------------------------------------- @@ -166,6 +168,10 @@ void LLChannelManager::reshape(S32 width, S32 height, BOOL called_from_parent) //-------------------------------------------------------------------------- +LLScreenChannel* LLChannelManager::getStartUpChannel() +{ + return mStartUpChannel; +} //-------------------------------------------------------------------------- diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 3914d20ebc..ac8e81d7ef 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -112,6 +112,8 @@ public: void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + LLScreenChannel* getStartUpChannel(); + private: LLScreenChannel* mStartUpChannel; diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index ee3e465832..81f1beb40d 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -35,24 +35,143 @@ #include "llfloatercamera.h" // Library includes -#include "lluictrlfactory.h" +#include "llfloaterreg.h" // Viewer includes #include "lljoystickbutton.h" +#include "llfirsttimetipmanager.h" #include "llviewercontrol.h" +#include "llbottomtray.h" +#include "llagent.h" +#include "lltoolmgr.h" +#include "lltoolfocus.h" // Constants const F32 CAMERA_BUTTON_DELAY = 0.0f; +#define ORBIT "cam_rotate_stick" +#define PAN "cam_track_stick" +#define CONTROLS "controls" + // // Member functions // + +/*static*/ bool LLFloaterCamera::inFreeCameraMode() +{ + LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance(); + if (floater_camera && floater_camera->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA) + { + return true; + } + return false; +} + +bool LLFloaterCamera::inAvatarViewMode() +{ + return mCurrMode == CAMERA_CTRL_MODE_AVATAR_VIEW; +} + +void LLFloaterCamera::resetFreeCameraMode() +{ + if (mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA) + { + /* Camera Tool can be deselected when we are mouse wheel scrolling into Mouse Look + In such case we are unable to determine that we will be into Mouse Look view */ + if (mPrevMode == CAMERA_CTRL_MODE_AVATAR_VIEW) + { + setMode(CAMERA_CTRL_MODE_ORBIT); + } + else + { + setMode(mPrevMode); + } + } +} + +void LLFloaterCamera::update() +{ + ECameraControlMode mode = determineMode(); + if (mode != mCurrMode) setMode(mode); + LLFirstTimeTipsManager::showTipsFor(mMode2TipType[mode], this); +} + + +/*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() +{ + LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance(); + if (floater_camera && floater_camera->inAvatarViewMode()) + { + floater_camera->toPrevMode(); + } +} + +LLFloaterCamera* LLFloaterCamera::findInstance() +{ + return LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera"); +} + +/*static*/ +void LLFloaterCamera::onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param) +{ + std::string name = param.asString(); + + if ("rear_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_REAR, ctrl); + gAgent.resetView(TRUE, TRUE); + } + else if ("3/4_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_GROUP); + //*TODO implement 3/4 view + } + else if ("front_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_FRONT); + //*TODO implement front view + } + +} + +void LLFloaterCamera::onOpen(const LLSD& key) +{ + updatePosition(); +} + +void LLFloaterCamera::updatePosition() +{ + LLBottomTray* tray = LLBottomTray::getInstance(); + if (!tray) return; + + LLButton* camera_button = tray->getChild<LLButton>("camera_btn", TRUE, FALSE); + if (!camera_button) return; + + //align centers of a button and a floater + S32 x = camera_button->calcScreenRect().getCenterX() - getRect().getWidth()/2; + setOrigin(x, 0); +} + LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLFloater(val) +: LLFloater(val), + mCurrMode(CAMERA_CTRL_MODE_ORBIT), + mPrevMode(CAMERA_CTRL_MODE_ORBIT) { - //// For now, only used for size and tooltip strings - //const BOOL DONT_OPEN = FALSE; - //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_camera.xml", DONT_OPEN); } // virtual @@ -60,10 +179,163 @@ BOOL LLFloaterCamera::postBuild() { setIsChrome(TRUE); - mRotate = getChild<LLJoystickCameraRotate>("cam_rotate_stick"); + mRotate = getChild<LLJoystickCameraRotate>(ORBIT); mZoom = getChild<LLJoystickCameraZoom>("zoom"); - mTrack = getChild<LLJoystickCameraTrack>("cam_track_stick"); + mTrack = getChild<LLJoystickCameraTrack>(PAN); + + initMode2TipTypeMap(); + + assignButton2Mode(CAMERA_CTRL_MODE_ORBIT, "orbit_btn"); + assignButton2Mode(CAMERA_CTRL_MODE_PAN, "pan_btn"); + assignButton2Mode(CAMERA_CTRL_MODE_FREE_CAMERA, "freecamera_btn"); + assignButton2Mode(CAMERA_CTRL_MODE_AVATAR_VIEW, "avatarview_btn"); + + update(); return TRUE; } +ECameraControlMode LLFloaterCamera::determineMode() +{ + LLTool* curr_tool = LLToolMgr::getInstance()->getCurrentTool(); + if (curr_tool == LLToolCamera::getInstance()) + { + return CAMERA_CTRL_MODE_FREE_CAMERA; + } + + if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) + { + return CAMERA_CTRL_MODE_AVATAR_VIEW; + } + + return CAMERA_CTRL_MODE_ORBIT; +} + + +void clear_camera_tool() +{ + LLToolMgr* tool_mgr = LLToolMgr::getInstance(); + if (tool_mgr->usingTransientTool() && + tool_mgr->getCurrentTool() == LLToolCamera::getInstance()) + { + tool_mgr->clearTransientTool(); + } +} + + +void LLFloaterCamera::setMode(ECameraControlMode mode) +{ + if (mode != mCurrMode) + { + mPrevMode = mCurrMode; + mCurrMode = mode; + } + + updateState(); +} + +void LLFloaterCamera::switchMode(ECameraControlMode mode) +{ + setMode(mode); + + switch (mode) + { + case CAMERA_CTRL_MODE_ORBIT: + clear_camera_tool(); + break; + + case CAMERA_CTRL_MODE_PAN: + clear_camera_tool(); + break; + + case CAMERA_CTRL_MODE_FREE_CAMERA: + LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); + break; + + case CAMERA_CTRL_MODE_AVATAR_VIEW: + gAgent.changeCameraToMouselook(); + break; + + default: + //normally we won't occur here + llassert_always(FALSE); + } +} + + +void LLFloaterCamera::onClickBtn(ECameraControlMode mode) +{ + // check for a click on active button + if (mCurrMode == mode) mMode2Button[mode]->setToggleState(TRUE); + + switchMode(mode); + + LLFirstTimeTipsManager::showTipsFor(mMode2TipType[mode], mMode2Button[mode]); +} + +void LLFloaterCamera::assignButton2Mode(ECameraControlMode mode, const std::string& button_name) +{ + LLButton* button = getChild<LLButton>(button_name, TRUE, FALSE); + llassert_always(button); + + if (button) + { + button->setClickedCallback(boost::bind(&LLFloaterCamera::onClickBtn, this, mode)); + mMode2Button[mode] = button; + } +} + +void LLFloaterCamera::initMode2TipTypeMap() +{ + mMode2TipType[CAMERA_CTRL_MODE_ORBIT] = LLFirstTimeTipsManager::FTT_CAMERA_ORBIT_MODE; + mMode2TipType[CAMERA_CTRL_MODE_PAN] = LLFirstTimeTipsManager::FTT_CAMERA_PAN_MODE; + mMode2TipType[CAMERA_CTRL_MODE_FREE_CAMERA] = LLFirstTimeTipsManager::FTT_CAMERA_FREE_MODE; + mMode2TipType[CAMERA_CTRL_MODE_AVATAR_VIEW] = LLFirstTimeTipsManager::FTT_AVATAR_FREE_MODE; +} + + +void LLFloaterCamera::updateState() +{ + //updating buttons + std::map<ECameraControlMode, LLButton*>::const_iterator iter = mMode2Button.begin(); + for (; iter != mMode2Button.end(); ++iter) + { + iter->second->setToggleState(iter->first == mCurrMode); + } + + //updating controls + bool isOrbitMode = CAMERA_CTRL_MODE_ORBIT == mCurrMode; + bool isPanMode = CAMERA_CTRL_MODE_PAN == mCurrMode; + + childSetVisible(ORBIT, isOrbitMode); + childSetVisible(PAN, isPanMode); + + //hiding or showing the panel with controls by reshaping the floater + bool showControls = isOrbitMode || isPanMode; + if (showControls == childIsVisible(CONTROLS)) return; + + childSetVisible(CONTROLS, showControls); + + LLRect rect = getRect(); + LLRect controls_rect; + if (childGetRect(CONTROLS, controls_rect)) + { + static S32 height = controls_rect.getHeight(); + S32 newHeight = rect.getHeight(); + + if (showControls) + { + newHeight += height; + } + else + { + newHeight -= height; + } + + rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), newHeight); + reshape(rect.getWidth(), rect.getHeight()); + setRect(rect); + + } +} + diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index fabe8f577e..04554c6493 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -35,26 +35,94 @@ #include "llfloater.h" +#include "llfirsttimetipmanager.h" + class LLJoystickCameraRotate; class LLJoystickCameraZoom; class LLJoystickCameraTrack; +class LLFloaterReg; + +enum ECameraControlMode +{ + CAMERA_CTRL_MODE_ORBIT, + CAMERA_CTRL_MODE_PAN, + CAMERA_CTRL_MODE_FREE_CAMERA, + CAMERA_CTRL_MODE_AVATAR_VIEW +}; class LLFloaterCamera : public LLFloater { friend class LLFloaterReg; -private: - - LLFloaterCamera(const LLSD& val); - ~LLFloaterCamera() {}; - - /*virtual*/ BOOL postBuild(); public: + + /* whether in free camera mode */ + static bool inFreeCameraMode(); + + static void toPrevModeIfInAvatarViewMode(); + + /* resets free camera mode to the previous mode */ + //*TODO remove, if it won't be used by LLToolCamera::handleDeselect() + void resetFreeCameraMode(); + + /* determines actual mode and updates ui */ + void update(); + static void updateIfNotInAvatarViewMode(); + + static void onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param); + + virtual void onOpen(const LLSD& key); + + // *HACK: due to hard enough to have this control aligned with "Camera" button while resizing + // let update its position in each frame + /*virtual*/ void draw(){updatePosition(); LLFloater::draw();} + LLJoystickCameraRotate* mRotate; LLJoystickCameraZoom* mZoom; LLJoystickCameraTrack* mTrack; + +private: + + LLFloaterCamera(const LLSD& val); + ~LLFloaterCamera() {}; + + /* return instance if it exists - created by LLFloaterReg */ + static LLFloaterCamera* findInstance(); + + /*virtual*/ BOOL postBuild(); + + ECameraControlMode determineMode(); + + /* whether in avatar view (first person) mode */ + bool inAvatarViewMode(); + + /* resets to the previous mode */ + void toPrevMode(); + + /* sets a new mode and performs related actions */ + void switchMode(ECameraControlMode mode); + + /* sets a new mode preserving previous one and updates ui*/ + void setMode(ECameraControlMode mode); + + /* updates the state (UI) according to the current mode */ + void updateState(); + + void onClickBtn(ECameraControlMode mode); + void assignButton2Mode(ECameraControlMode mode, const std::string& button_name); + void initMode2TipTypeMap(); + + /*Updates position of the floater to be center aligned with "Camera" button.*/ + void updatePosition(); + + + ECameraControlMode mPrevMode; + ECameraControlMode mCurrMode; + std::map<ECameraControlMode, LLButton*> mMode2Button; + std::map<ECameraControlMode, LLFirstTimeTipsManager::EFirstTimeTipType> mMode2TipType; + }; #endif diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index cf78d7d34f..1118dd8f69 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -50,7 +50,6 @@ // newview includes #include "llappviewer.h" #include "llfirstuse.h" -#include "llfloateravatarinfo.h" #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfocusmgr.h" diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index cda30d8900..30f4447283 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -39,6 +39,127 @@ #include "llfloatergroupinfo.h" #include "llfloaterreg.h" #include "llimview.h" // for gIMMgr +#include "llgroupmgr.h" +#include "llavataractions.h" +#include "llviewercontrol.h" + +// LLGroupActions::teleport helper +// +// Method is offerTeleport should be called. +// First it checks, whether LLGroupMgr contains LLGroupMgrGroupData for this group already. +// If it's there, processMembersList can be called, which builds vector of ID's for online members and +// calls LLAvatarActions::offerTeleport. +// If LLGroupMgr doesn't contain LLGroupMgrGroupData, then ID of group should be saved in +// mID or queue, if mID is not empty. After that processQueue uses ID from mID or queue, +// registers LLGroupTeleporter as observer at LLGroupMgr and sends request for group members. +// LLGroupMgr notifies about response on this request by calling method 'changed'. +// It calls processMembersList, sets mID to null, to indicate that current group is processed, +// and calls processQueue to process remaining groups. +// The reason of calling of LLGroupMgr::addObserver and LLGroupMgr::removeObserver in +// processQueue and 'changed' methods is that LLGroupMgr notifies observers of only particular group, +// so, for each group mID should be updated and addObserver/removeObserver is called. + +class LLGroupTeleporter : public LLGroupMgrObserver +{ +public: + LLGroupTeleporter() : LLGroupMgrObserver(LLUUID()) {} + + void offerTeleport(const LLUUID& group_id); + + // LLGroupMgrObserver trigger + virtual void changed(LLGroupChange gc); +private: + void processQueue(); + void processMembersList(LLGroupMgrGroupData* gdatap); + + std::queue<LLUUID> mGroupsQueue; +}; + +void LLGroupTeleporter::offerTeleport(const LLUUID& group_id) +{ + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); + + if (!gdatap || !gdatap->isMemberDataComplete()) + { + if (mID.isNull()) + mID = group_id; + else + // Not null mID means that user requested next group teleport before + // previous group is processed, so this group goes to queue + mGroupsQueue.push(group_id); + + processQueue(); + } + else + { + processMembersList(gdatap); + } +} + +// Sends request for group in mID or one group in queue +void LLGroupTeleporter::processQueue() +{ + // Get group from queue, if mID is empty + if (mID.isNull() && !mGroupsQueue.empty()) + { + mID = mGroupsQueue.front(); + mGroupsQueue.pop(); + } + + if (mID.notNull()) + { + LLGroupMgr::getInstance()->addObserver(this); + LLGroupMgr::getInstance()->sendGroupMembersRequest(mID); + } +} + +// Collects all online members of group and offers teleport to them +void LLGroupTeleporter::processMembersList(LLGroupMgrGroupData* gdatap) +{ + U32 limit = gSavedSettings.getU32("GroupTeleportMembersLimit"); + + LLDynamicArray<LLUUID> ids; + for (LLGroupMgrGroupData::member_list_t::iterator iter = gdatap->mMembers.begin(); iter != gdatap->mMembers.end(); iter++) + { + LLGroupMemberData* member = iter->second; + if (!member) + continue; + + if (member->getID() == gAgent.getID()) + // No need to teleport own avatar + continue; + + if (member->getOnlineStatus() == "Online") + ids.push_back(member->getID()); + + if ((U32)ids.size() >= limit) + break; + } + + LLAvatarActions::offerTeleport(ids); +} + +// LLGroupMgrObserver trigger +void LLGroupTeleporter::changed(LLGroupChange gc) +{ + if (gc == GC_MEMBER_DATA) + { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); + + if (gdatap && gdatap->isMemberDataComplete()) + processMembersList(gdatap); + + LLGroupMgr::getInstance()->removeObserver(this); + + // group in mID is processed + mID.setNull(); + + // process other groups in queue, if any + processQueue(); + } +} + +static LLGroupTeleporter sGroupTeleporter; // static void LLGroupActions::search() @@ -119,6 +240,12 @@ void LLGroupActions::startChat(const LLUUID& group_id) } } +// static +void LLGroupActions::offerTeleport(const LLUUID& group_id) +{ + sGroupTeleporter.offerTeleport(group_id); +} + //-- Private methods ---------------------------------------------------------- // static diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 1e6caea17c..b6ddb4511a 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -71,6 +71,11 @@ public: * Start group instant messaging session. */ static void startChat(const LLUUID& group_id); + + /** + * Offers teleport for online members of group + */ + static void offerTeleport(const LLUUID& group_id); private: static bool onLeaveGroup(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp index 471a0868bc..68143fd1e3 100644 --- a/indra/newview/lllocationhistory.cpp +++ b/indra/newview/lllocationhistory.cpp @@ -47,6 +47,12 @@ void LLLocationHistory::addItem(std::string item) { static LLUICachedControl<S32> max_items("LocationHistoryMaxSize", 100); + std::vector<std::string>::iterator item_iter = std::find(mItems.begin(), mItems.end(), item); + + if (item_iter != mItems.end()) { + mItems.erase(item_iter); + } + mItems.push_back(item); // If the vector size exceeds the maximum, purge the oldest items. @@ -56,7 +62,7 @@ void LLLocationHistory::addItem(std::string item) void LLLocationHistory::removeItems() { - mItems.erase(mItems.begin(), mItems.end()); + mItems.clear(); } diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 94abd128c4..3880ea91eb 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -54,6 +54,7 @@ #include "llsidetray.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" +#include "llviewercontrol.h" //============================================================================ /* @@ -330,6 +331,13 @@ void LLLocationInputCtrl::onFocusLost() LLUICtrl::onFocusLost(); refreshLocation(); } +void LLLocationInputCtrl::draw(){ + + if(!hasFocus()){ + refreshLocation(); + } + LLComboBox::draw(); +} void LLLocationInputCtrl::onInfoButtonClicked() { @@ -341,8 +349,7 @@ void LLLocationInputCtrl::onAddLandmarkButtonClicked() LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); // Floater "Add Landmark" functionality moved to Side Tray - // TODO* Disable floater "Add Landmark" call - LLFloaterReg::showInstance("add_landmark"); + //LLFloaterReg::showInstance("add_landmark"); } void LLLocationInputCtrl::onAgentParcelChange() @@ -387,8 +394,10 @@ void LLLocationInputCtrl::refreshLocation() // Update location field. std::string location_name; + LLAgent::ELocationFormat format = (gSavedSettings.getBOOL("ShowCoordinatesOption") ? + LLAgent::LOCATION_FORMAT_FULL: LLAgent::LOCATION_FORMAT_NORMAL); - if (!gAgent.buildLocationString(location_name, LLAgent::LOCATION_FORMAT_NORMAL)) + if (!gAgent.buildLocationString(location_name,format)) location_name = "Unknown"; setText(location_name); diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 2cc63a33b7..bda67fd313 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -71,6 +71,7 @@ public: /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); + /*virtual*/ void draw(); //======================================================================== // LLUICtrl interface diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 963be61d93..124a2def7f 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -40,12 +40,17 @@ // Viewer includes #include "llagent.h" +#include "llvoavatarself.h" // to check gAgent.getAvatarObject()->isSitting() +#include "llbottomtray.h" #include "llbutton.h" +#include "llfirsttimetipmanager.h" #include "llfloaterreg.h" +#include "llfloaterfirsttimetip.h" #include "lljoystickbutton.h" #include "lluictrlfactory.h" #include "llviewerwindow.h" #include "llviewercontrol.h" +#include "llselectmgr.h" // // Constants @@ -55,17 +60,24 @@ const F32 MOVE_BUTTON_DELAY = 0.0f; const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed const F32 NUDGE_TIME = 0.25f; // in seconds +const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn"; + // // Member functions // // protected LLFloaterMove::LLFloaterMove(const LLSD& key) -: LLFloater(key) +: LLFloater(key), + mForwardButton(NULL), + mBackwardButton(NULL), + mTurnLeftButton(NULL), + mTurnRightButton(NULL), + mMoveUpButton(NULL), + mMoveDownButton(NULL), + mStopFlyingButton(NULL), + mModeActionsPanel(NULL) { - -// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_moveview.xml", DONT_OPEN); - } // virtual @@ -80,36 +92,55 @@ BOOL LLFloaterMove::postBuild() mBackwardButton = getChild<LLJoystickAgentTurn>("backward btn"); mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mSlideLeftButton = getChild<LLJoystickAgentSlide>("slide left btn"); - mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - - mSlideRightButton = getChild<LLJoystickAgentSlide>("slide right btn"); - mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnLeftButton = getChild<LLButton>("turn left btn"); mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnLeftButton->setHeldDownCallback( turnLeft, NULL ); - + mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this)); mTurnRightButton = getChild<LLButton>("turn right btn"); mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnRightButton->setHeldDownCallback( turnRight, NULL ); + mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this)); mMoveUpButton = getChild<LLButton>("move up btn"); - childSetAction("move up btn",moveUp,NULL); mMoveUpButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mMoveUpButton->setHeldDownCallback( moveUp, NULL ); + mMoveUpButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveUp, this)); mMoveDownButton = getChild<LLButton>("move down btn"); - childSetAction("move down btn",moveDown,NULL); mMoveDownButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mMoveDownButton->setHeldDownCallback( moveDown, NULL ); + mMoveDownButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveDown, this)); + + + mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); + + mModeActionsPanel = getChild<LLPanel>("panel_modes"); + + LLButton* btn; + btn = getChild<LLButton>("mode_walk_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onWalkButtonClick, this)); + + btn = getChild<LLButton>("mode_run_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onRunButtonClick, this)); + + btn = getChild<LLButton>("mode_fly_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onFlyButtonClick, this)); + + btn = getChild<LLButton>("stop_fly_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onStopFlyingButtonClick, this)); + + + + showFlyControls(false); + + initModeTooltips(); + + updatePosition(); + + initModeButtonMap(); + + initMovementMode(); + return TRUE; } -// -// Static member functions -// -// protected static +// static F32 LLFloaterMove::getYawRate( F32 time ) { if( time < NUDGE_TIME ) @@ -123,38 +154,431 @@ F32 LLFloaterMove::getYawRate( F32 time ) } } -// protected static -void LLFloaterMove::turnLeft(void *) + +// static +void LLFloaterMove::setFlyingMode(BOOL fly) { - LLFloaterMove* instance = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); - if(!instance) return; - - F32 time = instance->mTurnLeftButton->getHeldDownTime(); + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + instance->setFlyingModeImpl(fly); + instance->showModeButtons(!fly); + } + if (fly) + { + LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); + } + else + { + LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING); + } +} +//static +void LLFloaterMove::setAlwaysRunMode(bool run) +{ + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + instance->setAlwaysRunModeImpl(run); + } +} + +void LLFloaterMove::setFlyingModeImpl(BOOL fly) +{ + updateButtonsWithMovementMode(fly ? MM_FLY : (gAgent.getAlwaysRun() ? MM_RUN : MM_WALK)); +} + +void LLFloaterMove::setAlwaysRunModeImpl(bool run) +{ + if (!gAgent.getFlying()) + { + updateButtonsWithMovementMode(run ? MM_RUN : MM_WALK); + } +} + +//static +void LLFloaterMove::setSittingMode(BOOL bSitting) +{ + if (bSitting) + { + LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND); + } + else + { + LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND); + } + enableInstance(!bSitting); +} + +// protected +void LLFloaterMove::turnLeft() +{ + F32 time = mTurnLeftButton->getHeldDownTime(); gAgent.moveYaw( getYawRate( time ) ); } -// protected static -void LLFloaterMove::turnRight(void *) +// protected +void LLFloaterMove::turnRight() { - LLFloaterMove* instance = LLFloaterReg::getTypedInstance<LLFloaterMove>("moveview"); - if(!instance) return; - - F32 time = instance->mTurnRightButton->getHeldDownTime(); + F32 time = mTurnRightButton->getHeldDownTime(); gAgent.moveYaw( -getYawRate( time ) ); } -// protected static -void LLFloaterMove::moveUp(void *) +// protected +void LLFloaterMove::moveUp() { // Jumps or flys up, depending on fly state gAgent.moveUp(1); } -// protected static -void LLFloaterMove::moveDown(void *) +// protected +void LLFloaterMove::moveDown() { // Crouches or flys down, depending on fly state gAgent.moveUp(-1); } +////////////////////////////////////////////////////////////////////////// +// Private Section: +////////////////////////////////////////////////////////////////////////// + +void LLFloaterMove::onWalkButtonClick() +{ + setMovementMode(MM_WALK); +} +void LLFloaterMove::onRunButtonClick() +{ + setMovementMode(MM_RUN); +} +void LLFloaterMove::onFlyButtonClick() +{ + setMovementMode(MM_FLY); +} +void LLFloaterMove::onStopFlyingButtonClick() +{ + setMovementMode(gAgent.getAlwaysRun() ? MM_RUN : MM_WALK); +} + +void LLFloaterMove::setMovementMode(const EMovementMode mode) +{ + gAgent.setFlying(MM_FLY == mode); + + switch (mode) + { + case MM_RUN: + gAgent.setAlwaysRun(); + gAgent.setRunning(); + break; + case MM_WALK: + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + break; + default: + //do nothing for other modes (MM_FLY) + break; + } + // tell the simulator. + gAgent.sendWalkRun(gAgent.getAlwaysRun()); + + updateButtonsWithMovementMode(mode); + + bool bHideModeButtons = MM_FLY == mode + || (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()); + + showModeButtons(!bHideModeButtons); + + showQuickTips(mode); +} + +void LLFloaterMove::updateButtonsWithMovementMode(const EMovementMode newMode) +{ + showFlyControls(MM_FLY == newMode); + setModeTooltip(newMode); + setModeButtonToggleState(newMode); +} + +void LLFloaterMove::showFlyControls(bool bShow) +{ + mMoveUpButton->setVisible(bShow); + mMoveDownButton->setVisible(bShow); + + // *TODO: mantipov: mStopFlyingButton from the FloaterMove is not used now. + // It was not completly removed until functionality is reviewed by LL + mStopFlyingButton->setVisible(FALSE); +} + +void LLFloaterMove::initModeTooltips() +{ + control_tooltip_map_t walkTipMap; + walkTipMap.insert(std::make_pair(mForwardButton, getString("walk_forward_tooltip"))); + walkTipMap.insert(std::make_pair(mBackwardButton, getString("walk_back_tooltip"))); + mModeControlTooltipsMap[MM_WALK] = walkTipMap; + + control_tooltip_map_t runTipMap; + runTipMap.insert(std::make_pair(mForwardButton, getString("run_forward_tooltip"))); + runTipMap.insert(std::make_pair(mBackwardButton, getString("run_back_tooltip"))); + mModeControlTooltipsMap[MM_RUN] = runTipMap; + + control_tooltip_map_t flyTipMap; + flyTipMap.insert(std::make_pair(mForwardButton, getString("fly_forward_tooltip"))); + flyTipMap.insert(std::make_pair(mBackwardButton, getString("fly_back_tooltip"))); + mModeControlTooltipsMap[MM_FLY] = flyTipMap; + + setModeTooltip(MM_WALK); +} + +void LLFloaterMove::initModeButtonMap() +{ + mModeControlButtonMap[MM_WALK] = getChild<LLButton>("mode_walk_btn"); + mModeControlButtonMap[MM_RUN] = getChild<LLButton>("mode_run_btn"); + mModeControlButtonMap[MM_FLY] = getChild<LLButton>("mode_fly_btn"); +} + +void LLFloaterMove::initMovementMode() +{ + EMovementMode initMovementMode = gAgent.getAlwaysRun() ? MM_RUN : MM_WALK; + if (gAgent.getFlying()) + { + initMovementMode = MM_FLY; + } + setMovementMode(initMovementMode); + + if (gAgent.getAvatarObject()) + { + setEnabled(!gAgent.getAvatarObject()->isSitting()); + } +} + +void LLFloaterMove::setModeTooltip(const EMovementMode mode) +{ + llassert_always(mModeControlTooltipsMap.end() != mModeControlTooltipsMap.find(mode)); + control_tooltip_map_t controlsTipMap = mModeControlTooltipsMap[mode]; + control_tooltip_map_t::const_iterator it = controlsTipMap.begin(); + for (; it != controlsTipMap.end(); ++it) + { + LLView* ctrl = it->first; + std::string tooltip = it->second; + ctrl->setToolTip(tooltip); + } +} + +/** + * Updates position of the floater to be center aligned with Move button. + * + * Because Tip floater created as dependent floater this method + * must be called before "showQuickTips()" to get Tip floater be positioned at the right side of the floater + */ +void LLFloaterMove::updatePosition() +{ + LLBottomTray* tray = LLBottomTray::getInstance(); + if (!tray) return; + + LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME, TRUE, FALSE); + if (!movement_btn) return; + + //align centers of a button and a floater + S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2; + + S32 y = 0; + if (!mModeActionsPanel->getVisible()) + { + y = mModeActionsPanel->getRect().getHeight(); + } + setOrigin(x, y); +} +void LLFloaterMove::showModeButtons(BOOL bShow) +{ + if (mModeActionsPanel->getVisible() == bShow) + return; + mModeActionsPanel->setVisible(bShow); + + LLRect rect = getRect(); + + static S32 height = mModeActionsPanel->getRect().getHeight(); + S32 newHeight = getRect().getHeight(); + if (!bShow) + { + newHeight -= height; + } + else + { + newHeight += height; + } + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), newHeight); + reshape(rect.getWidth(), rect.getHeight()); + setRect(rect); +} +//static +void LLFloaterMove::enableInstance(BOOL bEnable) +{ + LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview"); + if (instance) + { + instance->setEnabled(bEnable); + instance->showModeButtons(bEnable); + } +} + +void LLFloaterMove::onOpen(const LLSD& key) +{ + updatePosition(); +} + +void LLFloaterMove::showQuickTips(const EMovementMode mode) +{ + LLFirstTimeTipsManager::EFirstTimeTipType tipType = LLFirstTimeTipsManager::FTT_MOVE_WALK; + switch (mode) + { + case MM_FLY: tipType = LLFirstTimeTipsManager::FTT_MOVE_FLY; break; + case MM_RUN: tipType = LLFirstTimeTipsManager::FTT_MOVE_RUN; break; + case MM_WALK: tipType = LLFirstTimeTipsManager::FTT_MOVE_WALK; break; + default: llwarns << "Quick Tip type was not detected, FTT_MOVE_WALK will be used" << llendl; + } + + LLFirstTimeTipsManager::showTipsFor(tipType, this); +} + +void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode) +{ + llassert_always(mModeControlButtonMap.end() != mModeControlButtonMap.find(mode)); + + mode_control_button_map_t::const_iterator it = mModeControlButtonMap.begin(); + for (; it != mModeControlButtonMap.end(); ++it) + { + it->second->setToggleState(FALSE); + } + + mModeControlButtonMap[mode]->setToggleState(TRUE); +} + + + +/************************************************************************/ +/* LLPanelStandStopFlying */ +/************************************************************************/ +LLPanelStandStopFlying::LLPanelStandStopFlying() : + mStandButton(NULL), + mStopFlyingButton(NULL) +{ + // make sure we have the only instance of this class + static bool b = true; + llassert_always(b); + b=false; +} + +// static +inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance() +{ + static LLPanelStandStopFlying* panel = getStandStopFlyingPanel(); + return panel; +} + +//static +void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode) +{ + LLPanelStandStopFlying* panel = getInstance(); + panel->setVisible(TRUE); + + BOOL standVisible = SSFM_STAND == mode; + panel->mStandButton->setVisible(standVisible); + panel->mStopFlyingButton->setVisible(!standVisible); +} + +//static +void LLPanelStandStopFlying::clearStandStopFlyingMode(EStandStopFlyingMode mode) +{ + LLPanelStandStopFlying* panel = getInstance(); + switch(mode) { + case SSFM_STAND: + panel->mStandButton->setVisible(FALSE); + break; + case SSFM_STOP_FLYING: + panel->mStopFlyingButton->setVisible(FALSE); + break; + default: + llerrs << "Unexpected EStandStopFlyingMode is passed: " << mode << llendl; + } + +} + +BOOL LLPanelStandStopFlying::postBuild() +{ + mStandButton = getChild<LLButton>("stand_btn"); + mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this)); + mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE)); + + mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); + mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); + mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this)); + + + return TRUE; +} + +//virtual +void LLPanelStandStopFlying::setVisible(BOOL visible) +{ + if (visible) + { + updatePosition(); + } + + LLPanel::setVisible(visible); +} + +////////////////////////////////////////////////////////////////////////// +// Private Section +////////////////////////////////////////////////////////////////////////// + +//static +LLPanelStandStopFlying* LLPanelStandStopFlying::getStandStopFlyingPanel() +{ + LLPanelStandStopFlying* panel = new LLPanelStandStopFlying(); + LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_stand_stop_flying.xml"); + + panel->setVisible(FALSE); + LLUI::getRootView()->addChild(panel); + + llinfos << "Build LLPanelStandStopFlying panel" << llendl; + + panel->updatePosition(); + return panel; +} + +void LLPanelStandStopFlying::onStandButtonClick() +{ + LLSelectMgr::getInstance()->deselectAllForStandingUp(); + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + + setVisible(FALSE); +} + +void LLPanelStandStopFlying::onStopFlyingButtonClick() +{ + gAgent.setFlying(FALSE); + + setVisible(FALSE); +} + +/** + * Updates position of the Stand & Stop Flying panel to be center aligned with Move button. + */ +void LLPanelStandStopFlying::updatePosition() +{ + + LLBottomTray* tray = LLBottomTray::getInstance(); + if (!tray) return; + + LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME, TRUE, FALSE); + if (!movement_btn) return; + + //align centers of a button and a floater + S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2; + + S32 y = tray->getRect().getHeight(); + + setOrigin(x, y); +} + + // EOF diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h index 250315b9f2..fd9cf9f4c1 100644 --- a/indra/newview/llmoveview.h +++ b/indra/newview/llmoveview.h @@ -55,26 +55,106 @@ public: /*virtual*/ BOOL postBuild(); static F32 getYawRate(F32 time); + static void setFlyingMode(BOOL fly); + void setFlyingModeImpl(BOOL fly); + static void setAlwaysRunMode(bool run); + void setAlwaysRunModeImpl(bool run); + static void setSittingMode(BOOL bSitting); + static void enableInstance(BOOL bEnable); + /*virtual*/ void onOpen(const LLSD& key); + + // *HACK: due to hard enough to have this control aligned with "Move" button while resizing + // let update its position in each frame + /*virtual*/ void draw(){updatePosition(); LLFloater::draw();} + protected: - static void turnLeftNudge(void* userdata); - static void turnLeft(void* userdata); - - static void turnRightNudge(void* userdata); - static void turnRight(void* userdata); + void turnLeft(); + void turnRight(); - static void moveUp(void* userdata); - static void moveDown(void* userdata); + void moveUp(); + void moveDown(); + +private: + typedef enum movement_mode_t + { + MM_WALK, + MM_RUN, + MM_FLY + } EMovementMode; + void onWalkButtonClick(); + void onRunButtonClick(); + void onFlyButtonClick(); + void onStopFlyingButtonClick(); + void initMovementMode(); + void setMovementMode(const EMovementMode mode); + void showFlyControls(bool bShow); + void initModeTooltips(); + void setModeTooltip(const EMovementMode mode); + void showQuickTips(const EMovementMode mode); + void initModeButtonMap(); + void setModeButtonToggleState(const EMovementMode mode); + void updateButtonsWithMovementMode(const EMovementMode newMode); + void updatePosition(); + void showModeButtons(BOOL bShow); public: + LLJoystickAgentTurn* mForwardButton; LLJoystickAgentTurn* mBackwardButton; - LLJoystickAgentSlide* mSlideLeftButton; - LLJoystickAgentSlide* mSlideRightButton; LLButton* mTurnLeftButton; LLButton* mTurnRightButton; LLButton* mMoveUpButton; LLButton* mMoveDownButton; +private: + LLButton* mStopFlyingButton; + LLPanel* mModeActionsPanel; + + typedef std::map<LLView*, std::string> control_tooltip_map_t; + typedef std::map<EMovementMode, control_tooltip_map_t> mode_control_tooltip_map_t; + mode_control_tooltip_map_t mModeControlTooltipsMap; + + typedef std::map<EMovementMode, LLButton*> mode_control_button_map_t; + mode_control_button_map_t mModeControlButtonMap; + +}; + + +/** + * This class contains Stand Up and Stop Flying buttons displayed above Move button in bottom tray + */ +class LLPanelStandStopFlying : public LLPanel +{ +public: + typedef enum stand_stop_flying_mode_t + { + SSFM_STAND, + SSFM_STOP_FLYING + } EStandStopFlyingMode; + + static LLPanelStandStopFlying* getInstance(); + static void setStandStopFlyingMode(EStandStopFlyingMode mode); + static void clearStandStopFlyingMode(EStandStopFlyingMode mode); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + + // *HACK: due to hard enough to have this control aligned with "Move" button while resizing + // let update its position in each frame + /*virtual*/ void draw(){updatePosition(); LLPanel::draw();} + + +protected: + LLPanelStandStopFlying(); + + +private: + static LLPanelStandStopFlying* getStandStopFlyingPanel(); + void onStandButtonClick(); + void onStopFlyingButtonClick(); + void updatePosition(); + + LLButton* mStandButton; + LLButton* mStopFlyingButton; }; diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 58ec2d24a8..06cab9afb0 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -47,12 +47,15 @@ #include "lllocationinputctrl.h" #include "llteleporthistory.h" #include "llsearcheditor.h" +#include "llsidetray.h" #include "llslurl.h" #include "llurlsimstring.h" #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" #include "llworldmap.h" +#include "llappviewer.h" +#include "llviewercontrol.h" //-- LLTeleportHistoryMenuItem ----------------------------------------------- @@ -190,6 +193,9 @@ LLNavigationBar::LLNavigationBar() // navigation bar can never get a tab setFocusRoot(FALSE); + + // set a listener function for LoginComplete event + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLNavigationBar::handleLoginComplete, this)); } LLNavigationBar::~LLNavigationBar() @@ -253,7 +259,7 @@ void LLNavigationBar::draw() LLPanel::draw(); } -BOOL LLNavigationBar::handleRightMouseDown(S32 x, S32 y, MASK mask) +BOOL LLNavigationBar::handleRightMouseUp(S32 x, S32 y, MASK mask) { // *HACK. We should use mCmbLocation's right click callback instead. @@ -271,7 +277,7 @@ BOOL LLNavigationBar::handleRightMouseDown(S32 x, S32 y, MASK mask) } return TRUE; } - return LLPanel:: handleRightMouseDown(x, y, mask); + return LLPanel:: handleRightMouseUp(x, y, mask); } void LLNavigationBar::onBackButtonClicked() @@ -410,21 +416,26 @@ void LLNavigationBar::onRegionNameResponse( } // Location is valid. Add it to the typed locations history. + // If user has typed text this variable will contain -1. S32 selected_item = mCmbLocation->getCurrentIndex(); - if (selected_item == -1) // user has typed text - { - LLLocationHistory* lh = LLLocationHistory::getInstance(); - mCmbLocation->add(typed_location); - lh->addItem(typed_location); - lh->save(); - } + + /* + LLLocationHistory* lh = LLLocationHistory::getInstance(); + lh->addItem(selected_item == -1 ? typed_location : mCmbLocation->getSelectedItemLabel()); + lh->save(); + */ // Teleport to the location. LLVector3d region_pos = from_region_handle(region_handle); LLVector3d global_pos = region_pos + (LLVector3d) local_coords; + llinfos << "Teleporting to: " << global_pos << llendl; gAgent.teleportViaLocation(global_pos); + + LLLocationHistory* lh = LLLocationHistory::getInstance(); + lh->addItem(selected_item == -1 ? typed_location : mCmbLocation->getSelectedItemLabel()); + lh->save(); } void LLNavigationBar::showTeleportHistoryMenu() @@ -456,18 +467,16 @@ void LLNavigationBar::onLocationContextMenuItemClicked(const LLSD& userdata) std::string item = userdata.asString(); LLLineEditor* location_entry = mCmbLocation->getTextEntry(); - if (item == std::string("copy_url")) + if (item == std::string("show_coordinates")) { - std::string sl_url = gAgent.getSLURL(); - LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(sl_url)); - - LLSD args; - args["SLURL"] = sl_url; - LLNotifications::instance().add("CopySLURL", args); + gSavedSettings.setBOOL("ShowCoordinatesOption",!gSavedSettings.getBOOL("ShowCoordinatesOption")); } else if (item == std::string("landmark")) { - LLFloaterReg::showInstance("add_landmark"); + LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); + + // Floater "Add Landmark" functionality moved to Side Tray + //LLFloaterReg::showInstance("add_landmark"); } else if (item == std::string("cut")) { @@ -519,6 +528,9 @@ bool LLNavigationBar::onLocationContextMenuItemEnabled(const LLSD& userdata) else if(item == std::string("can_landmark")) { return !LLLandmarkActions::landmarkAlreadyExists(); + }else if(item == std::string("show_coordinates")){ + + return gSavedSettings.getBOOL("ShowCoordinatesOption"); } return false; diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index a46c59306d..17a1438912 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -56,7 +56,7 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL postBuild(); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); void handleLoginComplete(); void clearHistoryCache(); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 847262ddfd..1fa1e2a09d 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -252,7 +252,8 @@ void LLNearbyChat::addMessage(const LLChat& chat) void LLNearbyChat::onNearbySpeakers() { - LLSD param = "nearby_panel"; + LLSD param; + param["people_panel_tab_name"] = "nearby_panel"; LLSideTray::getInstance()->showPanel("panel_people",param); } diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 7b67ae645c..a3100f65ca 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -50,6 +50,16 @@ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 static LLDefaultChildRegistry::Register<LLGestureComboBox> r("gesture_combo_box"); +struct LLChatTypeTrigger { + std::string name; + EChatType type; +}; + +static LLChatTypeTrigger sChatTypeTriggers[] = { + { "/whisper" , CHAT_TYPE_WHISPER}, + { "/shout" , CHAT_TYPE_SHOUT} +}; + LLGestureComboBox::LLGestureComboBox(const LLComboBox::Params& p) : LLComboBox(p) , mGestureLabelTimer() @@ -219,12 +229,38 @@ BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) return handled; } +BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ + U32 in_len = in_str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + for (S32 n = 0; n < cnt; n++) + { + if (in_len > sChatTypeTriggers[n].name.length()) + continue; + + std::string trigger_trunc = sChatTypeTriggers[n].name; + LLStringUtil::truncate(trigger_trunc, in_len); + + if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) + { + *out_str = sChatTypeTriggers[n].name; + return TRUE; + } + } + + return FALSE; +} + void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) { + LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - LLWString raw_text; - if (self->mChatBox) raw_text = self->mChatBox->getWText(); + if (!self->mChatBox) + return; + + LLWString raw_text = self->mChatBox->getWText(); // Can't trim the end, because that will cause autocompletion // to eat trailing spaces that might be part of a gesture. @@ -270,16 +306,19 @@ void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str)) { - if (self->mChatBox) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part - S32 outlength = self->mChatBox->getLength(); // in characters - - // Select to end of line, starting from the character - // after the last one the user typed. - self->mChatBox->setSelection(length, outlength); - } + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + S32 outlength = self->mChatBox->getLength(); // in characters + + // Select to end of line, starting from the character + // after the last one the user typed. + self->mChatBox->setSelection(length, outlength); + } + else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part + self->mChatBox->setCursorToEnd(); } //llinfos << "GESTUREDEBUG " << trigger @@ -296,6 +335,38 @@ void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userd gAgent.stopTyping(); } +EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) +{ + U32 length = str.length(); + S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); + + for (S32 n = 0; n < cnt; n++) + { + if (length >= sChatTypeTriggers[n].name.length()) + { + std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + + if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) + { + U32 trigger_length = sChatTypeTriggers[n].name.length(); + + // It's to remove space after trigger name + if (length > trigger_length && str[trigger_length] == ' ') + trigger_length++; + + str = str.substr(trigger_length, length); + + if (CHAT_TYPE_NORMAL == type) + return sChatTypeTriggers[n].type; + else + break; + } + } + } + + return type; +} + void LLNearbyChatBar::sendChat( EChatType type ) { if (mChatBox) @@ -324,6 +395,8 @@ void LLNearbyChatBar::sendChat( EChatType type ) utf8_revised_text = utf8str_trim(utf8_revised_text); + type = processChatTypeTriggers(type, utf8_revised_text); + if (!utf8_revised_text.empty()) { // Chat with animation diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index d1f5fbff6b..9c2a72aaf3 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -86,6 +86,7 @@ public: static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); protected: + static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); @@ -93,6 +94,7 @@ protected: void onChatBoxCommit(); static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); + EChatType processChatTypeTriggers(EChatType type, std::string &str); // Which non-zero channel did we last chat on? static S32 sLastSpecialChatChannel; diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index a24d1ed54a..0eb96f992a 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -231,7 +231,7 @@ void LLOverlayBar::refresh() BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } button = getChild<LLButton>("Stand Up"); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index f57489934a..91156ae542 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -269,7 +269,7 @@ void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType ty childSetValue("sl_description_edit", avatar_data->about_text); childSetValue("fl_description_edit",avatar_data->fl_about_text); childSetValue("2nd_life_pic", avatar_data->image_id); - childSetValue("1st_life_pic", avatar_data->fl_image_id); + childSetValue("real_world_pic", avatar_data->fl_image_id); childSetValue("homepage_edit", avatar_data->profile_url); if (!isEditMode()) @@ -365,7 +365,7 @@ void LLPanelAvatarProfile::clear() void LLPanelAvatarProfile::clearControls() { childSetValue("2nd_life_pic",LLUUID::null); - childSetValue("1st_life_pic",LLUUID::null); + childSetValue("real_world_pic",LLUUID::null); childSetValue("online_status",LLStringUtil::null); childSetValue("status_message",LLStringUtil::null); childSetValue("sl_description_edit",LLStringUtil::null); @@ -489,7 +489,7 @@ void LLPanelAvatarProfile::onShareButtonClick() { pic->setFallbackImageName("default_land_picture.j2c"); } - pic = getChild<LLTextureCtrl>("1st_life_pic",TRUE,FALSE); + pic = getChild<LLTextureCtrl>("real_world_pic",TRUE,FALSE); if(pic) { pic->setFallbackImageName("default_land_picture.j2c"); @@ -510,13 +510,13 @@ void LLPanelAvatarProfile::onOpen(const LLSD& key) void LLPanelAvatarProfile::updateChildrenList() { - if (mUpdated || isEditMode()) - { - return; - } switch (mProfileType) { case PT_OWN: + if (mUpdated || isEditMode()) + { + return; + } childSetVisible("user_name", true); childSetVisible("status_panel", false); childSetVisible("profile_buttons_panel", false); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 92a8653252..2f63033437 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -539,7 +539,7 @@ void LLPanelPeople::updateButtons() } bool item_selected = selected_id.notNull(); - buttonSetEnabled("teleport_btn", friends_tab_active && item_selected); + buttonSetEnabled("teleport_btn", (friends_tab_active || group_tab_active) && item_selected); buttonSetEnabled("view_profile_btn", item_selected); buttonSetEnabled("im_btn", item_selected); buttonSetEnabled("call_btn", item_selected && false); // not implemented yet @@ -771,7 +771,16 @@ void LLPanelPeople::onCallButtonClicked() void LLPanelPeople::onTeleportButtonClicked() { - LLAvatarActions::offerTeleport(getCurrentItemID()); + std::string cur_tab = mTabContainer->getCurrentPanel()->getName(); + + if (cur_tab == FRIENDS_TAB_NAME) + { + LLAvatarActions::offerTeleport(getCurrentItemID()); + } + else if (cur_tab == GROUP_TAB_NAME) + { + LLGroupActions::offerTeleport(getCurrentItemID()); + } } void LLPanelPeople::onShareButtonClicked() @@ -786,22 +795,10 @@ void LLPanelPeople::onMoreButtonClicked() void LLPanelPeople::onOpen(const LLSD& key) { - // Profile View is activated through LLSideTray::showPanel(), - // hide Profile View to be able to see Panel People content - hideProfileView(); - - std::string tab_name = key.asString(); + std::string tab_name = key["people_panel_tab_name"]; if (!tab_name.empty()) mTabContainer->selectTabByName(tab_name); else reSelectedCurrentTab(); } -void LLPanelPeople::hideProfileView() -{ - LLView* view = getChildView("panel_profile_view",true,false); - if(view && view->getVisible()) - { - view->setVisible(false); - } -} diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 2ac1bf424c..6c3b5e0664 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -104,8 +104,6 @@ private: const std::vector<LLUUID>& ids, void*); - void hideProfileView(); - LLFilterEditor* mFilterEditor; LLTabContainer* mTabContainer; LLAvatarList* mFriendList; diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index ea05b666db..40275be82f 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -51,6 +51,7 @@ #include "llagent.h" #include "llfloaterworldmap.h" #include "llinventorymodel.h" +#include "lllandmarkactions.h" #include "lltexturectrl.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" @@ -487,6 +488,26 @@ void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type) } } +void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id) +{ + std::string name = mTitleEditor->getText(); + std::string desc = mNotesEditor->getText(); + + LLStringUtil::trim(name); + LLStringUtil::trim(desc); + + // If typed name is empty use the parcel name instead. + if (name.empty()) + { + name = mParcelName->getText() + "; " + mRegionName->getText(); + } + + LLStringUtil::replaceChar(desc, '\n', ' '); + // If no folder chosen use the "Landmarks" folder. + LLLandmarkActions::createLandmarkHere(name, desc, + folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)); +} + void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent) { if (mMinHeight > 0) diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index f06a2d1fb7..e7b81dc3e6 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -79,6 +79,10 @@ public: // sets a corresponding title and contents. void setInfoType(INFO_TYPE type); + // Create a landmark for the current location + // in a folder specified by folder_id + void createLandmark(const LLUUID& folder_id); + BOOL isMediaPanelVisible(); void toggleMediaPanel(BOOL visible); void displayItemInfo(const LLInventoryItem* pItem); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index b443cc4d5e..1fb3eb8b71 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -39,6 +39,7 @@ #include "llnotifications.h" #include "llfiltereditor.h" #include "lltabcontainer.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llagent.h" @@ -48,11 +49,15 @@ #include "llpanellandmarks.h" #include "llpanelteleporthistory.h" #include "llsidetray.h" +#include "lltoggleablemenu.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" -// Helper function to get local position from global -const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global); +// Helper functions +static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); +static std::string getFullFolderName(const LLViewerInventoryCategory* cat); +static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); +static const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global); static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places"); @@ -63,6 +68,7 @@ LLPanelPlaces::LLPanelPlaces() mFilterEditor(NULL), mPlaceInfo(NULL), mItem(NULL), + mLandmarkFoldersMenuHandle(), mPosGlobal() { gInventory.addObserver(this); @@ -77,17 +83,25 @@ LLPanelPlaces::~LLPanelPlaces() { if (gInventory.containsObserver(this)) gInventory.removeObserver(this); + + LLView::deleteViewByHandle(mLandmarkFoldersMenuHandle); } BOOL LLPanelPlaces::postBuild() { + mCreateLandmarkBtn = getChild<LLButton>("create_landmark_btn"); + mCreateLandmarkBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, LLUUID())); + + mFolderMenuBtn = getChild<LLButton>("folder_menu_btn"); + mFolderMenuBtn->setClickedCallback(boost::bind(&LLPanelPlaces::showLandmarkFoldersMenu, this)); + mTeleportBtn = getChild<LLButton>("teleport_btn"); mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this)); mShowOnMapBtn = getChild<LLButton>("map_btn"); mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this)); - //mShareBtn = getChild<LLButton>("share_btn"); + mShareBtn = getChild<LLButton>("share_btn"); //mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this)); mOverflowBtn = getChild<LLButton>("overflow_btn"); @@ -155,6 +169,11 @@ void LLPanelPlaces::onOpen(const LLSD& key) } else if (mPlaceInfoType == "remote_place") { + if (mPlaceInfo->isMediaPanelVisible()) + { + toggleMediaPanel(); + } + mPosGlobal = LLVector3d(key["x"].asReal(), key["y"].asReal(), key["z"].asReal()); @@ -323,20 +342,31 @@ void LLPanelPlaces::onShowOnMapButtonClicked() } } +void LLPanelPlaces::onCreateLandmarkButtonClicked(const LLUUID& folder_id) +{ + if (!mPlaceInfo) + return; + + mPlaceInfo->createLandmark(folder_id); + + onBackButtonClicked(); + LLSideTray::getInstance()->collapseSideBar(); +} + void LLPanelPlaces::onBackButtonClicked() { togglePlaceInfoPanel(FALSE); // Resetting mPlaceInfoType when Place Info panel is closed. mPlaceInfoType = LLStringUtil::null; - + updateVerbs(); } void LLPanelPlaces::toggleMediaPanel() { if (!mPlaceInfo) - return; + return; mPlaceInfo->toggleMediaPanel(!mPlaceInfo->isMediaPanelVisible()); } @@ -403,7 +433,7 @@ void LLPanelPlaces::onAgentParcelChange() { if (mPlaceInfo->getVisible() && (mPlaceInfoType == "agent" || mPlaceInfoType == "create_landmark")) { - LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", mPlaceInfoType)); + onOpen(LLSD().insert("type", mPlaceInfoType)); } else { @@ -415,9 +445,20 @@ void LLPanelPlaces::updateVerbs() { bool is_place_info_visible = mPlaceInfo->getVisible(); bool is_agent_place_info_visible = mPlaceInfoType == "agent"; + bool is_create_landmark_visible = mPlaceInfoType == "create_landmark"; + + mTeleportBtn->setVisible(!is_create_landmark_visible); + mShareBtn->setVisible(!is_create_landmark_visible); + mCreateLandmarkBtn->setVisible(is_create_landmark_visible); + mFolderMenuBtn->setVisible(is_create_landmark_visible); + + // Enable overflow button only when showing the information + // about agent's current location. + mOverflowBtn->setEnabled(is_agent_place_info_visible); + if (is_place_info_visible) { - if (is_agent_place_info_visible || mPlaceInfoType == "create_landmark") + if (is_agent_place_info_visible) { // We don't need to teleport to the current location so disable the button mTeleportBtn->setEnabled(FALSE); @@ -433,9 +474,205 @@ void LLPanelPlaces::updateVerbs() { mActivePanel->updateVerbs(); } +} + +void LLPanelPlaces::showLandmarkFoldersMenu() +{ + if (mLandmarkFoldersMenuHandle.isDead()) + { + LLMenuGL::Params menu_p; + menu_p.name("landmarks_folders_menu"); + menu_p.can_tear_off(false); + menu_p.visible(false); + menu_p.scrollable(true); + + LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p); + + mLandmarkFoldersMenuHandle = menu->getHandle(); + } + + LLToggleableMenu* menu = (LLToggleableMenu*)mLandmarkFoldersMenuHandle.get(); + if(!menu) + return; + + if (menu->getClosedByButtonClick()) + { + menu->resetClosedByButtonClick(); + return; + } + + if (menu->getVisible()) + { + menu->setVisible(FALSE); + menu->resetClosedByButtonClick(); + return; + } + + // Collect all folders that can contain landmarks. + LLInventoryModel::cat_array_t cats; + collectLandmarkFolders(cats); + + // Sort the folders by their full name. + folder_vec_t folders; + S32 count = cats.count(); + for (S32 i = 0; i < count; i++) + { + const LLViewerInventoryCategory* cat = cats.get(i); + std::string cat_full_name = getFullFolderName(cat); + folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name)); + } + sort(folders.begin(), folders.end(), cmp_folders); + + LLRect btn_rect = mFolderMenuBtn->getRect(); + + LLRect root_rect = getRootView()->getRect(); + + // Check it there are changed items or viewer dimensions + // have changed since last call + if (mLandmarkFoldersCache.size() == count && + mRootViewWidth == root_rect.getWidth() && + mRootViewHeight == root_rect.getHeight()) + { + S32 i; + for (i = 0; i < count; i++) + { + if (mLandmarkFoldersCache[i].second != folders[i].second) + { + break; + } + } + + // Check passed, just show the menu + if (i == count) + { + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); - // Enable overflow button only when showing the information about agent's current location. - mOverflowBtn->setEnabled(is_place_info_visible && is_agent_place_info_visible); + menu->setButtonRect(btn_rect, this); + LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop); + return; + } + } + + // If there are changes, store the new viewer dimensions + // and a list of folders + mRootViewWidth = root_rect.getWidth(); + mRootViewHeight = root_rect.getHeight(); + mLandmarkFoldersCache = folders; + + menu->empty(); + U32 max_width = 0; + + // Menu width must not exceed the root view limits, + // so we assume the space between the left edge of + // the root view and + LLRect screen_btn_rect; + localRectToScreen(btn_rect, &screen_btn_rect); + S32 free_space = screen_btn_rect.mRight; + + for(folder_vec_t::const_iterator it = mLandmarkFoldersCache.begin(); it != mLandmarkFoldersCache.end(); it++) + { + const std::string& item_name = it->second; + + LLMenuItemCallGL::Params item_params; + item_params.name(item_name); + item_params.label(item_name); + + item_params.on_click.function(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, it->first)); + + LLMenuItemCallGL *menu_item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); + + // Check whether item name wider than menu + if ((S32) menu_item->getNominalWidth() > free_space) + { + S32 chars_total = item_name.length(); + S32 chars_fitted = 1; + menu_item->setLabel(LLStringExplicit("")); + S32 label_space = free_space - menu_item->getFont()->getWidth("...") - + menu_item->getNominalWidth(); // This returns width of menu item with empty label (pad pixels) + + while (chars_fitted < chars_total && menu_item->getFont()->getWidth(item_name, 0, chars_fitted) < label_space) + { + chars_fitted++; + } + chars_fitted--; // Rolling back one char, that doesn't fit + + menu_item->setLabel(item_name.substr(0, chars_fitted) + "..."); + } + + max_width = llmax(max_width, menu_item->getNominalWidth()); + + menu->addChild(menu_item); + } + + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + menu->setButtonRect(btn_rect, this); + LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop); +} + +static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) +{ + return left.second < right.second; +} + +static std::string getFullFolderName(const LLViewerInventoryCategory* cat) +{ + std::string name = cat->getName(); + LLUUID parent_id; + + // translate category name, if it's right below the root + // FIXME: it can throw notification about non existent string in strings.xml + if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID()) + { + name = LLTrans::getString("InvFolder " + name); + } + + // we don't want "My Inventory" to appear in the name + while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID()) + { + cat = gInventory.getCategory(parent_id); + name = cat->getName() + "/" + name; + } + + return name; +} + +static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) +{ + // Add the "Landmarks" category itself. + LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + LLViewerInventoryCategory* landmarks_cat = gInventory.getCategory(landmarks_id); + if (!landmarks_cat) + { + llwarns << "Cannot find the landmarks folder" << llendl; + } + else + { + cats.put(landmarks_cat); + } + + // Add descendent folders of the "Landmarks" category. + LLInventoryModel::item_array_t items; // unused + LLIsType is_category(LLAssetType::AT_CATEGORY); + gInventory.collectDescendentsIf( + landmarks_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_category); + + // Add the "My Favorites" category. + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); + if (!favorites_cat) + { + llwarns << "Cannot find the favorites folder" << llendl; + } + else + { + cats.put(favorites_cat); + } } const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global) @@ -445,4 +682,4 @@ const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global) LLVector3 pos_local(region_x, region_y, (F32)pos_global.mdV[VZ]); return pos_local; -} +} diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index c100ace8cc..695c78cfba 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -47,6 +47,8 @@ class LLPanelPlacesTab; class LLFilterEditor; class LLTabContainer; +typedef std::pair<LLUUID, std::string> folder_pair_t; + class LLPanelPlaces : public LLPanel, LLInventoryObserver { public: @@ -69,6 +71,7 @@ private: //void onShareButtonClicked(); void onTeleportButtonClicked(); void onShowOnMapButtonClicked(); + void onCreateLandmarkButtonClicked(const LLUUID& folder_id); void onBackButtonClicked(); void toggleMediaPanel(); @@ -76,15 +79,19 @@ private: void onAgentParcelChange(); void updateVerbs(); + + void showLandmarkFoldersMenu(); LLFilterEditor* mFilterEditor; LLPanelPlacesTab* mActivePanel; LLTabContainer* mTabContainer; LLPanelPlaceInfo* mPlaceInfo; - //LLButton* mShareBtn; + LLButton* mCreateLandmarkBtn; + LLButton* mFolderMenuBtn; LLButton* mTeleportBtn; LLButton* mShowOnMapBtn; + LLButton* mShareBtn; LLButton* mOverflowBtn; // Pointer to a landmark item or to a linked landmark @@ -100,6 +107,20 @@ private: // Information type currently shown in Place Information panel std::string mPlaceInfoType; + + // Menu handle for pop-up menu to chose a landmark saving + // folder when creating a new landmark + LLHandle<LLView> mLandmarkFoldersMenuHandle; + + typedef std::vector<folder_pair_t> folder_vec_t; + + // List of folders to choose from when creating a landmark + folder_vec_t mLandmarkFoldersCache; + + // If root view width or height is changed + // the pop-up menu must be updated + S32 mRootViewWidth; + S32 mRootViewHeight; }; #endif //LL_LLPANELPLACES_H diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index deca08050b..f97105caa8 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -35,6 +35,8 @@ #include "lltabcontainer.h" #include "llpanelpicks.h" #include "llagent.h" +#include "llcommandhandler.h" +#include "llavataractions.h" static const std::string PANEL_PICKS = "panel_picks"; static const std::string PANEL_NOTES = "panel_notes"; @@ -44,6 +46,33 @@ static LLRegisterPanelClassWrapper<LLPanelAvatarProfile> t_panel_profile(PANEL_P static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks(PANEL_PICKS); +class LLAgentHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLAgentHandler() : LLCommandHandler("agent", true) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLWebBrowserCtrl* web) + { + if (params.size() < 2) return false; + LLUUID agent_id; + if (!agent_id.set(params[0], FALSE)) + { + return false; + } + + if (params[1].asString() == "about") + { + LLAvatarActions::showProfile(agent_id); + return true; + } + return false; + } +}; +LLAgentHandler gAgentHandler; + + LLPanelProfile::LLPanelProfile() : LLPanel(), mTabContainer(NULL) @@ -68,25 +97,6 @@ BOOL LLPanelProfile::postBuild() return TRUE; } -void LLPanelProfile::onOpen(const LLSD& key) -{ - //*NOTE LLUUID::null in this context means Agent related stuff - LLUUID id(key.has("id") ? key["id"].asUUID() : gAgentID); - if (key.has("open_tab_name")) - mTabContainer->selectTabByName(key["open_tab_name"]); - - if(id.notNull() && mAvatarId.notNull() && mAvatarId != id) - { - mTabs[PANEL_PROFILE]->clear(); - mTabs[PANEL_PICKS]->clear(); - mTabs[PANEL_NOTES]->clear(); - } - - mAvatarId = id; - - mTabContainer->getCurrentPanel()->onOpen(mAvatarId); -} - //*TODO redo panel toggling void LLPanelProfile::togglePanel(LLPanel* panel) { diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index e8aea849df..2f6d53a859 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -46,7 +46,7 @@ class LLPanelProfile : public LLPanel public: virtual BOOL postBuild(); - virtual void onOpen(const LLSD& key); + virtual void onOpen(const LLSD& key) {}; virtual void togglePanel(LLPanel*); diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index 7d02c8ff0b..00254ee8ee 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -35,6 +35,7 @@ #include "llpanelavatar.h" #include "llpanelpicks.h" +#include "llsidetraypanelcontainer.h" #include "llpanelprofile.h" static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("panel_profile_view"); @@ -56,15 +57,23 @@ LLPanelProfileView::~LLPanelProfileView(void) /*virtual*/ void LLPanelProfileView::onOpen(const LLSD& key) { - LLPanelProfile::onOpen(key); - - //*NOTE profile view panel doesn't have own side tray tab and - //is usually opened over People side tray tab. By Back button - // Profile View panel just becomes invisible, see onBackBtnClick() - setVisible(TRUE); + LLUUID id = key["id"]; + if (key.has("open_tab_name")) + mTabContainer->selectTabByName(key["open_tab_name"]); + + if(id.notNull() && mAvatarId != id) + { + mAvatarId = id; + + mTabs[PANEL_PROFILE]->clear(); + mTabs[PANEL_PICKS]->clear(); + mTabs[PANEL_NOTES]->clear(); + } + + mTabContainer->getCurrentPanel()->onOpen(mAvatarId); std::string full_name; - gCacheName->getFullName(key["id"],full_name); + gCacheName->getFullName(mAvatarId,full_name); childSetValue("user_name",full_name); } @@ -85,5 +94,9 @@ BOOL LLPanelProfileView::postBuild() void LLPanelProfileView::onBackBtnClick() { - setVisible(FALSE); + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); + if(parent) + { + parent->openPreviousPanel(); + } } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 5dca12e06b..5ae79f6c63 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -59,6 +59,7 @@ LLScreenChannel::LLScreenChannel(): mUnreadToastsPanel(NULL), //TODO: load as a resource string mOverflowFormatString = "You have %d more notification"; + mToastList.clear(); setMouseOpaque( false ); } @@ -266,7 +267,7 @@ void LLScreenChannel::showToastsBottom() { mHiddenToastsNum++; } - createOverflowToast(bottom); + createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastTime")); } } @@ -319,7 +320,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) mUnreadToastsPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true); toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight()); mUnreadToastsPanel->setRect(toast_rect); - mUnreadToastsPanel->setAndStartTimer(timer ? timer : gSavedSettings.getS32("NotificationToastTime")); + mUnreadToastsPanel->setAndStartTimer(timer); getRootView()->addChild(mUnreadToastsPanel); text_box->setValue(text); @@ -337,14 +338,19 @@ void LLScreenChannel::onOverflowToastHide() } //-------------------------------------------------------------------------- -void LLScreenChannel::hideToastsFromScreen() +void LLScreenChannel::closeUnreadToastsPanel() { - if(mUnreadToastsPanel) + if(mUnreadToastsPanel != NULL) { mUnreadToastsPanel->close(); - delete mUnreadToastsPanel; mUnreadToastsPanel = NULL; } +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::hideToastsFromScreen() +{ + closeUnreadToastsPanel(); for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) (*it).toast->setVisible(FALSE); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index f05c205e2a..a205b913ab 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -73,6 +73,7 @@ public: void setHovering(bool hovering) { mIsHovering = hovering; } void removeToastsFromChannel(); + void closeUnreadToastsPanel(); void hideToastsFromScreen(); void setStoreToasts(bool store) { mStoreToasts = store; } @@ -125,7 +126,7 @@ private: void showToastsCentre(); void showToastsTop(); - void createOverflowToast(S32 bottom, F32 timer = 0); + void createOverflowToast(S32 bottom, F32 timer); void onOverflowToastHide(); static bool mWasStartUpToastShown; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 2688399139..5f0fbe6ee5 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -44,6 +44,7 @@ #include "llfloater.h" //for gFloaterView #include "lliconctrl.h"//for Home tab icon +#include "llsidetraypanelcontainer.h" #include "llwindow.h"//for SetCursor //#include "llscrollcontainer.h" @@ -609,9 +610,22 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para if(view) { onTabButtonClick((*child_it)->getName()); + + LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent()); + if(container) + { + LLSD new_params = params; + new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; + container->onOpen(new_params); + + return container->getCurrentPanel(); + } + LLPanel* panel = dynamic_cast<LLPanel*>(view); if(panel) + { panel->onOpen(params); + } return panel; } } diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 99e84f8141..1f8b6b402f 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -163,6 +163,7 @@ public: /** * Activate tab with "panel_name" panel * if no such tab - return NULL, otherwise a pointer to the panel + * Pass params as array, or they may be overwritten(example - params["name"]="nearby") */ LLPanel* showPanel (const std::string& panel_name, const LLSD& params); diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp new file mode 100644 index 0000000000..21061a802a --- /dev/null +++ b/indra/newview/llsidetraypanelcontainer.cpp @@ -0,0 +1,89 @@ +/** +* @file llsidetraypanelcontainer.cpp +* @brief LLSideTrayPanelContainer implementation +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +* +* Copyright (c) 2001-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 "llsidetraypanelcontainer.h" + +static LLDefaultChildRegistry::Register<LLSideTrayPanelContainer> r2("panel_container"); + +std::string LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME = "sub_panel_name"; + +LLSideTrayPanelContainer::Params::Params() +{ + // Always hide tabs. + hide_tabs(true); +} + +LLSideTrayPanelContainer::LLSideTrayPanelContainer(const Params& p) + : LLTabContainer(p) +{ +} + +void LLSideTrayPanelContainer::onOpen(const LLSD& key) +{ + // Select specified panel and save navigation history. + if(key.has(PARAM_SUB_PANEL_NAME)) + { + // Save panel navigation history + std::string panel_name = key[PARAM_SUB_PANEL_NAME]; + S32 old_index = getCurrentPanelIndex(); + + selectTabByName(panel_name); + + S32 new_index = getCurrentPanelIndex(); + + // Don't update navigation history if we are opening same panel again. + if(old_index != new_index) + { + mPanelHistory[panel_name] = old_index; + } + } + // Will reopen current panel if no panel name was passed. + getCurrentPanel()->onOpen(key); +} + +void LLSideTrayPanelContainer::openPreviousPanel() +{ + std::string current_panel_name = getCurrentPanel()->getName(); + panel_navigation_history_t::const_iterator it = mPanelHistory.find(current_panel_name); + if(mPanelHistory.end() != it) + { + selectTab(it->second); + } +} + +BOOL LLSideTrayPanelContainer::handleKeyHere(KEY key, MASK mask) +{ + // No key press handling code for Panel Container - this disables + // Tab Container's Alt + Left/Right Button tab switching. + return TRUE; +} diff --git a/indra/newview/llsidetraypanelcontainer.h b/indra/newview/llsidetraypanelcontainer.h new file mode 100644 index 0000000000..3f3cb552f8 --- /dev/null +++ b/indra/newview/llsidetraypanelcontainer.h @@ -0,0 +1,95 @@ +/** +* @file llsidetraypanelcontainer.h +* @brief LLSideTrayPanelContainer class declaration +* +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 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_LLSIDETRAY_PANEL_CONTAINER_H +#define LL_LLSIDETRAY_PANEL_CONTAINER_H + +#include "lltabcontainer.h" + +/** +* LLSideTrayPanelContainer class acts like LLTabContainer with invisible tabs. +* It is designed to make panel switching easier, avoid setVisible(TRUE) setVisible(FALSE) +* calls and related workarounds. +* use onOpen to open sub panel, pass the name of panel to open +* in key[PARAM_SUB_PANEL_NAME]. +* LLSideTrayPanelContainer also implements panel navigation history - it allows to +* open previous or next panel if navigation history is available(after user +* has opened two or more panels). *NOTE - only back navigation is implemented so far. +*/ +class LLSideTrayPanelContainer : public LLTabContainer +{ +public: + + struct Params : public LLInitParam::Block<Params, LLTabContainer::Params> + { + Params(); + }; + + /** + * Opens sub panel + * @param key - params to be passed to panel, use key[PARAM_SUB_PANEL_NAME] + * to specify panel name to be opened. + */ + /*virtual*/ void onOpen(const LLSD& key); + + /** + * Opens previous panel from panel navigation history. + */ + void openPreviousPanel(); + + /** + * Overrides LLTabContainer::handleKeyHere to disable panel switch on + * Alt + Left/Right button press. + */ + BOOL handleKeyHere(KEY key, MASK mask); + + /** + * Name of parameter that stores panel name to open. + */ + static std::string PARAM_SUB_PANEL_NAME; + +protected: + LLSideTrayPanelContainer(const Params& p); + friend class LLUICtrlFactory; + + /** + * std::string - name of panel + * S32 - index of previous panel + * *NOTE - no forward navigation implemented yet + */ + typedef std::map<std::string, S32> panel_navigation_history_t; + + // Navigation history + panel_navigation_history_t mPanelHistory; +}; + +#endif //LL_LLSIDETRAY_PANEL_CONTAINER_H diff --git a/indra/newview/llsplitbutton.cpp b/indra/newview/llsplitbutton.cpp new file mode 100644 index 0000000000..ffd9bc7624 --- /dev/null +++ b/indra/newview/llsplitbutton.cpp @@ -0,0 +1,275 @@ +/** + * @file llsplitbutton.cpp + * @brief LLSplitButton base class + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 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$ + */ + +// A control that consolidates several buttons as options + +#include "llviewerprecompiledheaders.h" + +#include "llsplitbutton.h" + +#include "llinitparam.h" +#include "llpanel.h" +#include "llfocusmgr.h" +#include "llviewerwindow.h" +#include "llrootview.h" + + +S32 BUTTON_PAD = 2; //pad between buttons on an items panel + + +static LLDefaultChildRegistry::Register<LLSplitButton> split_button("split_button"); + +void LLSplitButton::ArrowPositionValues::declareValues() +{ + declare("left", LEFT); + declare("right", RIGHT); +} + +LLSplitButton::ItemParams::ItemParams() +{ +} + +LLSplitButton::Params::Params() +: arrow_position("arrow_position", LEFT), + items("item"), + arrow_button("arrow_button"), + items_panel("items_panel") +{ +} + + +void LLSplitButton::onFocusLost() +{ + hideButtons(); + LLUICtrl::onFocusLost(); +} + +void LLSplitButton::setFocus(BOOL b) +{ + LLUICtrl::setFocus(b); + + if (b) + { + if (mItemsPanel && mItemsPanel->getVisible()) + { + mItemsPanel->setFocus(TRUE); + } + } +} + +void LLSplitButton::setEnabled(BOOL enabled) +{ + LLView::setEnabled(enabled); + mArrowBtn->setEnabled(enabled); +} + + +void LLSplitButton::onArrowBtnDown() +{ + if (!mItemsPanel->getVisible()) + { + showButtons(); + + setFocus(TRUE); + + if (mArrowBtn->hasMouseCapture() || mShownItem->hasMouseCapture()) + { + gFocusMgr.setMouseCapture(this); + } + } + else + { + hideButtons(); + } +} + +void LLSplitButton::onHeldDownShownButton() +{ + if (!mItemsPanel->getVisible()) onArrowBtnDown(); +} + +void LLSplitButton::onItemSelected(LLUICtrl* ctrl) +{ + if (!ctrl) return; + + hideButtons(); + + // call the callback if it exists + if(!mSelectionCallback.empty()) + { + mSelectionCallback(this, ctrl->getName()); + } + + gFocusMgr.setKeyboardFocus(NULL); +} + +BOOL LLSplitButton::handleMouseUp(S32 x, S32 y, MASK mask) +{ + gFocusMgr.setMouseCapture(NULL); + + if (mShownItem->parentPointInView(x, y)) + { + onItemSelected(mShownItem); + return TRUE; + } + + for (std::list<LLButton*>::const_iterator it = mHidenItems.begin(); it != mHidenItems.end(); ++it) + { + LLButton* item = *it; + + S32 panel_x = 0; + S32 panel_y = 0; + localPointToOtherView(x, y, &panel_x, &panel_y, mItemsPanel); + + if (item->parentPointInView(panel_x, panel_y)) + { + onItemSelected(item); + return TRUE; + } + } + return TRUE; +} + +void LLSplitButton::showButtons() +{ + mItemsPanel->setOrigin(0, getRect().getHeight()); + + // register ourselves as a "top" control + // effectively putting us into a special draw layer + gFocusMgr.setTopCtrl(this); + + mItemsPanel->setFocus(TRUE); + + //push arrow button down and show the item buttons + mArrowBtn->setToggleState(TRUE); + mItemsPanel->setVisible(TRUE); + + setUseBoundingRect(TRUE); +} + +void LLSplitButton::hideButtons() +{ + mItemsPanel->setVisible(FALSE); + mArrowBtn->setToggleState(FALSE); + + setUseBoundingRect(FALSE); + if(gFocusMgr.getTopCtrl() == this) + { + gFocusMgr.setTopCtrl(NULL); + } +} + + +// protected/private + +LLSplitButton::LLSplitButton(const LLSplitButton::Params& p) +: LLUICtrl(p), + mArrowBtn(NULL), + mShownItem(NULL), + mItemsPanel(NULL), + mArrowPosition(p.arrow_position) +{ + LLRect rc(p.rect); + + LLButton::Params arrow_params = p.arrow_button; + S32 arrow_width = p.arrow_button.rect.width; + + //Default arrow rect values for LEFT arrow position + S32 arrow_left = 0; + S32 arrow_right = arrow_width; + S32 btn_left = arrow_width; + S32 btn_right = rc.getWidth(); + + if (mArrowPosition == RIGHT) + { + arrow_left = rc.getWidth()- arrow_width; + arrow_right = rc.getWidth(); + btn_left = 0; + btn_right = arrow_left; + } + + arrow_params.rect(LLRect(arrow_left, rc.getHeight(), arrow_right, 0)); + arrow_params.label(""); + arrow_params.mouse_down_callback.function(boost::bind(&LLSplitButton::onArrowBtnDown, this)); + mArrowBtn = LLUICtrlFactory::create<LLButton>(arrow_params); + addChild(mArrowBtn); + + //a panel for hidden item buttons + LLPanel::Params panel_params = p.items_panel; + mItemsPanel= prepareItemsPanel(panel_params, p.items.numValidElements()); + addChild(mItemsPanel); + + + LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin(); + + //processing shown item button + mShownItem = prepareItemButton(*it); + mShownItem->setHeldDownCallback(boost::bind(&LLSplitButton::onHeldDownShownButton, this)); + mShownItem->setMouseUpCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1)); + mShownItem->setRect(LLRect(btn_left, rc.getHeight(), btn_right, 0)); + addChild(mShownItem); + + //processing hidden item buttons + S32 item_top = mItemsPanel->getRect().getHeight(); + for (++it; it != p.items().end(); ++it) + { + LLButton* hidden_button = prepareItemButton(*it); + hidden_button->setRect(LLRect(btn_left, item_top, btn_right, item_top - rc.getHeight())); + hidden_button->setMouseDownCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1)); + mHidenItems.push_back(hidden_button); + mItemsPanel->addChild(hidden_button); + + //calculate next button's top + item_top -= (rc.getHeight() + BUTTON_PAD); + } + + setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this)); +} + + +LLButton* LLSplitButton::prepareItemButton(LLButton::Params params) +{ + params.label(""); + params.is_toggle(false); + return LLUICtrlFactory::create<LLButton>(params); +} + +LLPanel* LLSplitButton::prepareItemsPanel(LLPanel::Params params, S32 items_count) +{ + S32 num_hiden_btns = items_count - 1; + S32 panel_height = num_hiden_btns * (getRect().getHeight() + BUTTON_PAD); + params.visible(false); + params.rect.width(getRect().getWidth()); + params.rect.height(panel_height); + return LLUICtrlFactory::create<LLPanel>(params); +} + diff --git a/indra/newview/llsplitbutton.h b/indra/newview/llsplitbutton.h new file mode 100644 index 0000000000..0fb5f6594e --- /dev/null +++ b/indra/newview/llsplitbutton.h @@ -0,0 +1,112 @@ +/** + * @file llsplitbutton.h + * @brief LLSplitButton base class + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 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$ + */ + +// A control that displays the name of the chosen item, which when clicked +// shows a scrolling box of choices. + + +#include "llbutton.h" +#include "llpanel.h" +#include "lluictrl.h" + + +#ifndef LL_LLSPLITBUTTON_H +#define LL_LLSPLITBUTTON_H + +class LLSplitButton + : public LLUICtrl +{ +public: + typedef enum e_arrow_position + { + LEFT, + RIGHT + } EArrowPosition; + + struct ArrowPositionValues : public LLInitParam::TypeValuesHelper<EArrowPosition, ArrowPositionValues> + { + static void declareValues(); + }; + + struct ItemParams : public LLInitParam::Block<ItemParams, LLButton::Params> + { + ItemParams(); + }; + + struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> + { + Optional<EArrowPosition, ArrowPositionValues> arrow_position; + Optional<LLButton::Params> arrow_button; + Optional<LLPanel::Params> items_panel; + Multiple<ItemParams> items; + + Params(); + }; + + + virtual ~LLSplitButton() {}; + + //Overridden + virtual void onFocusLost(); + virtual void setFocus(BOOL b); + virtual void setEnabled(BOOL enabled); + + //Callbacks + void onArrowBtnDown(); + void onHeldDownShownButton(); + void onItemSelected(LLUICtrl* ctrl); + void setSelectionCallback(commit_callback_t cb) { mSelectionCallback = cb; } + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + + virtual void showButtons(); + virtual void hideButtons(); + + +protected: + friend class LLUICtrlFactory; + LLSplitButton(const LLSplitButton::Params& p); + + LLButton* prepareItemButton(LLButton::Params params); + LLPanel* prepareItemsPanel(LLPanel::Params params, S32 items_count); + + LLPanel* mItemsPanel; + std::list<LLButton*> mHidenItems; + LLButton* mArrowBtn; + LLButton* mShownItem; + EArrowPosition mArrowPosition; + + commit_callback_t mSelectionCallback; +}; + + +#endif diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 6f5b25214e..0d4c75b507 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -36,6 +36,7 @@ #include "llbutton.h" #include "llfocusmgr.h" +#include "llviewercontrol.h" using namespace LLNotificationsUI; @@ -48,7 +49,8 @@ LLToast::LLToast(LLPanel* panel) : mCanFade(true), mHideBtn(NULL), mIsModal(false), - mCanBeStored(true) + mCanBeStored(true), + mHideBtnPressed(false) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_toast.xml"); @@ -104,8 +106,7 @@ bool LLToast::timerHasExpired() if (mTimer.getStarted()) { F32 elapsed_time = mTimer.getElapsedTimeF32(); - // after 4 seconds a toast should start fade - if (elapsed_time > 4) + if (elapsed_time > gSavedSettings.getS32("ToastOpaqueTime")) { setBackgroundOpaque(FALSE); } @@ -218,6 +219,7 @@ void LLToast::onMouseEnter(S32 x, S32 y, MASK mask) //-------------------------------------------------------------------------- void LLToast::onMouseLeave(S32 x, S32 y, MASK mask) { + llinfos << "MOUSE LEAVE: x = " << x << "y = " << y << llendl; mOnToastHover(this, MOUSE_LEAVE); if(mCanFade && !mIsViewed) @@ -226,14 +228,26 @@ void LLToast::onMouseLeave(S32 x, S32 y, MASK mask) } if(mHideBtn && mHideBtn->getEnabled()) { - if( mHideBtn->getRect().pointInRect(x, y) ) + if( mHideBtnPressed ) + { + mHideBtnPressed = false; return; - mHideBtn->setVisible(FALSE); + } + mHideBtn->setVisible(FALSE); } } //-------------------------------------------------------------------------- +BOOL LLToast::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if(mHideBtn && mHideBtn->getEnabled()) + { + mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y); + } + + return LLFloater::handleMouseDown(x, y, mask); +} diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 018664f3d1..f998754585 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -55,6 +55,7 @@ public: LLToast(LLPanel* panel); virtual ~LLToast(); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); // bool isViewed() { return mIsViewed; } @@ -109,6 +110,7 @@ private: bool mCanFade; bool mIsModal; bool mCanBeStored; + bool mHideBtnPressed; }; } diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index 477e452907..5478e0005a 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -253,7 +253,7 @@ void LLToolBar::refresh() BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } if (!gAgent.canFly()) diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index ee6e36518f..297cf2c667 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -56,6 +56,8 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llmorphview.h" +#include "llfloaterreg.h" +#include "llfloatercamera.h" // Globals BOOL gCameraBtnZoom = TRUE; @@ -254,7 +256,11 @@ void LLToolCamera::releaseMouse() gViewerWindow->showCursor(); - LLToolMgr::getInstance()->clearTransientTool(); + //for the situation when left click was performed on the Agent + if (!LLFloaterCamera::inFreeCameraMode()) + { + LLToolMgr::getInstance()->clearTransientTool(); + } mMouseSteering = FALSE; mValidClickPoint = FALSE; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 350657538b..fab336f17d 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -42,7 +42,6 @@ #include "llagent.h" #include "llviewercontrol.h" #include "llfirstuse.h" -#include "llfloateravatarinfo.h" #include "llfloaterland.h" #include "llfloaterreg.h" #include "llfloaterscriptdebug.h" @@ -190,7 +189,7 @@ BOOL LLToolPie::pickLeftMouseDownCallback() // touch behavior down below... break; case CLICK_ACTION_SIT: - if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // agent not already sitting + if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // agent not already sitting { handle_sit_or_stand(); return TRUE; @@ -362,7 +361,7 @@ ECursorType cursor_from_object(LLViewerObject* object) switch(click_action) { case CLICK_ACTION_SIT: - if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // not already sitting? + if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // not already sitting? { cursor = UI_CURSOR_TOOLSIT; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5c38be86d5..034bb9b88d 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -42,7 +42,6 @@ #include "llfloateractivespeakers.h" #include "llfloaterauction.h" #include "llfloateraddlandmark.h" -#include "llfloateravatarinfo.h" #include "llfloaterbeacons.h" #include "llfloaterbulkpermission.h" #include "llfloaterbuildoptions.h" @@ -51,6 +50,7 @@ #include "llfloaterchat.h" #include "llfloaterchatterbox.h" #include "llfloaterdirectory.h" +#include "llfloaterfirsttimetip.h" #include "llfloaterfonttest.h" #include "llfloatergodtools.h" #include "llfloaterhtmlcurrency.h" @@ -114,6 +114,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("contacts", "floater_my_friends.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyFriends>); + LLFloaterReg::add("first_time_tip", "floater_first_time_tip.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFirstTimeTip>); LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>); LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>); @@ -127,7 +128,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>); LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); - LLFloaterReg::add("me_profile", "floater_me.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarInfo>); LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaBrowser>); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>); LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMute>); @@ -144,7 +144,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preview_url", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterURLDisplay>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); LLFloaterReg::add("pref_voicedevicesettings", "floater_device_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceDeviceSettings>); - LLFloaterReg::add("preview_avatar", "floater_profile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarInfo>); LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview"); LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview"); LLFloaterReg::add("preview_landmark", "floater_preview_existing_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLandmark>, "preview"); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 66da7d89fb..75d9321313 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -201,10 +201,19 @@ void LLViewerInventoryItem::fetchFromServer(void) const { std::string url; - if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString()) - url = gAgent.getRegion()->getCapability("FetchLib"); - else - url = gAgent.getRegion()->getCapability("FetchInventory"); + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString()) + url = region->getCapability("FetchLib"); + else + url = region->getCapability("FetchInventory"); + } + else + { + llwarns << "Agent Region is absent" << llendl; + } if (!url.empty()) { diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 4e0c4023fd..6bb302727d 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -44,6 +44,7 @@ #include "lltoolfocus.h" #include "llviewerwindow.h" #include "llvoavatarself.h" +#include "llfloatercamera.h" // // Constants @@ -135,14 +136,29 @@ static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDo } } +void camera_move_forward( EKeystate s ); + void agent_push_forward( EKeystate s ) { + //in free camera control mode we need to intercept keyboard events for avatar movements + if (LLFloaterCamera::inFreeCameraMode()) + { + camera_move_forward(s); + return; + } agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD); } +void camera_move_backward( EKeystate s ); void agent_push_backward( EKeystate s ) { + //in free camera control mode we need to intercept keyboard events for avatar movements + if (LLFloaterCamera::inFreeCameraMode()) + { + camera_move_backward(s); + return; + } agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD); } @@ -175,8 +191,17 @@ void agent_slide_right( EKeystate s ) agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT); } +void camera_spin_around_cw( EKeystate s ); + void agent_turn_left( EKeystate s ) { + //in free camera control mode we need to intercept keyboard events for avatar movements + if (LLFloaterCamera::inFreeCameraMode()) + { + camera_spin_around_cw(s); + return; + } + if (LLToolCamera::getInstance()->mouseSteerMode()) { agent_slide_left(s); @@ -189,9 +214,17 @@ void agent_turn_left( EKeystate s ) } } +void camera_spin_around_ccw( EKeystate s ); void agent_turn_right( EKeystate s ) { + //in free camera control mode we need to intercept keyboard events for avatar movements + if (LLFloaterCamera::inFreeCameraMode()) + { + camera_spin_around_ccw(s); + return; + } + if (LLToolCamera::getInstance()->mouseSteerMode()) { agent_slide_right(s); @@ -842,7 +875,7 @@ EKeyboardMode LLViewerKeyboard::getMode() { return MODE_EDIT_AVATAR; } - else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting) + else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()) { return MODE_SITTING; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7071b65228..d4cbe580a9 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -81,6 +81,7 @@ #include "lldrawpooltree.h" #include "llface.h" #include "llfirstuse.h" +#include "llfirsttimetipmanager.h" #include "llfloater.h" #include "llfloaterabout.h" #include "llfloaterbuycurrency.h" @@ -3439,7 +3440,7 @@ class LLSelfStandUp : public view_listener_t { bool handleEvent(const LLSD& userdata) { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + gAgent.standUp(); return true; } }; @@ -3448,7 +3449,7 @@ class LLSelfEnableStandUp : public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting; + bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting(); return new_value; } }; @@ -3676,7 +3677,7 @@ bool handle_sit_or_stand() if (sitting_on_selection()) { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + gAgent.standUp(); return true; } @@ -3722,7 +3723,7 @@ class LLLandSit : public view_listener_t { bool handleEvent(const LLSD& userdata) { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + gAgent.standUp(); LLViewerParcelMgr::getInstance()->deselectLand(); LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; @@ -4630,7 +4631,7 @@ BOOL sitting_on_selection() return FALSE; } - return (avatar->mIsSitting && avatar->getRoot() == root_object); + return (avatar->isSitting() && avatar->getRoot() == root_object); } class LLToolsSaveToInventory : public view_listener_t @@ -5225,6 +5226,9 @@ class LLWorldAlwaysRun : public view_listener_t // tell the simulator. gAgent.sendWalkRun(gAgent.getAlwaysRun()); + // Update Movement Controls according to AlwaysRun mode + LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun()); + return true; } }; @@ -5275,7 +5279,10 @@ class LLWorldCreateLandmark : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLFloaterReg::showInstance("add_landmark"); + LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); + + // Floater "Add Landmark" functionality moved to Side Tray + //LLFloaterReg::showInstance("add_landmark"); return true; } }; @@ -7623,7 +7630,23 @@ class LLWorldDayCycle : public view_listener_t } }; +/// Show First Time Tips calbacks +class LLHelpCheckShowFirstTimeTip : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return LLFirstTimeTipsManager::tipsEnabled(); + } +}; +class LLHelpShowFirstTimeTip : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFirstTimeTipsManager::enabledTip(!userdata.asBoolean()); + return true; + } +}; void initialize_menus() { @@ -7728,6 +7751,9 @@ void initialize_menus() view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess"); view_listener_t::addMenu(new LLWorldDayCycle(), "World.DayCycle"); + view_listener_t::addMenu(new LLHelpCheckShowFirstTimeTip(), "Help.CheckShowFirstTimeTip"); + view_listener_t::addMenu(new LLHelpShowFirstTimeTip(), "Help.ShowQuickTips"); + // Tools menu view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 25c00bb816..129cd5aab9 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -96,6 +96,7 @@ #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llmenugl.h" +#include "llmoveview.h" #include "llmutelist.h" #include "llnotifications.h" #include "llnotify.h" @@ -1184,9 +1185,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { opener = open_agent_offer; } - - // add buddy to recent people list - LLRecentPeople::instance().add(mFromID); } break; case IM_TASK_INVENTORY_OFFERED: @@ -1259,6 +1257,12 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& break; } + if(IM_INVENTORY_OFFERED == mIM) + { + // add buddy to recent people list + LLRecentPeople::instance().add(mFromID); + } + if(opener) { gInventory.addObserver(opener); @@ -3850,7 +3854,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) if (object) { LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); - if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot())) + if (!use_autopilot || (avatar && avatar->isSitting() && avatar->getRoot() == object->getRoot())) { //we're already sitting on this object, so don't autopilot } diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 0fadba1364..afee30293a 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -44,7 +44,6 @@ #include "llviewertexteditor.h" #include "llfloaterchat.h" -#include "llfloateravatarinfo.h" #include "llfloaterworldmap.h" #include "llnotify.h" #include "llpanelplaces.h" @@ -64,6 +63,7 @@ #include "llnotecard.h" #include "llmemorystream.h" #include "llmenugl.h" +#include "llavataractions.h" #include "llappviewer.h" // for gPacificDaylightTime @@ -1394,9 +1394,7 @@ void LLViewerTextEditor::openEmbeddedCallingcard( LLInventoryItem* item, llwchar { if(item && !item->getCreatorUUID().isNull()) { - BOOL online; - online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); - LLFloaterAvatarInfo::showFromFriend(item->getCreatorUUID(), online); + LLAvatarActions::showProfile(item->getCreatorUUID()); } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f312cc0f63..e44112fb8f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4254,30 +4254,19 @@ void LLViewerWindow::destroyWindow() void LLViewerWindow::drawMouselookInstructions() { - // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.) + // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.) const std::string instructions = LLTrans::getString("LeaveMouselook"); - const LLFontGL* font = LLFontGL::getFontSansSerif(); - - const S32 INSTRUCTIONS_PAD = 5; - LLRect instructions_rect; - instructions_rect.setLeftTopAndSize( - mWorldViewRect.mLeft + INSTRUCTIONS_PAD, - mWorldViewRect.mTop - INSTRUCTIONS_PAD, - font->getWidth( instructions ) + 2 * INSTRUCTIONS_PAD, - llround(font->getLineHeight() + 2 * INSTRUCTIONS_PAD)); - - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.9f, 0.9f, 0.9f, 1.0f ); - gl_rect_2d( instructions_rect ); - } + const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Huge", LLFontGL::BOLD)); + //to be on top of Bottom bar when it is opened + const S32 INSTRUCTIONS_PAD = 50; + font->renderUTF8( instructions, 0, - instructions_rect.mLeft + INSTRUCTIONS_PAD, - instructions_rect.mTop - INSTRUCTIONS_PAD, - LLColor4( 0.0f, 0.0f, 0.0f, 1.f ), - LLFontGL::LEFT, LLFontGL::TOP); + mWorldViewRect.getCenterX(), + mWorldViewRect.mBottom + INSTRUCTIONS_PAD, + LLColor4( 0.0f, 0.0f, 0.0f, 0.6f ), + LLFontGL::HCENTER, LLFontGL::TOP); } @@ -4396,11 +4385,6 @@ BOOL LLViewerWindow::getShowProgress() const return (mProgressView && mProgressView->getVisible()); } -void LLViewerWindow::handleLoginComplete() -{ - LLNavigationBar::getInstance()->handleLoginComplete(); -} - void LLViewerWindow::moveProgressViewToFront() { if( mProgressView && mRootView ) diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 35173c8922..62769fe343 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -267,7 +267,6 @@ public: void setProgressMessage(const std::string& msg); void setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null ); LLProgressView *getProgressView() const; - void handleLoginComplete(); void updateObjectUnderCursor(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 714145ce14..6658227aaf 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -57,6 +57,7 @@ #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" #include "llmutelist.h" +#include "llmoveview.h" #include "llnotify.h" #include "llquantize.h" #include "llregionhandle.h" @@ -4244,7 +4245,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL } else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) { - mIsSitting = TRUE; + sitDown(TRUE); } @@ -4261,7 +4262,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) { - mIsSitting = FALSE; + sitDown(FALSE); } stopMotion(anim_id); result = TRUE; @@ -5483,6 +5484,19 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) return FALSE; } +//----------------------------------------------------------------------------- +// sitDown() +//----------------------------------------------------------------------------- +void LLVOAvatar::sitDown(BOOL bSitting) +{ + mIsSitting = bSitting; + if (isSelf()) + { + // Update Movement Controls according to own Sitting mode + LLFloaterMove::setSittingMode(bSitting); + } +} + //----------------------------------------------------------------------------- // sitOnObject() //----------------------------------------------------------------------------- @@ -5502,7 +5516,7 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot); gPipeline.markMoved(mDrawable, TRUE); - mIsSitting = TRUE; + sitDown(TRUE); mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject mRoot.setPosition(getPosition()); mRoot.updateWorldMatrixChildren(); @@ -5566,7 +5580,8 @@ void LLVOAvatar::getOffObject() gPipeline.markMoved(mDrawable, TRUE); - mIsSitting = FALSE; + sitDown(FALSE); + mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject mRoot.setPosition(cur_position_world); mRoot.setRotation(cur_rotation_world); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f36d64aa8e..59be38a1b0 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -784,8 +784,13 @@ public: // Sitting //-------------------------------------------------------------------- public: + void sitDown(BOOL bSitting); + BOOL isSitting(){return mIsSitting;} void sitOnObject(LLViewerObject *sit_object); void getOffObject(); + +private: + // set this property only with LLVOAvatar::sitDown method BOOL mIsSitting; /** Hierarchy diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 4a6bb6facb..9df25bdb11 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1006,6 +1006,15 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr ETextureIndex index = data->mIndex; if (!isIndexLocalTexture(index)) return; LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); + + // fix for EXT-268. Preventing using of NULL pointer + if(NULL == local_tex_obj) + { + LL_WARNS("TAG") << "There is no Local Texture Object with index: " << index + << ", final: " << final + << LL_ENDL; + return; + } if (success) { if (!local_tex_obj->getBakedReady() && diff --git a/indra/newview/macview_Prefix.h b/indra/newview/macview_Prefix.h index a273320b3d..0fcdf2da4f 100644 --- a/indra/newview/macview_Prefix.h +++ b/indra/newview/macview_Prefix.h @@ -63,7 +63,6 @@ #include "lldrawable.h" #include "llfirstuse.h" #include "llfloater.h" -#include "llfloateravatarinfo.h" #include "llfloaterbuildoptions.h" #include "llfloaterchat.h" #include "llfloatercustomize.h" diff --git a/indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png b/indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..be7c87efb67aebee345f1caef05aa305b6fc0784 GIT binary patch literal 1447 zcmZvc2~d+q6vy*%7!D7rRk0<2`Uy&55K->CTrqMKP!pJdBatH%uzUo92E!B?#Q_q& z2r(Maq7Vs3K#rEXRRkh(6vRlP3Duw+1!^FGB1uE7)fxMH^Y*{*&3m)Evpbs|=<l;Z z=PMlq0<i(@>lvid9+ltFTBjP(%H8EE0iYls4@7mp!K5l!cM{{{iBPWDjW!NLmC-)! zi-Qmd-7RYlAg;3YRY_zr+RqC)iZs;L&|nVlj71<cP0^n2A!OmqGrt^sq(1U5YN>-4 z*L@fM$VD19o13MX%}Z$3JD*jW+Zpr(TVl2|Hr)m*%05_t4cS{uui<*eU?^MjOY+Me z)F0+~UB6~1*a6MfTSu48uk5j1DppyM<14n(e&FmJ1yt?eQw9@8H!H-*l#WOZpf=b4 zH(VZ|_Ze>gu{U$s3If)^Z5I2=NbpV4$^kwDeeBVEONDu;WC99nm@$lGyJN}^>EE0) z<`ZC4!$x*cmFsNliG@XqvyyDlF*s3IDzwS9>Q5e^4W~+C+1*!kwR@hJOdYoJl?6B8 z@x2n8$D*+K=`MZFG}u-(S0h;jk1w?5Vow6BBQh+U%6<5z?X6K_WgSOYU8SBJIGyL% zpA4|dRh2m1G4SqYot|9u#=bxW$nOe0caWbcC-<6n#p?Pp+o9KsH5pnxIWAmMs!5YG zzX07IXK&0aAIGD`)!nuaPqG`;+b|KpPs}3Mqtn&JQP0H-X$>fhEK;%RBWTVWK4wOm z{KgpiRn%(jh+Rq*NXdQ$f$`zImGMJ3Lsffua|frE+Lg9pKQFqQ6Gl{I4zp_oHbTKb z68q=S$J0ZCt>?p26rM1X2vh9%jcf{&8=qqd8{Dqw`MyhazNjh)<aeW1bhJ|1;|Uwp zKBDy*=4rjm<)yh)4+P@GIg4O{<)!$<Ym2E)x;?v|csIrdh<Ze=#-EY#FEwL*_mw_h zzQ1pJJG+Pg!K-M+VOi!gn;C<#A&|G{jRoHl-DrYiNnxVvWvKw<g{%x}qKh#yJnYJ# zT$g4M6CF(XWuOGKFC;|3(V^i31o$}P9a|a$2f$C`Y>S@aIKx|V)yIyo))&u4G@%lh z>J}nmSk|ffbV!abkk%ExLXNa^e<(Ray(+)DGXC5lyTO?noeTZG%Wig?pIdvC)!YDU z{=)1_GvffT$((-)q=krHJ519Wsjf+CZx8ZGBm@t0r^PA?b_(frH5sK7O3dil`58`O zG^5+6t9+A=H>3}e`{FdD3(FN<PG_|vPPMGNHF?+DO(;}WkN+|9qAXvY5UXK|P8pG* ztSPH)N+`>|^<rL&*J}?>OU@>v0F%-0NV9hGM9Co;MT3CrUfeAwpX#MV(h1x`DsOx~ zYWZz2>cM`1#mV^d>pI0ub3aRuUOf|xQctQcG>y_v)c*zAo;H3bCOk&uZ`c?gkmPl< z4YMk0@D4Wvb`)Z5X_Zi1WJxg?F(Q+rFqMv)x0D$<?S9Wn6*Cpy;kSWNyL(`IaMe<h z1@(%Qd*+^025zF|EQL6WBjyXBDdL@-{IhBYI)EJ`A3AU&TK6X61K|0%HVngn{qok3 zK_W?Rjl^XDlR?VGqq{91Wq_tGOmgkZsP3tAaf+3+`$Eu>@h*RhkwZd71%HCPUE2A| zJYu{PNxQ&ky(V=5CT)%JQ<8R~v}wJT+R(oD0Ri}eE><7<XWeajz@)P=ep=!}RHgMC zgWdWoU-Zvqet2>p6``hv>Kl=;WOd&*?)&sh`v18bRRPRB?!26JK%BZ(f%fwEtoAtZ F<KM|AmKy*7 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_free_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_free_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3f3703b2211c195467a135bb5f5e3e52d1d6cc GIT binary patch literal 2267 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 J-tlt!zX9WTCOQBB literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..dd72cc01625528f35c37d31cb36864ac175b036f GIT binary patch literal 2381 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 ajL;w(w;-)ufGGZ)YJc3>rux{W_<sZK9EJt} literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..b537dcbe46c70748ba396b36d6064e9b8fc4509d GIT binary patch literal 2418 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 NMOZpml$(3T{~Km@k~07R literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png new file mode 100644 index 0000000000000000000000000000000000000000..7674a75ac3fe972ac2636c9167df1ef596db80d8 GIT binary patch literal 2365 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 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9b923a5aef5323e201403cff15dbc5ea90ca00 GIT binary patch literal 2595 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 YQ0E}+J5gC^>gHgSz1vBu-G%gj0S40laR2}S literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png new file mode 100644 index 0000000000000000000000000000000000000000..15c305349104f6a398d2652e960312bface1611e GIT binary patch literal 2221 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 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_fly_first.png b/indra/newview/skins/default/textures/quick_tips/move_fly_first.png new file mode 100644 index 0000000000000000000000000000000000000000..b6e2ce60e4b37e6957791681807d43b0292612a1 GIT binary patch literal 1528 zcmeAS@N?(olHy`uVBq!ia0vp^CxCbX2OE&|{I9$cNHG=%xjQkeJ16rJ$l)yTh%9Dc z;1&j9Muu5)B!GhKC7!;n>^C`>xfK->T5c|4U|{X?ba4!+xb^n#+5C`DiQ^yd8_&Jf z;9!0E+?7dcd8<NIUL0Z(R({oV<Vve=k8YNMVqx}$9l@S|xbMuIkg+8*uu&l1OJyC4 znHrbjAwMNOhsu{c#=(sa@z3n^s+Jiia39^4`TX4X&53$*C)~OGd++l(w>=HZ#T$02 zN-#AzFfcK4uqX&1GXyvs6c`#APHUbN2wAH8J^X3uLF2nU9Fq!nZ+L$-i#O5mdCBtP zCu#?TxPkgq!+NIqc-PAPFJF0NQ<o&jDAj9PleXOv^o&+Hxx_Zy=JU_F_wJ|tG#CEF zfB50bru4WN)#ruRm)?B)-thP0rJ=dj!k_A<SNYB}dAY_rUVQ5RE47zZj6Du-o_I=o zI@|kSc|RS#Zf$$@bxri!PuHfH$?$KqPrM{`a#rlOj+FOXS3Z8=wtL4k2dO)Mcl})J z8GiWTvoh_RS^xEFD>r*Sd>yBgQM08^U%*-+^7|iirs_}2CdqF&vTFX)3r%$g%GUcA zpR4}fTXtG@(w6LJ`KQ)<-7@~}I$2`Pzio!M-`_J1-2Qo)&dX1egC1?(I_uZVrgibY zna=A|-g{SB-C>FIzkPHs>wBx?JeMx`n`BLoyqCZ1+5eb;WlK)SbG1*LBD3;&ao>{d z-Sgh+R~>(G|K8N{_cJvrzLf;-oIB}U%jUcy)!&gxraR`8&oO-YydZE%(5d|ezpH~z z<xba;y;r>E!OC6xR!_4j&RDm<{Ju%#wA!G}&u^U)TFs~Po&S)M>)~ZCJ0up#PU5>? z^w6W(?DxG-0dw*tmc0-^d8qQX^BIKz&$;d~r`o-r%<Or(TPyzcCU41;^SRrfAG=zq zb1r#f++^`AzGzOCqU%#U*|i><$9}dbcj}z(E0&fjUl=a(eB+D2?;)jT7p0gScSy|o zcJ@uY>SVSvY1bsx_6B9D2A%%5qyKQe*4ovUd;An8sKkE!QhBn!{V@AwscNm<<mi}d z(%%#ptLEz-tCg7*Qnw@Red#=3tE@CZ-rZknEN&^jj5_O-vqJFLfzWrWb1wN>c`D2Z z4fuB4?5W<2EryeR`PfP7O}p%ReqPt_pWAOQJs#tmA2MC3Ge06}VcF)mX<uARo3qwF zEM1e<Kc%;J%BDNprcAwc=E|0H$E<GaZa+QMLgVGWnKO_0KiT`2#h4?{aP6n*XTA0; zel>Y@lH>mx_0*&-Q?@XAGGCe!bjs7HGBwcj@htE6$G%pd;n~Cy{<m??68TlxMb-i5 z=kK0XJ^$h5&-K1PJ-$Vq+*~ij@ocl*AIX`^+8=*6SX4RNyW02PZf|oF;WLq*^0OzM zpSI`mb&LAq-v3X_0$+bV?)$BF$9y^6in4T>bKUX0M|d`ce4l=IYItC?%`H^{9gp_d z$}3CWCVsOpUw3YC4_9MC*)fgxVP6B!?b}iRuFGLVLgeYM9@oVA)Rnf@99<#6(X{DH zSn3-et2-R?cW2#*RrBA-kOs`R4NI?Gn19sB_}X;t2k+bzdVil?-e7&-B_fFtHCIFO zIRgt5G<%~ku#^H!jNnoLMHyHGZfu0-NjG^0<HuSD{#<Y0ZOp~stpjw<)&1;-#@BLz zjyX1C-JKchUZ~C8d-jsOOoGq!I-kfSMmz?>O;!*f#hn~2iVR3)Sj5*!r@!*gmRx*# v#<l-5c3UrI*l>giNgiqortbvG|1*VssZ@MkDb)lls2Mz6{an^LB{Ts5Lc5Nx literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_fly_second.png b/indra/newview/skins/default/textures/quick_tips/move_fly_second.png new file mode 100644 index 0000000000000000000000000000000000000000..84b63cc3382d5ea298fe716670e8f2c0d992ecfa GIT binary patch literal 2128 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 XoOV-=cBuTYnMeWmlgC(Y=hOcU=*q?O literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_run_first.png b/indra/newview/skins/default/textures/quick_tips/move_run_first.png new file mode 100644 index 0000000000000000000000000000000000000000..16093dc683e392a5d1d1282f75c44f80a27be1cd GIT binary patch literal 1554 zcmZux2~d+)5dH%s;ZQ&VD2Nax2-YTG5Jcp@gBT8JP%%J?I+dsdx#Uhz3UbJ$l1fx+ zB?Y;WqY#0gpg;r@<t&##xs=OD6oeo&v@?u4&b)o!zBjwy?##}9*In@TTcuT{0RY&F zbFgs}VXMe;Bw?Z(x2~Bl0!W~ny%kW*ReLLXNKqV41_FQ#V#6T79mWpPCp-vu%og4! zDK3LC`amHb0RZSjoQ<XXmHxRw&pgFofcoB_cX%=vTUZtgVbQgGV@-n&6T7_jJe1i- zjO0kZT||bdhi}`H@u0Q59GUzk7G`N<w=DngwvL^xvVpr546AEMx?{_nx*(^Y)KoP; z%`uG-M$2z~JQEOluKu_6n2=N?E(7(|aU0kd+>w;Rt~fn4Y7LtC94b{hp`qPaT~~_O zc_9m-plzAo!$TLp(~2T~@M;#H61xg&f?OS^;beAD#+0Rs!(74G5csQ(lW?$mI)69e zqn5dJr_{32xZ?<E<Pp1RsRdVB<q=wLtyO}2isOeeBpO5@OF{F!Mn|>g{SH4hR&CSc z|3d1{o%c&=w%FcKO^lnsX_F-{oA8Q0GIX4_14n6Osy=7_uQ`AqVyihGf3BOyiLaFd zk_3oOfUj99du2C1*4oRmzv(7>!5?kX%1vbl$?&&Pc2Yv3UphfA!3=FlwS`9~jRR>K z)NW8|`TAQ$A47i7nwPUd+9Ji5w49_|f8#Fr1jY+9l<w>!mcB5Da0>*Vx<P$d$BKR* z6wHkK$-k06!ASRRBmh~!7&VXz=a>x^ZVA?yPD>|yU)?PX87W>h#Y<q|hD!GWy%m|; zjo~T-$Q2p~4Dx~K-PEApdfd-?v7Fr|?qcj#S=``fv!tr0sNG0o*VcjiUFmqJI<NP| zTyl}AFG{$+H0IMY`Usx&6z39!UBTXuiGsF^tq7Jm2pHB5(Q0f4zm%GpGsy68-37Ne zzr#%$(VH6_4aUb=FoS#4KRK&)CHzso=Ay{tiI+?k6bB}BpAynqs9^yLv*fYf8dhnf z>d-~<`_)PLf=V+ep&6&wF<Bx2>U^C^VTm4Tdy_JA+*jr3;%e<0^>MQVUsgkWI^OJ` zspDqph*@*dj9}PB_`o6XE=Z~OJE_QQvp-O+@+|b$bJOL|Otit2Ps_oY(#V$<rw|;w za@`*Yg^BE-QK>b$D`Uv<Y!`npFu5j+mK=c6h3G239$wLLg6~`{GnZ-WG`XGqvnwf# zMXTtM??by&r9ikVoomFE8h_xsr4BC|ZBfgz4rUk0IDYo(tHh6Y7y4NX7y?70$(4@T z%c?YjOHxx@>9WnZw4P6z_aXX%2_;whJmfX6<#{LV$inXfC+ni}vV=JY-L$Xu(yBRT zii6IJ=U1%CdEw1d&I8KYjfN%2qSSFD1(7yhfO%emLXb^9Pq4?M#rQD(5z4jM?7aN~ zqZ?yYv&ERTXwUpt#OerYDyQC&f*M{V8-;r=$&I|mhqn+v7vu#fpw0}_i`oysXu;hL zvDxcmvTd~R%sDi8Hf6m>Me{>(cxdIK*dftYWYQ`;P~MqQOMhM-!ARUIc>lxzjPw!b zlcQ~Mf|~ZC0EN?{)#Pz?rfYYcfJVYsp=#U`&>5mXhWh(eK(EtM{@RqplY*Gxp_n;q zY+9L1h^K18bTYwy5C+?$lCZJ(2Dp+KmpAVMt}wa`Ud}|+pRP);J$o};s5VXfkz;`p zPv2sLmH*OFNjQVdpgC;hf9ZT1wvqUqu#Ln`w)_c4)3voWbuo2qkqAvEmgV{iGaEh+ zG0{d$_#Hzbnq@vS|ICeZu^%>2vCUuL_-)az*fweZbH40tv)k`AiIvA~(xN^5I(TT- qdFPeI(Cn&3`t7f!@qeWx&UhPy9gE{@fDs}I2XMA{n_?@U*na`Tmc}&z literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_run_second.png b/indra/newview/skins/default/textures/quick_tips/move_run_second.png new file mode 100644 index 0000000000000000000000000000000000000000..19fa43ec32a8c7a2e41936b3f3033ccb986cbc36 GIT binary patch literal 2534 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 literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_walk_first.png b/indra/newview/skins/default/textures/quick_tips/move_walk_first.png new file mode 100644 index 0000000000000000000000000000000000000000..92d120d53ea03a48a14e88f39d070d280bcd176e GIT binary patch literal 2106 zcmchYcTf}97Kc+Lp@pb%A=IGKB9aUekfm281c3zsDHdEsBPduXAwWP>)JPG~)zBnT zL==Ky>BI=QGy~Ee2q+O00s<i*HIQu9_h#PP_x^u#?>T4gH|LzWbLZasyW{S97$&PC z3jhFMcqa!BNo<qY6KROV<HdVRBmsEU<FFl|tV?ZLvXBXL^1TWG$RYkRAb^&QltAb; z{1Hd!2WhYzR>f4#AXh@(;T>#`Mh(x6QtqjpRc{rno=6peWDK4n4{HHkc|#CmbfsU} zGPFf;8NLa=ut!^GC*H-yMN4a^_94VC2%Jtj^1+Q~JLnZMEd}pUHblexi|&EW=o=1Z zdS~vQ&i`E5xSSfRbMSa%<jTBcTpBB<)EUjr&v7jBNUX7QQviIr*5BubE64sl8J|5! zZ6zuW6m6(+8b4d99>ao^k~lp$>Wa4oWm^=h@*53Djqq*=0=qZx2}H%?7J7j>WmnRm z+FbkC6_N(pQski2Ek5=(VjwsoIyn>gbDs{FPVzkstWOYZA1zHcwKnI_tLxNe0l^uj z*18<}!I4Z=YQl0LQ(@MRr(5%U^YMieoL+37dtS~v3JBUX>B~N!gs7K|iX4hz>{^4V z$F+E|UoEUn<ESa*<o=j_6*`_lKYi^da=S2{`-Q3KpN9jpEyxeG|1k^wqM9My)<;xS zcOKsiWefL#JTUDM#vG@tgj5g;bf{^zQVj`C0Vg$|tB<S-%GK)XhUNk=@cMaYCU50~ zwf5eL9D-4uUx({>40_@0DSd|7z1Mr$<?*OuU)-d;#~l6%&%DfO+~UGzZgAlnRxy!H zF}<^N)xRM~hJgu5F|6qKU;9;h^5OQhNC4H&3A3$CDh|+)*0Nqqj+DBjnsPS(+Wsa1 zvsUJCcaxQ@1#}b^pq%pU^eI@F62tt?5)<YWj#@-<D;U0Dt54&^(u6&xsSj0Rnx1I9 z<XPvsFnM2gS&x(0{0vjKqN`G6NEd3nkRT@u2UM?6Y6p5ST)KjIYwu^!8Jp<$Ntwdb z#v?%DU{c6)p7jY}oWiJD$BQMqp)TM~ZYlfQ=UQrl`IAp{hnLuyH+%|w;qgKgbm1nB z`iF3$|DMb8Re7*5K{Y|H>FtG!eWZHrJ4>vM@rbBg=ofdIqgcVHTOXf|0%C#@X(_O1 zn&aiH?nQ5&wSw;DI9%rG-C@6bipAfDiEYK6cSmJn&>{2CGB|T4rrLl*7t&VLoyKG2 z!nUv3)M#FmVtteEt$i1563_$0;Kw)Vy#N)EiODhw$Jyhfb(uv!A{IapgmzCfLY7ZU zFxyh(`Ufsy+2MV9Qo_0HPlG{X<igY5veF#eIwqo~1V`O`h1_J{EfPJoh!2Im8Iuly z3kQJ&>R^HIwYp}_<2$1tg$J5MyB+KCQ|`bxH@ae*1-{(kz$Gc}FpesEdrA-cNDERR zJW%RobJt_~DD}ZJOB`!=`OT?|{8wVV>zBzqWAAs1vfa_#>fP7MdupZ^y&$cfg{}G< z(}}QUf$hkLA~+g!g|YrH9Y;L@6^+uTc*rz{l~_6%t5zI#eWtH*ZhW_n_mDTJ6uJMa zMsO`~x-4i5x-iHf+3uVwZC;!@pCx))3-`@wA?<=tDgvVSbLdlk4U<(x!>f*5G8=|_ zh{DS0V+sD^w&81`=#w%H$7utU-&)q|fU-{O<kEu%6*@jaFVUPmozBpu9tGgKpB~es z=a`3IFTEWz;ujrrFwCFkSUj9*ZzLdF?XYT2aZkiTH6#yb21iwZ+t_r(wi3EDGvu6V z-|g!t65p~N=$Od2Mt8jE5P@q7zOQA?H5n#WNsd&0ZCBX-S##9T{g!nyR8uog-||za zP2Fl#iPcBx0E7nWe57g&%~3bLcz9dEM|lqxl$WDUo7O+~EZbs-C{}q$epjiF(yg=? zv#EW*@YkaxS0FK)^c%a}prQ_Cs+(atrUcojEewivdrOE+V*UD47*P;GRNQLhEWr;5 zK6Y&3vniIds!s*6t&mgxHBCOIW;o8+`eViyVHl5;?tUru%KU3YNwV8s=~d8cnbzgx z_kG9VG4)45d;;@)o>5zW=L<haanI;8`w70Y*#n=jNhPn~W?`N*bI?$Qz{nzQ8v5M4 zFVF};u7L8eTMf%>Fg_b@MER&@N3qCcD=#2)ykTyDle5)u%Q280veL`v@m8T%{&P_x zj#}jzOK#p_CN}ggKi6#yIEkLCQ&@AX$sk$H^ba;3nxOVf!P>s4%lhOrd3qHdqB({h zG$t2656Zz&=cSn~&H39*VGYg`pGq&XB|otU*Qq^e$&PfczXW1gyMY(uxJhgyc01$! zl^cIt+4#zg4XMZMyC2kMw{{W?BdL%J=PLr@ElL`*?zLJ%APxsK)8%h#;d|wkzw>Qp z6o9RG-R8u&$#3CCy@txazhT`PE+G8K0^XOuea1!$yhnL^d%P3GA^pFBq|;yM-x>b` zKZ<^o{3rOIE}Yuoc(EuvDSpC1B204hs>&+<mSFW!*PBNgxfS!(^Xs!wiowRIM3h?J zKFpHy|7%n7jiDdyN0uh|hB+gK27gz~e+sDL3o%g6dDW!2;&zrq>H&C1SBEmYQ`i3l D++@se literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/quick_tips/move_walk_second.png b/indra/newview/skins/default/textures/quick_tips/move_walk_second.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e28722bea507957036c4fc11eade6cbf3240fc GIT binary patch literal 3108 zcmai$c|4R|8^>ox!!-6u$`)_dki8HgDYR&_46+oGbuhLFBV?C&Y{{N|h{Ryf@E}A} zS%(=$WbhbElV*(Qy?g(w=a2XLe9nE&eO>3iKiB!4?{z*W@w$a6FI*H30)cqV%}j0r z{Q%I4VVuCz{HJs^(1Fo6O^reI@5NVumxF$0wrCKD`_Qij20eRz6mW6{nqR%ZMS^i~ zE1ro&?EH$gn46rl44tM^?7f91!Tno5*Qbq4H2cXsa&Z{@E1qX=mm*@M)zYi9673XX zUwBBZULLEd8S6ToCB<LYd%nD%Kf-K`OLY2ia)v^x-Qa)Jm$G3oiASKGmPt~L>aCn; zsndPfYmyHqQnVeN2;q&)UGwaad+x!(Pl!00Mw6F-;Quob^O7qPI;#(8m<PW8<*4D3 zb1gsR{7yHln$P9##jG)O1fs}{E_DVcsf)9U2V1k1YO9$t>AHZ6a4}{gRsN1lsiN&c zs^D050cu!@xx-8Z-zlEamdjY7Ysx<Fc8L;b?F@#^ygcUmpdo^jd(_+6s%LemiWYG; ze{R0Cka>vOOsJV$*A}<P*^SV<++t&NQy_h)g!8}@;{FX3r`^;^Tk*6Jf><<d?=fmv z)pU6tC2zTS1yzIw@4%LWagxblv%PmLgE1Q>XE(e!EDQY!0l53o{P6<mtwr*-MOWuT zMW>*>c=;%B<e5kD%cA$77Te$34hziXdJ+6_x%^o1Vhw%BuwQai$QuUcEtgKO3xQ+( zdu5lp4~PD~i&3?`{)!mGotk3rD6rk(W-FXFPB5_X1)(@pclraLQ16UAa&3i*SZFKF z79@dZ;-^MLzp^-{L|gYNb~}{@_wx8mbvKWxb=R@wH>Kxtr(lwoz#?(roiXi-W34)| zm;-oMNxn~q!&L+bZ=mhUTO#GOvcjAq=sa=_BDi5U0W$oSYTjpL6Z1_OHt?2^v;Mub ziguM=c{3K0)hSofqna94I7u{Ehz`K94A+6R(L9_lb(C+VdiXmKxTE(fTIm`hX;7n6 zYA3D-&oNWmvP#d_KnDYj$a+q7_B`Od0yGlV8-tcoBfRCkZo{Xs&zjP%a7m!lIvixW zUC>rqeZY_R{j7znImRkP4UY&Nvjz`75_VOfV5zKy>&8YIK~0MB8v6-hvqIDpIF{_D zMUPy#1NVW=z%hoLyOeleec$sh))AZ!C$*QtlKAUvu{VU%!{&}I*cIL@_Qzm&f-w8~ zYVRqLZ?%`+#R}I;gwCBzL(f!dir=Czo;ZOwp_{R&;iyr+&}J!;0I+XF%sm_uvE88? z4M!}kljzT49Sq?q4)Dwr!+LaxVw+(%S{x-uS{jj=sXTvb)6BUI#<G5vR)=vl=gwfM zNP1ro2FD#-;74$-b_>k+2o^!krhBtBS06AaNGKIC=-$2$zMX2=f|pZv$Znn65|);n zI<npINlV<m327^o?n=Ri+N|(76(rWouWPNX&Zik7I4LMu?hMqGBMo{nG24c1)(eKd zZ33ZlsYPRt7DKraFIn;kckhQT^$=brLO?s{$6e>~m!*a7nR_5ZZtvaF8AFL#h~xKE zkD$zhlVmmugu<hB-~&kh1U;so;w&*OY__M02Cek-%2*SXj8{$xn;io%pssJ*II;SF zC=Eu|Vsx3TK*@WUcXuyNWwX9Wcd4fm`i<i3%!zSH)$4aXgq1GiZ7+jW2U*hUQd^mc zUkI#N^&w|UZFu9Ut0?ghM79?uCx$4!`rze@<xS6X15~aG_R4o`8BGJe+$Oc9*6{aX z=R2Q;ursuC+L-qo`>@xL8OTN#o=u{GsT!Nk9r({;XkQrd<pCDXUW>ppm-{}}=hN5d zYT$$rW;NTtCZN02!=I{C9*OgG)M6opfw(8kBYZZ|zM!CJe>1-yPq9#v0PL;&`GfI# z6S~w~`)`<S5#`!BP&fn?pw~oCa)G)o;txp>o*F@K>kY7^8}qke4LuYCx)|C6Mk#y4 z$MD!cMWJA2+}xsbFxSX6To@*~^0?c9FK#5p4hFAzv*cXAWH+XFcYaIBH*>^s<UpZc zvO3#hj<3&`%KUbl<Gbq^<6f_-uXt6hRxDhyJwBbB6gJC$+id9*8nLxkMYC$n-j2j~ z{JpAD5f&cQ*mdUm6aK|Co>#;hQd>zAt~A5QVahdX1XT>}mYelT_Cx6f@`Br|@lIo+ zRX^Q#92bov^Ax9aW5zhTukDZX2FR+c2W*r@TZM4m4{9NsG8JpvZKEfnIH!bidBfnW zn3|S^Kg`T7E&xz-Z^z1%Gc)I%>a3lcE5S9^Sl5a3junR>)WifVc*Dp<NZ^m*9}XG$ zkpjJ(>k7SzhveDVjn&n=pL-KcjtfrD%<PgUKYTD!5W2fgZc{XZx_aB=TWC>W2_3&; zBD=l)3}DOa>q{R>x_*9XZ)p+6obsBe0v%2#!^}E9ah+ESTD8<C{=+nY$}j@hnky^p z0s5DBIeF?XoSAZ0OY7=V{aR@e9+dW=6fy0zv^2gHb#c95Y)H|{Xyxei^rc(34)yi* z<yDKHm24YXAyR6f<}szE$A^Z7?xRqZB_&`CQn~+Qndu2t)yj^J=WKSE?`+3G0`Rqm zk5BpQ*IF*~0#KQ<h4fz$a_dL2bYT8d>9aq5)~VewAgp7j9kdd&xTN!<r6t=;rstL0 zI|WtMpF<I%QD&!8&V8!r?4(>gE@+QL-gjxtjabTa$8PL)GIRd=Ybq%T?p4<eWOrH! zPExX|pSof^Cs83R;{b=lL%)4AZ40K0^78VE8$4{qeE|V~t*oz4yH#oNkxU-$iQ~>Y z?eh$70Uqr1wYIW4OsCV8ow_=%8Trn2jigEFY3-+z|G8`HMc?1sJ?YH&`c>JP_*{21 z+{wYA0O~D+Xv9P?DIq=;)yd@yDUY+%I(wXgvhvy<WnyAtce~KR!9hq!=mUvlt|MLn zh-{uI=hhOite?=1T+zDIbHEyl1QUR@vL7;iA|nkh=cquP2Qy?v_~WafjqI<U%~GD{ z{!PvQSo)o)L2KQJHvImN8tLPJX~?m2R%f0(B-LKgv@BxW)L@UhcXI73JvLSxRaO`+ z`JnYO0dl+)lb|4V9G>v|@L!Hn%)n6uJT5HiD}#||5OF3eE6dW#>LZC%4Qb~R*{NjK zTGze8)M2r&Non&@v8P9g&2vRN4B8Bu_C9q&W26A1rL8^Vr{fJ4<BRt}qnjWaJ>bTP z>H2z=nXxg~kae;LZ6x0vY;R}hsi&v+*4wDx<cQbCY-eCdh-T!E&~`kYghLfgZwU>& zdso)lnhR(g@Pp-l>C&b9-rkGblTMRIW%B8>onjdJ4324=J$6D_d2!sv33_xCWp-j` zx+pM`<1MWy>iu(Fw1SGt60qsRg=g~tvHiC`UpN-FT!NKg@incD+Ewi7Pe#76DladO z%hPnfi9`;J*V>rc=Ph02e&tR)hHdsHw>|~vthk!rF!9UNIZ`?G*NIyowf?H)EIOrj zBww3jbFGP3lb<EGWnETWYy=*>NFx^gLe947UgO<9I7m@Z@mCg8jV{j(qa2%c;yk^) zz{rl!Mo7j;oheXg^M1M46-)qN+S=N1yRy~(d+eYVpBYX9w`xZ*L}Ur0aZ*^-QJ<QK zmA#z3tUmxN<Z46H(tJET8u1|;EkO3d4aveMUjgu)xsmG=HQe8Sk$VcLR<YzhHu*?$ zpZAR$PoZn1CilbXLIvhd4bIV>e)B!K2AKw)c;wdl_+wr%Sp05Ril5Ffd;6bLNXeBU z1fS-EudYDqRW&uA7Y8!|0qvogsT;v=Zf?R2<KyFdvp`AsfbFfVfzso8Q3Dm(mWP{` zeGDx1<H=c>D(XXg{1dw0Ni)kf8|+I`oDftE&+=GWZTjtmU3~VFBi_L=ua<vd1h~|L N%r97&)EhfL`Y#8W<$nMG literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 343ff893e8..1501f39b67 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,14 +1,15 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater can_minimize="false" + can_close="false" center_horiz="true" follows="top" - height="64" + height="95" layout="topleft" name="camera_floater" save_rect="true" save_visibility="true" - width="176"> + width="105"> <floater.string name="rotate_tooltip"> Rotate Camera Around Focus @@ -21,50 +22,121 @@ name="move_tooltip"> Move Camera Up and Down, Left and Right </floater.string> - <joystick_rotate - follows="top|left" + <panel + border="true" height="64" - image_selected="cam_rotate_in.tga" - image_unselected="cam_rotate_out.tga" layout="topleft" - left="16" - name="cam_rotate_stick" - picture_style="true" - quadrant="left" - scale_image="false" - sound_flags="3" - tool_tip="rotate_tooltip" + left="0" top="0" - width="64" /> - <joystick_zoom - follows="top|left" - height="64" - image_unselected="cam_zoom_out.tga" - layout="topleft" - left_delta="64" - minus_image="cam_zoom_minus_in.tga" - name="zoom" - picture_style="true" - plus_image="cam_zoom_plus_in.tga" - quadrant="left" - scale_image="false" - sound_flags="3" - tool_tip="zoom_tooltip" - top_delta="0" - width="16" /> - <joystick_track - follows="top|left" - height="64" - image_selected="cam_tracking_in.tga" - image_unselected="cam_tracking_out.tga" + name="controls" + width="105"> + <joystick_rotate + follows="top|left" + height="64" + image_selected="cam_rotate_in.tga" + image_unselected="cam_rotate_out.tga" + layout="topleft" + left="2" + name="cam_rotate_stick" + picture_style="true" + quadrant="left" + scale_image="false" + sound_flags="3" + tool_tip="Orbit Camera Around Focus" + top="0" + width="64" /> + <joystick_track + follows="top|left" + height="64" + image_selected="cam_tracking_in.tga" + image_unselected="cam_tracking_out.tga" + layout="topleft" + left="2" + name="cam_track_stick" + picture_style="true" + quadrant="left" + scale_image="false" + sound_flags="3" + tool_tip="Move Camera Up and Down, Left and Right" + top="0" + visible="false" + width="64" /> + <joystick_zoom + follows="top|left" + height="64" + image_unselected="cam_zoom_out.tga" + layout="topleft" + left_delta="74" + minus_image="cam_zoom_minus_in.tga" + name="zoom" + picture_style="true" + plus_image="cam_zoom_plus_in.tga" + quadrant="left" + scale_image="false" + sound_flags="3" + tool_tip="Zoom Camera Towards Focus" + top_delta="0" + width="16" /> + </panel> + <panel + border="true" + height="30" layout="topleft" - left_delta="16" - name="cam_track_stick" - picture_style="true" - quadrant="left" - scale_image="false" - sound_flags="3" - tool_tip="move_tooltip" - top_delta="0" - width="64" /> + left="0" + top_pad="1" + name="buttons" + width="105"> + <button + height="25" + label="" + layout="topleft" + left="0" + is_toggle="true" + image_selected="btn_orbit_selected.png" + image_unselected="btn_orbit_unselected.png" + name="orbit_btn" + tab_stop="false" + tool_tip="Orbit Camera" + value="true" + width="25"> + </button> + <button + height="25" + label="" + layout="topleft" + left_pad="1" + is_toggle="true" + image_selected="btn_pan_selected.png" + image_unselected="btn_pan_unselected.png" + name="pan_btn" + tab_stop="false" + tool_tip="Pan Camera" + width="25"> + </button> + <button + height="25" + label="" + layout="topleft" + left_pad="1" + is_toggle="true" + image_selected="btn_freecamera_selected.png" + image_unselected="btn_freecamera_unselected.png" + name="freecamera_btn" + tab_stop="false" + tool_tip="View Object" + width="25"> + </button> + <button + height="25" + label="" + layout="topleft" + left_pad="2" + image_selected="btn_firstperson_selected.png" + image_unselected="btn_firstperson_unselected.png" + name="avatarview_btn" + tab_stop="false" + tool_tip="See as Avatar" + width="25"> + </button> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml new file mode 100644 index 0000000000..c16373ba3c --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_close="true" + can_minimize="false" + height="250" + layout="topleft" + name="set_name_in_the_cladd" + save_rect="true" + width="300"> + <check_box + height="20" + follows="left|bottom|right" + label="Turn off Quick Tips" + layout="topleft" + left="5" + name="DontShowFirstTimeTip_checkbox" + text_enabled_color="white" + top="225" + width="200" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 7666a2494d..17d12c89b7 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -1,128 +1,184 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + can_close="false" can_minimize="false" center_horiz="true" follows="bottom" - height="58" + height="95" layout="topleft" name="move_floater" save_rect="true" save_visibility="true" - width="135"> - <button - follows="left|bottom" - height="25" - image_disabled="move_turn_left_out.tga" - image_disabled_selected="move_turn_left_in.tga" - image_selected="move_turn_left_in.tga" - image_unselected="move_turn_left_out.tga" - layout="topleft" - left="20" - name="turn left btn" - picture_style="true" - scale_image="false" - tool_tip="Turn Left" - top="29" - width="25" /> - <button - follows="left|bottom" - height="25" - image_disabled="move_turn_right_out.tga" - image_disabled_selected="move_turn_right_in.tga" - image_selected="move_turn_right_in.tga" - image_unselected="move_turn_right_out.tga" - layout="topleft" - left_pad="21" - name="turn right btn" - picture_style="true" - scale_image="false" - tool_tip="Turn Right" - top_delta="0" - width="25" /> - <button - follows="left|bottom" - height="25" - image_disabled="move_up_out.tga" - image_disabled_selected="move_up_in.tga" - image_selected="move_up_in.tga" - image_unselected="move_up_out.tga" - layout="topleft" - left="91" - name="move up btn" - picture_style="true" - scale_image="false" - tool_tip="Jump or Fly Up" - top="4" - width="25" /> - <button - follows="left|bottom" - height="25" - image_disabled="move_down_out.tga" - image_disabled_selected="move_down_in.tga" - image_selected="move_down_in.tga" - image_unselected="move_down_out.tga" - layout="topleft" - left_delta="0" - name="move down btn" - picture_style="true" - scale_image="false" - tool_tip="Crouch or Fly Down" - top_delta="25" - width="25" /> - <joystick_slide - follows="left|bottom" - height="25" - image_selected="move_left_in.tga" - image_unselected="move_left_out.tga" - layout="topleft" - left="20" - name="slide left btn" - picture_style="true" - quadrant="left" - scale_image="false" - tool_tip="Move Left" - top="4" - width="25" /> - <joystick_slide - follows="left|bottom" - height="25" - image_selected="move_right_in.tga" - image_unselected="move_right_out.tga" - layout="topleft" - left_pad="21" - name="slide right btn" - picture_style="true" - quadrant="right" - scale_image="false" - tool_tip="Move Right" - top_delta="0" - width="25" /> - <joystick_turn - follows="left|bottom" - height="25" - image_selected="move_forward_in.tga" - image_unselected="move_forward_out.tga" + width="115"> + <string + name="walk_forward_tooltip"> + Walk Forward (press Up Arrow or W) + </string> + <string + name="walk_back_tooltip"> + Walk Backwards (press Down Arrow or S) + </string> + <string + name="run_forward_tooltip"> + Run Forward (press Up Arrow or W) + </string> + <string + name="run_back_tooltip"> + Run Backwards (press Down Arrow or S) + </string> + <string + name="fly_forward_tooltip"> + Fly Forward (press Up Arrow or W) + </string> + <string + name="fly_back_tooltip"> + Fly Backwards (press Down Arrow or S) + </string> + <panel + border="true" + height="70" + follows="left|top" layout="topleft" - left_delta="-21" - name="forward btn" - picture_style="true" - quadrant="up" - scale_image="false" - tool_tip="Move Forward" - top_delta="0" - width="21" /> - <joystick_turn - follows="left|bottom" + left="0" + name="panel_actions" + top="0" + width="115"> + <button + follows="left|bottom" + height="25" + image_selected="move_turn_left_in.tga" + image_unselected="move_turn_left_out.tga" + layout="topleft" + left="10" + name="turn left btn" + picture_style="true" + scale_image="false" + tool_tip="Turn Left (press Left Arrow or A)" + top="35" + width="25" /> + <button + follows="left|bottom" + height="25" + image_selected="move_turn_right_in.tga" + image_unselected="move_turn_right_out.tga" + layout="topleft" + left_pad="45" + name="turn right btn" + picture_style="true" + scale_image="false" + tool_tip="Turn Right (press Right Arrow or D)" + top_delta="0" + width="25" /> + <button + follows="left|bottom" + height="25" + image_selected="move_up_in.tga" + image_unselected="move_up_out.tga" + layout="topleft" + left="10" + name="move up btn" + picture_style="true" + scale_image="false" + tool_tip="Fly Up, Press "E"" + top="4" + width="25" /> + <button + follows="left|bottom" + height="25" + image_selected="move_down_in.tga" + image_unselected="move_down_out.tga" + layout="topleft" + left_pad="45" + name="move down btn" + picture_style="true" + scale_image="false" + tool_tip="Fly Down, Press "C"" + top_delta="0" + width="25" /> + <joystick_turn + follows="left|bottom" + height="25" + image_selected="move_forward_in.tga" + image_unselected="move_forward_out.tga" + layout="topleft" + left="47" + name="forward btn" + picture_style="true" + quadrant="up" + scale_image="false" + tool_tip="Walk Forward (press Up Arrow or W)" + top_delta="10" + width="21" /> + <joystick_turn + follows="left|bottom" + height="25" + image_selected="move_backward_in.tga" + image_unselected="move_backward_out.tga" + layout="topleft" + left_delta="0" + name="backward btn" + picture_style="true" + quadrant="down" + scale_image="false" + tool_tip="Walk Backward (press Down Arrow or S)" + top_delta="30" + width="21" /> + </panel> +<!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml --> + <panel + border="true" height="25" - image_selected="move_backward_in.tga" - image_unselected="move_backward_out.tga" layout="topleft" - left_delta="0" - name="backward btn" - picture_style="true" - quadrant="down" - scale_image="false" - tool_tip="Move Backward" - top_delta="25" - width="21" /> + left="0" + name="panel_modes" + top_pad="1" + width="115"> + <button + follows="left|bottom" + height="20" + label="Walk" + layout="topleft" + name="mode_walk_btn" + pad_left="0" + pad_right="0" + tool_tip="Walking Mode" + top="2" + width="43" /> + <button + follows="left|bottom" + font="SansSerifSmall" + height="20" + label="Run" + layout="topleft" + left_pad="0" + name="mode_run_btn" + pad_left="0" + pad_right="0" + tool_tip="Running Mode" + top="2" + width="37" /> + <button + follows="left|bottom" + height="20" + label="Fly" + layout="topleft" + left_pad="0" + name="mode_fly_btn" + pad_left="0" + pad_right="0" + tool_tip="Flying Mode" + top="2" + width="35" /> + <button + visible="false" + follows="left|bottom" + height="20" + label="Stop Flying" + layout="topleft" + left="0" + name="stop_fly_btn" + tool_tip="Stop Flying" + top="2" + width="115" /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_navbar.xml b/indra/newview/skins/default/xui/en/menu_navbar.xml index 013136a593..435d928f00 100644 --- a/indra/newview/skins/default/xui/en/menu_navbar.xml +++ b/indra/newview/skins/default/xui/en/menu_navbar.xml @@ -8,14 +8,17 @@ top="624" visible="false" width="128"> - <menu_item_call - label="Copy SLurl to Clipboard" - layout="topleft" - name="Copy SLURL"> - <menu_item_call.on_click - function="Navbar.Action" - parameter="copy_url" /> - </menu_item_call> + <menu_item_check + label="Show Coordinates" + layout="topleft" + name="Show Coordinates"> + <menu_item_check.on_click + function="Navbar.Action" + parameter="show_coordinates" /> + <menu_item_check.on_check + function="Navbar.EnableMenuItem" + parameter="show_coordinates" /> + </menu_item_check> <menu_item_call label="Add Landmark..." layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index fe1baf22d0..4d1572e4a5 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -405,6 +405,15 @@ function="Floater.Show" parameter="hud" /> </menu_item_call> + <menu_item_check + label="Show Quick Tips" + layout="topleft" + name="Show Quick Tips"> + <menu_item_check.on_check + function="Help.CheckShowFirstTimeTip" /> + <menu_item_check.on_click + function="Help.ShowQuickTips" /> + </menu_item_check> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index d42943d225..4c880f6dc0 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -55,8 +55,8 @@ left="0" name="DUMMY" top="0" - width="5" - min_width="5"/> + width="3" + min_width="3"/> <layout_panel auto_resize="false" follows="right" @@ -64,19 +64,116 @@ layout="topleft" left="5" min_height="28" - width="90" + width="70" top_delta="-10" - min_width="90" + min_width="70" user_resize="false"> <button - bottom="22" follows="right" height="20" - label="Stand Up" + is_toggle="true" + label="Move" + layout="topleft" + name="movement_btn" + tab_stop="false" + tool_tip="Shows/Hide Movement controls" + top="6" + width="70"> + <button.init_callback + function="Button.SetFloaterToggle" + parameter="moveview" /> + </button> + </layout_panel> + <icon + auto_resize="false" + color="0 0 0 0" + follows="left|right" + height="10" + image_name="spacer24.tga" + layout="topleft" + left="0" + name="DUMMY" + top="0" + width="8" + min_width="8"/> + <layout_panel + auto_resize="false" + follows="right" + height="28" + layout="topleft" + min_height="28" + min_width="150" + top_delta="-10" + width="150"> + <split_button + follows="right" + height="18" + name="presets" + top="6" + width="35"> + <split_button.arrow_button + image_selected="camera_presets/camera_presets_arrow.png" + image_unselected="camera_presets/camera_presets_arrow.png" + image_disabled_selected="camera_presets/camera_presets_arrow.png" + image_disabled="camera_presets/camera_presets_arrow.png" + tool_tip="Camera Presets" + /> + <split_button.item + image_selected="camera_presets/camera_presets_rear_view.png" + image_unselected="camera_presets/camera_presets_rear_view.png" + name="rear_view" + tool_tip="Rear View" + /> + <split_button.item + image_selected="camera_presets/camera_presets_34_view.png" + image_unselected="camera_presets/camera_presets_34_view.png" + name="3/4_view" + tool_tip="3/4 View" + /> + <split_button.item + image_selected="camera_presets/camera_presets_fron_view.png" + image_unselected="camera_presets/camera_presets_fron_view.png" + name="front_view" + tool_tip="Front View" + /> + </split_button> + <button + follows="right" + height="20" + is_toggle="true" + label="Camera" layout="topleft" - name="stand" - top="3" - width="90" /> + left_pad="0" + tab_stop="false" + tool_tip="Shows/Hide Camera controls" + top="6" + name="camera_btn" + width="70"> + <button.init_callback + function="Button.SetFloaterToggle" + parameter="camera" /> + </button> + <split_button + arrow_position="right" + follows="right" + height="18" + left_pad="0" + name="snapshots" + top="6" + width="35"> + <split_button.arrow_button + image_selected="camera_presets/camera_presets_arrow_right.png" + image_unselected="camera_presets/camera_presets_arrow_right.png" + image_disabled_selected="camera_presets/camera_presets_arrow_right.png" + image_disabled="camera_presets/camera_presets_arrow_right.png" + tool_tip="Snapshot Settings" /> + /> + <split_button.item + image_selected="camera_presets/camera_presets_snapshot.png" + image_unselected="camera_presets/camera_presets_snapshot.png" + name="snapshot" + tool_tip="Take Snapshot" /> + </split_button> </layout_panel> <icon auto_resize="false" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index f7b2481f1c..55ac14ed46 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -492,16 +492,4 @@ <string name="no_groups"> No groups </string> - <panel - layout="topleft" - name="panel_profile_view" - class="panel_profile_view" - filename="panel_profile_view.xml" - top="0" - left="0" - width="355" - height="465" - follows="left|right|top|bottom" - visible="false" - /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index c91cb2394c..1a88cc55ec 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -1,52 +1,48 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel background_visible="true" - follows="left|top|right|bottom" + follows="all" height="400" label="Places" layout="topleft" - left="0" min_height="350" min_width="240" name="places panel" - top="400" width="305"> - <panel.string - name="landmarks_tab_title"> - Landmarks - </panel.string> - <panel.string - name="teleport_history_tab_title"> - Teleport History - </panel.string> + <string + name="landmarks_tab_title" + value="Landmarks" /> + <string + name="teleport_history_tab_title" + value="Teleport History" /> <filter_editor + background_image="TextField_Search_Off" follows="left|top|right" + font="SansSerif" height="20" label="Filter" layout="topleft" left="15" name="Filter" - top="3" - width="270" - font="SansSerif" - background_image="TextField_Search_Off" + text_color="black" text_pad_left="23" - text_color="black"/> + top="3" + width="270" /> <button - name="landmark_search" - layout="topleft" - top="5" - left="23" - width="13" - height="13" - scale_image="false" - follows="left|top|right" - font="SansSerifBigBold" - image_selected="Search" - image_unselected="Search" - picture_style="true"/> + follows="left|top|right" + font="SansSerifBigBold" + height="13" + image_selected="Search" + image_unselected="Search" + layout="topleft" + left="23" + name="landmark_search" + picture_style="true" + scale_image="false" + top="5" + width="13" /> <tab_container - follows="left|top|right|bottom" + follows="all" height="326" layout="topleft" left="10" @@ -54,26 +50,42 @@ tab_position="top" top_pad="19" width="280" /> - <panel - class="panel_place_info" - filename="panel_place_info.xml" - follows="left|top|right|bottom" - height="675" + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + image_disabled="widgets/SegmentedBtn_Left_Disabled.png" + image_selected="widgets/SegmentedBtn_Left_Selected.png" + image_unselected="widgets/SegmentedBtn_Left_Off.png" + label="Create" layout="topleft" - left="0" - name="panel_place_info" - top="-310" + left="10" + name="create_landmark_btn" + top_pad="5" visible="false" - width="280" /> + width="60" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + image_disabled="widgets/ComboButton_Disabled.png" + image_selected="widgets/ComboButton_Selected.png" + image_unselected="widgets/ComboButton_Off.png" + label="â–¼" + layout="topleft" + left_pad="0" + name="folder_menu_btn" + visible="false" + width="20" /> <button follows="bottom|left" font="SansSerifSmallBold" height="25" label="Teleport" layout="topleft" - left_delta="10" + left="10" name="teleport_btn" - top_pad="5" + top_delta="0" width="80" /> <button follows="bottom|left" @@ -97,7 +109,6 @@ top_delta="0" width="60" /> <button - enabled="true" follows="bottom|right" font="SansSerifSmallBold" height="25" @@ -107,4 +118,13 @@ name="overflow_btn" top_delta="0" width="30" /> + <panel + class="panel_place_info" + filename="panel_place_info.xml" + follows="all" + layout="topleft" + left="0" + name="panel_place_info" + top="-200" + visible="false" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 4f559394a6..2b21c05283 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -438,7 +438,7 @@ left="0" name="status_me_panel" top_pad="20" - width="125"> + width="250"> <text type="string" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index cd46ccb0bc..2466480d16 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -3,12 +3,12 @@ background_visible="true" follows="left|top|right|bottom" height="660" - label="Me" + label="Profile" layout="topleft" left="0" name="panel_target_profile" top="0" - width="305"> + width="250"> <button layout="topleft" name="back" @@ -17,6 +17,7 @@ width="20" height="20" label="" + tab_stop="false" follows="top|left" image_selected="navbar_bg_button.tga" image_unselected="navbar_bg_button.tga" diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 096b60adb1..73b06a3e41 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -20,8 +20,6 @@ <panel name="panel_home" filename="panel_sidetray_home_tab.xml" - width="355" - height="465" label="home" border="true" /> @@ -37,15 +35,22 @@ background_visible="true" bg_opaque_color="0.5 0.5 0.5 1.0" > + <panel_container + name="panel_container" + > <panel class="panel_people" name="panel_people" filename="panel_people.xml" - width="280" - height="465" - label="People" border="true" /> + <panel + class="panel_profile_view" + name="panel_profile_view" + filename="panel_profile_view.xml" + border="true" + /> + </panel_container> </sidetray_tab> <!-- *TODO Vadim: isn't the sidetray_tab "label" attribute redundant since we have "tab_title" ? --> <sidetray_tab diff --git a/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml b/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml new file mode 100644 index 0000000000..445c9cc288 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Width and height of this panel should be synchronized with "panel_modes" in the floater_moveview.xml--> +<panel + height="25" + layout="topleft" + name="panel_stand_stop_flying" + mouse_opaque="false" + visible="false" + width="115"> + <button + follows="left|bottom" + height="20" + label="Stand" + layout="topleft" + name="stand_btn" + tool_tip="Click here to stand up." + top="2" + width="115" /> + <button + follows="left|bottom" + height="20" + label="Stop Flying" + layout="topleft" + name="stop_fly_btn" + tool_tip="Stop Flying" + top="2" + width="115" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index e5665b0194..c64316e305 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -335,7 +335,7 @@ <string name="GraphicsQualityHigh">High</string> <!-- mouselook --> - <string name="LeaveMouselook">Press ESC to leave Mouselook.</string> + <string name="LeaveMouselook">Press ESC to return to World View</string> <!-- inventory --> <string name="InventoryNoMatchingItems">No matching items found in inventory.</string> diff --git a/indra/newview/skins/default/xui/en/widgets/split_button.xml b/indra/newview/skins/default/xui/en/widgets/split_button.xml new file mode 100644 index 0000000000..b0367b599b --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/split_button.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<split_button + font="SansSerifSmall" + arrow_position="left" + follows="right|top"> + <split_button.arrow_button + name="Arrow Button" + label="" + font="SansSerifSmall" + scale_image="true" + image_selected="camera_presets/camera_presets_arrow.png" + image_unselected="camera_presets/camera_presets_arrow.png" + image_disabled_selected="camera_presets/camera_presets_arrow.png" + image_disabled="camera_presets/camera_presets_arrow.png" + width="10"/> + <split_button.items_panel + background_visible="true" + border="true" + bg_alpha_color="1 1 1 1" + bg_opaq_color="1 1 1 1" + layout="topleft" + name="item_buttons" + /> +</split_button> -- GitLab