From e6240500a95559f6df4d6b711d0c01c706e13e58 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Fri, 31 Jul 2009 02:23:32 +0000 Subject: [PATCH 1/9] Minor change to protect against odd case where mArrowImage was NULL (unclear why it's happening, but the extra checks are not a bad thing). --- indra/llui/llcombobox.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 51f9d6bd18..45423920d6 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -117,6 +117,8 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) mArrowImage = button_params.image_unselected; mButton = LLUICtrlFactory::create(button_params); + + if(mAllowTextEntry) { //redo to compensate for button hack that leaves space for a character @@ -430,7 +432,8 @@ void LLComboBox::setButtonVisible(BOOL visible) LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); if (visible) { - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -472,14 +475,15 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p) LLRect rect = getLocalRect(); if (mAllowTextEntry) { + S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; S32 shadow_size = drop_shadow_button; - mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size, + mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); mButton->setTabStop(FALSE); mButton->setHAlign(LLFontGL::HCENTER); LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; // clear label on button std::string cur_label = mButton->getLabelSelected(); LLLineEditor::Params params = p.combo_editor; From 3c85899ee0db4a90d03ec687e514a31c1befe34e Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 31 Jul 2009 17:51:39 +0000 Subject: [PATCH 2/9] for DEV-33077 partially: don't call analyzeAlpha for media textures. --- indra/newview/llviewertexture.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 533889b2f7..6ea1522b47 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1940,6 +1940,8 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL { generateGLTexture() ; } + mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; + mIsPlaying = FALSE ; } @@ -1952,6 +1954,7 @@ void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) getLastReferencedTimer()->reset() ; generateGLTexture() ; + mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; } void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) From db5cda26676f376f18816013c0c5e3fbad5b20d0 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Mon, 3 Aug 2009 22:25:48 +0000 Subject: [PATCH 3/9] 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 | 288 +++++++++- 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, 3011 insertions(+), 565 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 @@ Value 5 + ToastOpaqueTime + + Comment + Width of notification messages + Persist + 1 + Type + S32 + Value + 4 + StartUpToastTime Comment @@ -4769,7 +4780,7 @@ Type S32 Value - 10 + 5 ToastMargin @@ -6763,6 +6774,17 @@ 0 ShowCrosshairs + + Comment + Show Coordinates in Location Input Field + Persist + 1 + Type + Boolean + Value + 0 + + ShowCoordinatesOption Comment Display crosshairs when in mouselook mode @@ -9623,5 +9645,16 @@ Value 0 + GroupTeleportMembersLimit + + Comment + Max number of members of group to offer teleport + Persist + 1 + Type + U32 + Value + 100 + 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("moveview"); + LLFloaterMove *floater_move = LLFloaterReg::findTypedInstance("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("camera"); - if(camera_instance) + LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance("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("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 selectedItems = getAllSelected(); + std::vector::const_iterator it = selectedItems.begin(); + + for (; it != selectedItems.end(); ++it) + { + (*it)->setSelected(FALSE); + } + return TRUE; + } + return LLScrollListCtrl::handleMouseDown(x, y, mask); +} + std::vector 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& 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 ("stand", TRUE, FALSE); - if (mStandUpBtn) - { - mStandUpBtn->setCommitCallback(boost::bind(&LLBottomTray::onCommitStandUp, this, _1)); - } - + LLSplitButton* presets = getChild("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 // -LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLFloater(val) + +/*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("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("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), + 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("cam_rotate_stick"); + mRotate = getChild(ORBIT); mZoom = getChild("zoom"); - mTrack = getChild("cam_track_stick"); + mTrack = getChild(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(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::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; +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(); -public: - - LLJoystickCameraRotate* mRotate; - LLJoystickCameraZoom* mZoom; - LLJoystickCameraTrack* mTrack; + + 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 mMode2Button; + std::map 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 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 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 max_items("LocationHistoryMaxSize", 100); + std::vector::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("backward btn"); mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mSlideLeftButton = getChild("slide left btn"); - mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - - mSlideRightButton = getChild("slide right btn"); - mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnLeftButton = getChild("turn left btn"); mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnLeftButton->setHeldDownCallback( turnLeft, NULL ); - + mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this)); mTurnRightButton = getChild("turn right btn"); mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY); - mTurnRightButton->setHeldDownCallback( turnRight, NULL ); + mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this)); mMoveUpButton = getChild("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("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("stop_fly_btn"); + + mModeActionsPanel = getChild("panel_modes"); + + LLButton* btn; + btn = getChild("mode_walk_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onWalkButtonClick, this)); + + btn = getChild("mode_run_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onRunButtonClick, this)); + + btn = getChild("mode_fly_btn"); + btn->setCommitCallback(boost::bind(&LLFloaterMove::onFlyButtonClick, this)); + + btn = getChild("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("moveview"); - if(!instance) return; - - F32 time = instance->mTurnLeftButton->getHeldDownTime(); + LLFloaterMove* instance = LLFloaterReg::findTypedInstance("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("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("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("mode_walk_btn"); + mModeControlButtonMap[MM_RUN] = getChild("mode_run_btn"); + mModeControlButtonMap[MM_FLY] = getChild("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(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("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("stand_btn"); + mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this)); + mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE)); + + mStopFlyingButton = getChild("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(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 control_tooltip_map_t; + typedef std::map mode_control_tooltip_map_t; + mode_control_tooltip_map_t mModeControlTooltipsMap; + + typedef std::map 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 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("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("1st_life_pic",TRUE,FALSE); + pic = getChild("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& 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 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("create_landmark_btn"); + mCreateLandmarkBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, LLUUID())); + + mFolderMenuBtn = getChild("folder_menu_btn"); + mFolderMenuBtn->setClickedCallback(boost::bind(&LLPanelPlaces::showLandmarkFoldersMenu, this)); + mTeleportBtn = getChild("teleport_btn"); mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this)); mShowOnMapBtn = getChild("map_btn"); mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this)); - //mShareBtn = getChild("share_btn"); + mShareBtn = getChild("share_btn"); //mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this)); mOverflowBtn = getChild("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(); } +} - // Enable overflow button only when showing the information about agent's current location. - mOverflowBtn->setEnabled(is_place_info_visible && is_agent_place_info_visible); +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(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); + + 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(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 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 mLandmarkFoldersMenuHandle; + + typedef std::vector 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 t_panel_profile(PANEL_P static LLRegisterPanelClassWrapper 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 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(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::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(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(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 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(); + }; + + /** + * 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 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 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::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(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::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(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(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 + { + static void declareValues(); + }; + + struct ItemParams : public LLInitParam::Block + { + ItemParams(); + }; + + struct Params : public LLInitParam::Block + { + Optional arrow_position; + Optional arrow_button; + Optional items_panel; + Multiple 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 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); LLFloaterReg::add("contacts", "floater_my_friends.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("first_time_tip", "floater_first_time_tip.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -127,7 +128,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("me_profile", "floater_me.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -144,7 +144,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("preview_url", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("pref_voicedevicesettings", "floater_device_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("preview_avatar", "floater_profile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "preview"); LLFloaterReg::add("preview_landmark", "floater_preview_existing_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build, "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 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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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 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 zcmai$3p88V8pp--R){ z5%s9HA?jVC^fC1oEki0VlvINtsaGS9d#t(Zt~=|_TKAl@&tB(S`|R`Wv;V*E`);3h zb5vE*caIeAy2cHfJd1CkQ9&q*c_Wm(6R2m02 z<}()$DyF3-%cZe`549&+T3VRTua)V5!5ViRR=V_3g1fRItvn(+h85n-|2jkVIilm5 zJI-QJ{At$@+Su4!lax8)_l>&eZQ8`*gbcffS%azt_+kFyVl3?YTB=lJ$~V7E#S+?L z7rEst;D3e{G!Co^SVfj{91tqM|ZmB>(;PP83f|OUq=PZMG*Fi?a0$ z2??o%Iqp>_TSj*Zcv!Xf#?nSJPponfdkI!xO}5 zTj&IlNc8Q?ymKdv*YkYN3(N4vN?AU%QrUuAa3 zJCQlULNR?#+3CO!&ft61=;m_-z4&Q$GCY2W!{O-e+ST*;o1i+}?0Q*Q*%$1D{h!WF z7bh;%!cwFwj1b3yw6wHb(rSXD+0nNTTK5Dv*_v5eD83Hl&WSz*;!%Y2IH5fji#@1| zr%)&^?r`BRun?(ug-{;Ym3>e%lRs49k}yMxjrbr0>*&BxgNU^vYq=!)E*>8m7IsP? z5In7}cBL(PlEKw!blhzYwcs$NC^-C8nyyWqCnXO7a(`;>Iq(7)u zFrK_Ia6EQl`KBruH|%QB0{l%(o6zCod%lWE+XS2Kck9j1nDKTF0)enFf;J`bdNnL8 zENBf4f4sWzZZh&iV`HOr)U*>bYI8A!`!5aDw&mZBAx$w0HGEd)G+LDYSNoed`~`+h z!%|A1x4iTozz_h~g#2Q14_nsBKw!msD>GI4EgL+n6(4bi9o1|k&*;U7Qx5SzjtuZ=fDr1-rjlHx`+ocMQh_J0c)ICGC-n8B>KtAt4z&$9Xe(9$i4az{c?+Y zb7xlzgNB5pLRxHU*9TnB6YMHoqudCW`#LEUi0YDJ`F9cPyw@%*%n{Fy1=2x zWU{PBq+!NoCY_R|Wyd)0G*O6Yw-he&`&wzVoF+qKV>bz_$t0kC{`KqEz8lV>+dKD% zu>go>i{`XE9a^PY&MGP2zDdUm0rzOFtya8v_q_X0&)>Rv)6c`>@JzCXhK8<=jx*E7 zpJiN5(sD8U{8lqlxjV<*nxCD$-LcFgHa0eKZnT;>U0Ix95JLNtF4!vO>eV`!o;B{n zi4!NX-(Iv%mOR&wXElX43GRX|&Jk?HpMS(>WyM8Cz6%czr&6i(=UHE^-bAT%CoaAS zLU9{Ha#&2}?z;|%!-pq>k5~nDk$h{atAWq-_BzL2ziy?Ar%@<(d>1ER01T7-)n6Z`0$q-_NZbQWU-X zM(r#C4>?Zs*qq<1tjl5?m(w6w<`3VVFxm(G(r6CqF@<{hv|cbRxK5j&pO3Fp2gKe0 zQ&I%^czeeW79%1;L(!*q86JWHS|-5Z@V3Xo~fxRR9{zTr%}(?*q8+jYRA2Cw} z;>UDpws}1%A8kt%1agNf-CYO<1_nbBKAxU?QDRY_iC08@vNR!See#x$w)VT0=$U0^ zXbpw~;nHmb$pO=%Z{TODBdz=0S8=^cT4< zAQYfj@gp{GuVOH3OH0oJYYW^-R(WwxmseSs$`^`|W0BBn=Hjs+a(q}=KM4&qypo#ksl*)XqhexSo-Y9m1|yCg`z#b*i;ani8*fjF)(vXE ze&tTyUTAcZZo=n1T~opaRZCOT34o<6-OF^zJgeDc$}EgVrAEAkf06=OYv7B$I9+ z%*+VyCGy@p!-$B8>p&8{@v7v_ zk57hgnoRtjPXKFX1B!Tfx*GsXUZ?tNxO{yIPkr*_nwwkp<~&!gN(9a0S8zET24kkP z(?Ls9)5_4WFC!x(nO~95W-#&_H~`ChAP-el8DY3>VgHgSz1vBu-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_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 zcmZvc3pCVeAIE2=L~_rjajB6(F>K5rkz0v>h-OVSI}NRv!K}-!dm*o~))M2dnt;*VGzNDxquc zskaN5^Ahjz$=D8HZ?Ni$bl&G|)Nw zU3+RnFjE7g-3HtJED?jnWAmnl14+oim&NkZkMgodNHk>7|1FqOf*G&3YO3gllidtg z;O0zy`@x;FW(QquzKWZZ{qj8V`D^fzL9@qKlOJTLx}fvEyx=}TSOYvC_1(yJdwT1M)>zGeS*qH{@R>t|Gix~`Fu!*_x z`UdUvI+@arUbljFJ$)6ap@F~;rQXsn@ zH(n1H+#XUipvIZ#-vCn`XwQAqS$ac@mVT~Eo)6Z}@p;%hJ&LN}GCIsdydb*5S~FGW z__*A?jUEcJSgxtoq27nwJ~DHt(sR{=BB;NTE6-q5QtL#Xs}&x+!_=P}Q0^noR_htg zR1=<|l#4dSt`mpjcuS$9{*ZyVR1+ydyf87aVhBhae>Z_wXWyt~jVix2gkne)s}4A; zaalL1X@|1i6%LraOsZ~wz3_I^@dmT!Lj5Q(O+y1yz2h+vgFu-5xN>6g2c|lbL6u1o zm*p-Ba3v)_6|>OvTXA_W>NU8&=D$?F7+q$fU~u^7jGS%%zU$GiZx&;6I(&&D^&k}_ z5r^EBpd^>fL2H$iTwGuXgoZ|18f@!U)aLfjg=uD2S3qHibgLDG?VY2cB=GU zNK78Q8;UdQzv~|u=(|OW&X0fdhbzE;)^tWPkauifNl6L*aJgVvHYUNyWU>OZ!J+81 zZD`cACOtuM{V$Dg$M3l2PGNq@N&7R9C@QFEB1Kj@r8N4K+A_J^uL}wa?#{Ab+*C6- z%pf$K4hs)I!ICxdc$dZYHa0dTMMcBo<3)&nxumM)vLo9qWNVR3l)WE`)Fc*Dx~IN# zuRR6e&2I3UNp0H78BoO?JXkfx4)g-&L_Bs@)^;0PTd{>c3YBD#siLAX0~w8l1Gn(p zBzYZLI&qH%GS=5tMx(bf9D58?Qc@P*Cx_E$U+vdk<%Q%p`zc+Zmu2-#J(0+fJW&*$ zdEGww-JR{*u3-E1balNwJTk4G6uF?zWBRR!Dvn^^qn#XbltFU>fiTfR%?s#AtPaIB z>e)pO_^ScR8E!uv+s93quL%0ND1PpD<~2P#K6LK~F7ajb*@eV&msaM=chaTOuyTil z+y%v_?Cg*nt23-~R-m`Ldq#fn9>>IkEf}q=-N2?ffOv7b-$XPM^qm2^UN2cLzV;#Y znQL`zexe)}H=LY+StPn6*8aNZkZyQP# zj@Bg|t}u5*u7A&7dBv^?8L3kkuJd{j7Vr;pf1d_P|6%YGq3Y_{LK``ONMx3j=*Gpz zo9U~W=X(yjnA2}wzQ~IbIT`iE#>bbq)lZAuO6OC^Z)iQa2I7%gkM4=O>7Dem7|ORo zTQDa=XtFC?la5h*y!!&!$3W`oVRbCe9Tc`j*@4~{F4O{OEn_`8I1@zfNIWHt{krK4 z`!odbEw7smQ+pa38vIZi!_v|ExV5(tHaJ{pXsD-TsFJFJ@8#aVZwyce%Zjn8^Y7ME z%a2?-4W3w4?JLMz@0&J_&dJRU7jhz$w<2_r$Wvr;d4*$AO;6rlnoQ8F;P8e_5lUKp zbjHUNoCzVx$>&P#q6$UxV{*w*cC$}^ZTiyEQt$5C3q84g61nufHf&$jR2$R?J1irhE5p$WX)%wZ*ryB&?HDBoqK2D1iCF@v{>lU>{mXdB<$GzOJq{ z=p7N!41KGZ!dv(QUy(>ObaAHoUM-D07Q@cQrZ_)8AM64HTFJK)CYx$K@}6=e8@ikb zS#Q3Pil8Os&NxTVOsdb#Rm*tv&1C1LGZ3#hZ^JI3jh&qyP}kO$@L;;Lv-3C@78zNW zejUy>^Bf7>k2&5QTYcxMuytuD2wo;u_ynZS$kJBw-8h?1`Sl`%=X-~We{$ya(vR>z 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@w;Rt~fn4Y7LtC94b{hp`qPaT~~_O zc_9m-plzAo!$TLp(~2T~@M;#H61xg&f?OS^;beAD#+0Rs!(74G5csQ(lW?$mI)69e zqn5dJr_{32xZ?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!mcB5Da0>*Vxx^ZVA?yPD>|yU)?PX87W>h#Yd-~<`_)PLf=V+ep&6&wFU^C^VTm4Tdy_JA+*jr3;%e<0^>MQVUsgkWI^OJ` zspDqph*@*dj9}PB_`o6XE=Z~OJE_QQvp-O+@+|b$bJOL|Otit2Ps_oY(#V$b$D`Uv9WnZw4P6z_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+O00sT4gH|LzWbLZasyW{S97$&PC z3jhFMcqa!BNof4#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%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|UoEUn40_@0DSd|7z1Mr$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{XR^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-{O5zW=LFg_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>&+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 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 + width="105"> Rotate Camera Around Focus @@ -21,50 +22,121 @@ name="move_tooltip"> Move Camera Up and Down, Left and Right - - + + + + + - + left="0" + top_pad="1" + name="buttons" + width="105"> + + + + + 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 @@ + + + + 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 @@ - + + + + + + + + + + + + + /> + + No groups - 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 @@ - - Landmarks - - - Teleport History - + + + top="3" + width="270" /> + width="115" />