From e1d8dac25a93db837c780428a23f81cbf9109270 Mon Sep 17 00:00:00 2001 From: Melinda Green <melinda@lindenlab.com> Date: Mon, 15 Dec 2008 21:21:19 +0000 Subject: [PATCH] svn merge -r105329:105903 svn+ssh://svn/svn/linden/branches/featurettes/featurettes-batch4-merge Resolving QAR-1051 Merge featurettes batch #4 --- doc/contributions.txt | 8 +- indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/llchat.h | 4 +- indra/llcommon/llcursortypes.cpp | 89 +++++ indra/llcommon/llcursortypes.h | 81 ++++ indra/llmath/llcamera.cpp | 57 ++- indra/llmath/llcamera.h | 22 +- indra/llmath/lloctree.h | 4 +- indra/llmessage/llnamevalue.cpp | 1 - indra/llrender/llcubemap.cpp | 1 - indra/llui/CMakeLists.txt | 2 + indra/llui/llbutton.cpp | 8 +- indra/llui/llfloater.h | 2 +- indra/llui/llpanel.cpp | 4 +- indra/llui/llpanel.h | 2 +- indra/llui/llprogressbar.cpp | 180 +++++++++ indra/llui/llprogressbar.h | 75 ++++ indra/llui/llscrollbar.cpp | 7 +- indra/llui/lltextbox.cpp | 110 ++---- indra/llui/lltextbox.h | 10 +- indra/llui/lltexteditor.cpp | 12 +- indra/llui/lltexteditor.h | 4 +- indra/llui/llui.cpp | 12 + indra/llui/llui.h | 1 + indra/llui/lluictrl.cpp | 13 - indra/llui/lluictrl.h | 4 +- indra/llui/llview.cpp | 18 +- indra/llui/llview.h | 3 + indra/llvfs/lldir.cpp | 2 +- indra/llwindow/llwindow.h | 43 +- indra/llxml/llcontrol.cpp | 4 +- indra/newview/CMakeLists.txt | 16 + indra/newview/app_settings/settings.xml | 334 ++++++++++++++-- indra/newview/llagent.cpp | 56 ++- indra/newview/llagent.h | 1 + indra/newview/llappviewerlinux.cpp | 6 +- indra/newview/llappviewermacosx.cpp | 20 +- indra/newview/llassetuploadresponders.cpp | 57 ++- indra/newview/llchatbar.cpp | 5 +- indra/newview/llcolorswatch.cpp | 22 +- indra/newview/llcolorswatch.h | 2 + indra/newview/llcommandhandler.cpp | 38 +- indra/newview/llcommandhandler.h | 36 +- indra/newview/lldynamictexture.h | 1 - indra/newview/llfilepicker.cpp | 16 +- indra/newview/llfilepicker.h | 5 + indra/newview/llfloaterabout.cpp | 4 +- indra/newview/llfloateranimpreview.cpp | 3 +- indra/newview/llfloaterbulkpermission.cpp | 366 ++++++++++++++++++ indra/newview/llfloaterbulkpermission.h | 107 +++++ indra/newview/llfloaterbuyland.cpp | 24 +- indra/newview/llfloaterchat.cpp | 18 +- indra/newview/llfloaterevent.cpp | 7 +- indra/newview/llfloaterhandler.cpp | 77 ++++ indra/newview/llfloaterhandler.h | 44 +++ indra/newview/llfloaterland.cpp | 50 ++- indra/newview/llfloaternamedesc.cpp | 4 +- indra/newview/llfloaterparcel.cpp | 7 +- indra/newview/llfloaterperms.cpp | 157 ++++++++ indra/newview/llfloaterperms.h | 70 ++++ indra/newview/llfloaterpreference.cpp | 14 +- indra/newview/llfloatersnapshot.cpp | 26 +- indra/newview/llfloatertelehub.cpp | 1 - indra/newview/llfloatertools.cpp | 115 ++---- indra/newview/llfloatertools.h | 6 +- indra/newview/llfloaterworldmap.cpp | 2 - indra/newview/llimpanel.cpp | 4 +- indra/newview/llloginhandler.cpp | 227 +++++++++++ indra/newview/llloginhandler.h | 63 +++ indra/newview/llnetmap.cpp | 36 +- indra/newview/llnetmap.h | 6 + indra/newview/llpanelavatar.cpp | 8 +- indra/newview/llpanelclassified.cpp | 7 +- indra/newview/llpanelcontents.cpp | 28 +- indra/newview/llpanelcontents.h | 1 + indra/newview/llpanelface.cpp | 4 +- indra/newview/llpanelgrouproles.cpp | 17 +- indra/newview/llpanelland.cpp | 15 +- indra/newview/llpanelland.h | 3 + indra/newview/llpanellogin.cpp | 199 +--------- indra/newview/llpanellogin.h | 36 +- indra/newview/llpanelobject.cpp | 26 +- indra/newview/llpanelpermissions.cpp | 30 -- indra/newview/llpanelplace.cpp | 1 + indra/newview/llprogressview.cpp | 265 +++---------- indra/newview/llprogressview.h | 9 +- indra/newview/llstartup.cpp | 44 ++- indra/newview/llstatusbar.cpp | 2 +- indra/newview/llstylemap.cpp | 37 +- indra/newview/llstylemap.h | 3 +- indra/newview/lltexturectrl.cpp | 30 +- indra/newview/lltexturectrl.h | 6 +- indra/newview/llurldispatcher.cpp | 78 ++-- indra/newview/llurldispatcher.h | 14 +- indra/newview/llviewercamera.cpp | 39 +- indra/newview/llviewercamera.h | 8 +- indra/newview/llviewermenu.cpp | 168 ++++---- indra/newview/llviewermenufile.cpp | 35 +- indra/newview/llviewermenufile.h | 20 +- indra/newview/llviewermessage.cpp | 50 ++- indra/newview/llviewerwindow.cpp | 5 +- .../default/textures/default_land_picture.j2c | Bin 0 -> 24492 bytes .../textures/default_profile_picture.j2c | Bin 0 -> 6128 bytes .../skins/default/textures/locked_image.j2c | Bin 0 -> 6140 bytes .../skins/default/textures/textures.xml | 4 + 105 files changed, 2884 insertions(+), 1146 deletions(-) create mode 100644 indra/llcommon/llcursortypes.cpp create mode 100644 indra/llcommon/llcursortypes.h create mode 100644 indra/llui/llprogressbar.cpp create mode 100644 indra/llui/llprogressbar.h create mode 100644 indra/newview/llfloaterbulkpermission.cpp create mode 100644 indra/newview/llfloaterbulkpermission.h create mode 100644 indra/newview/llfloaterhandler.cpp create mode 100644 indra/newview/llfloaterhandler.h create mode 100644 indra/newview/llfloaterperms.cpp create mode 100644 indra/newview/llfloaterperms.h create mode 100644 indra/newview/llloginhandler.cpp create mode 100644 indra/newview/llloginhandler.h create mode 100644 indra/newview/skins/default/textures/default_land_picture.j2c create mode 100644 indra/newview/skins/default/textures/default_profile_picture.j2c create mode 100644 indra/newview/skins/default/textures/locked_image.j2c diff --git a/doc/contributions.txt b/doc/contributions.txt index 842dc3ac9e8..ad0018bd7ba 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -13,7 +13,7 @@ Able Whitman Adam Marker VWR-2755 Aimee Trescothick - VWR-3336 + VWR-3336 VWR-3903 VWR-4083 VWR-6348 @@ -26,6 +26,7 @@ Aimee Trescothick VWR-8341 VWR-8482 VWR-9255 + VWR-1813 Alejandro Rosenthal VWR-1184 Alissa Sabre @@ -99,6 +100,7 @@ Carjay McGinnis VWR-6154 Catherine Pfeffer VWR-1282 + VWR-8624 Dale Glass VWR-120 VWR-560 @@ -225,8 +227,11 @@ Matthew Dowd VWR-1761 McCabe Maxsted VWR-1318 + VWR-4065 + VWR-7827 VWR-7877 VWR-7893 + VWR-8080 VWR-8689 Michelle2 Zenovka VWR-2652 @@ -237,6 +242,7 @@ Michelle2 Zenovka VWR-4331 VWR-4506 VWR-4981 + VWR-5082 VWR-5659 VWR-7831 VWR-8889 diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 4001e1f0c56..3f14be6e185 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -20,6 +20,7 @@ set(llcommon_SOURCE_FILES llcommon.cpp llcrc.cpp llcriticaldamp.cpp + llcursortypes.cpp lldate.cpp llerror.cpp llerrorthread.cpp @@ -90,6 +91,7 @@ set(llcommon_HEADER_FILES llcommon.h llcrc.h llcriticaldamp.h + llcursortypes.h lldarray.h lldarrayptr.h lldate.h diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h index b6f84b25b57..29f6b27e22c 100644 --- a/indra/llcommon/llchat.h +++ b/indra/llcommon/llchat.h @@ -77,7 +77,8 @@ class LLChat mAudible(CHAT_AUDIBLE_FULLY), mMuted(FALSE), mTime(0.0), - mPosAgent() + mPosAgent(), + mURL() { } std::string mText; // UTF-8 line of text @@ -89,6 +90,7 @@ class LLChat BOOL mMuted; // pass muted chat to maintain list of chatters F64 mTime; // viewer only, seconds from viewer start LLVector3 mPosAgent; + std::string mURL; }; #endif diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp new file mode 100644 index 00000000000..9f1a899dae0 --- /dev/null +++ b/indra/llcommon/llcursortypes.cpp @@ -0,0 +1,89 @@ +/** + * @file llcursortypes.cpp + * @brief Cursor types and lookup of types from a string + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llcursortypes.h" + +ECursorType getCursorFromString(const std::string& cursor_string) +{ + static std::map<std::string,U32> cursor_string_table; + if (cursor_string_table.empty()) + { + cursor_string_table["UI_CURSOR_ARROW"] = UI_CURSOR_ARROW; + cursor_string_table["UI_CURSOR_WAIT"] = UI_CURSOR_WAIT; + cursor_string_table["UI_CURSOR_HAND"] = UI_CURSOR_HAND; + cursor_string_table["UI_CURSOR_IBEAM"] = UI_CURSOR_IBEAM; + cursor_string_table["UI_CURSOR_CROSS"] = UI_CURSOR_CROSS; + cursor_string_table["UI_CURSOR_SIZENWSE"] = UI_CURSOR_SIZENWSE; + cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW; + cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE; + cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS; + cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO; + cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING; + cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB; + cursor_string_table["UI_CURSOR_TOOLLAND"] = UI_CURSOR_TOOLLAND; + cursor_string_table["UI_CURSOR_TOOLFOCUS"] = UI_CURSOR_TOOLFOCUS; + cursor_string_table["UI_CURSOR_TOOLCREATE"] = UI_CURSOR_TOOLCREATE; + cursor_string_table["UI_CURSOR_ARROWDRAG"] = UI_CURSOR_ARROWDRAG; + cursor_string_table["UI_CURSOR_ARROWCOPY"] = UI_CURSOR_ARROWCOPY; + cursor_string_table["UI_CURSOR_ARROWDRAGMULTI"] = UI_CURSOR_ARROWDRAGMULTI; + cursor_string_table["UI_CURSOR_ARROWCOPYMULTI"] = UI_CURSOR_ARROWCOPYMULTI; + cursor_string_table["UI_CURSOR_NOLOCKED"] = UI_CURSOR_NOLOCKED; + cursor_string_table["UI_CURSOR_ARROWLOCKED"] = UI_CURSOR_ARROWLOCKED; + cursor_string_table["UI_CURSOR_GRABLOCKED"] = UI_CURSOR_GRABLOCKED; + cursor_string_table["UI_CURSOR_TOOLTRANSLATE"] = UI_CURSOR_TOOLTRANSLATE; + cursor_string_table["UI_CURSOR_TOOLROTATE"] = UI_CURSOR_TOOLROTATE; + cursor_string_table["UI_CURSOR_TOOLSCALE"] = UI_CURSOR_TOOLSCALE; + cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA; + cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN; + cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN; + cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3; + cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT; + cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY; + cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY; + cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN; + cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY; + cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE; + cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN; + cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE; + } + + std::map<std::string,U32>::const_iterator iter = cursor_string_table.find(cursor_string); + + if (iter != cursor_string_table.end()) + { + return (ECursorType)iter->second; + } + + return UI_CURSOR_ARROW; +} + + + diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h new file mode 100644 index 00000000000..a9f23060c7c --- /dev/null +++ b/indra/llcommon/llcursortypes.h @@ -0,0 +1,81 @@ +/** + * @file llcursortypes.h + * @brief Cursor types + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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_LLCURSORTYPES_H +#define LL_LLCURSORTYPES_H + +#include "linden_common.h" + +// If you add types here, add them in LLCursor::getCursorFromString +enum ECursorType { + UI_CURSOR_ARROW, + UI_CURSOR_WAIT, + UI_CURSOR_HAND, + UI_CURSOR_IBEAM, + UI_CURSOR_CROSS, + UI_CURSOR_SIZENWSE, + UI_CURSOR_SIZENESW, + UI_CURSOR_SIZEWE, + UI_CURSOR_SIZENS, + UI_CURSOR_NO, + UI_CURSOR_WORKING, + UI_CURSOR_TOOLGRAB, + UI_CURSOR_TOOLLAND, + UI_CURSOR_TOOLFOCUS, + UI_CURSOR_TOOLCREATE, + UI_CURSOR_ARROWDRAG, + UI_CURSOR_ARROWCOPY, // drag with copy + UI_CURSOR_ARROWDRAGMULTI, + UI_CURSOR_ARROWCOPYMULTI, // drag with copy + UI_CURSOR_NOLOCKED, + UI_CURSOR_ARROWLOCKED, + UI_CURSOR_GRABLOCKED, + UI_CURSOR_TOOLTRANSLATE, + UI_CURSOR_TOOLROTATE, + UI_CURSOR_TOOLSCALE, + UI_CURSOR_TOOLCAMERA, + UI_CURSOR_TOOLPAN, + UI_CURSOR_TOOLZOOMIN, + UI_CURSOR_TOOLPICKOBJECT3, + UI_CURSOR_TOOLSIT, + UI_CURSOR_TOOLBUY, + UI_CURSOR_TOOLPAY, + UI_CURSOR_TOOLOPEN, + UI_CURSOR_TOOLPLAY, + UI_CURSOR_TOOLPAUSE, + UI_CURSOR_TOOLMEDIAOPEN, + UI_CURSOR_PIPETTE, + UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor) +}; + +ECursorType getCursorFromString(const std::string& cursor_string); + +#endif // LL_LLCURSORTYPES_H diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 3b9ba9d0f76..6c28013af8c 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -50,33 +50,38 @@ LLCamera::LLCamera() : } -LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : +LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : LLCoordFrame(), - mView(z_field_of_view), - mAspect(aspect_ratio), mViewHeightInPixels(view_height_in_pixels), - mNearPlane(near_plane), - mFarPlane(far_plane), mFixedDistance(-1.f), mPlaneCount(6) { - if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } - else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } + mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); + mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); + if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE; + mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); - if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } - else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } - - if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } - else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } + setView(vertical_fov_rads); +} - if (mFarPlane < 0) { mFarPlane = DEFAULT_FAR_PLANE; } - else if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } - else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } - calculateFrustumPlanes(); -} +// ---------------- LLCamera::getFoo() member functions ---------------- +F32 LLCamera::getMinView() const +{ + // minimum vertical fov needs to be constrained in narrow windows. + return mAspect > 1 + ? MIN_FIELD_OF_VIEW // wide views + : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views +} +F32 LLCamera::getMaxView() const +{ + // maximum vertical fov needs to be constrained in wide windows. + return mAspect > 1 + ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views + : MAX_FIELD_OF_VIEW; // narrow views +} // ---------------- LLCamera::setFoo() member functions ---------------- @@ -92,11 +97,9 @@ void LLCamera::disableUserClipPlane() mPlaneCount = 6; } -void LLCamera::setView(F32 field_of_view) +void LLCamera::setView(F32 vertical_fov_rads) { - mView = field_of_view; - if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } - else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } + mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); calculateFrustumPlanes(); } @@ -110,27 +113,21 @@ void LLCamera::setViewHeightInPixels(S32 height) void LLCamera::setAspect(F32 aspect_ratio) { - mAspect = aspect_ratio; - if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } - else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } + mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); calculateFrustumPlanes(); } void LLCamera::setNear(F32 near_plane) { - mNearPlane = near_plane; - if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } - else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } + mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); calculateFrustumPlanes(); } void LLCamera::setFar(F32 far_plane) { - mFarPlane = far_plane; - if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } - else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } + mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); calculateFrustumPlanes(); } diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 82c712e5e7a..094e59fd0a9 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -42,17 +42,19 @@ const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; const F32 DEFAULT_NEAR_PLANE = 0.25f; const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions -const F32 MAX_FIELD_OF_VIEW = F_PI; const F32 MAX_ASPECT_RATIO = 50.0f; const F32 MAX_NEAR_PLANE = 10.f; const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. const F32 MAX_FAR_CLIP = 512.0f; -const F32 MIN_FIELD_OF_VIEW = 0.1f; const F32 MIN_ASPECT_RATIO = 0.02f; const F32 MIN_NEAR_PLANE = 0.1f; const F32 MIN_FAR_PLANE = 0.2f; +// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio. +static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD; +static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; + static const LLVector3 X_AXIS(1.f,0.f,0.f); static const LLVector3 Y_AXIS(0.f,1.f,0.f); static const LLVector3 Z_AXIS(0.f,0.f,1.f); @@ -101,7 +103,7 @@ class LLCamera HORIZ_PLANE_ALL_MASK = 0x3 }; -protected: +private: F32 mView; // angle between top and bottom frustum planes in radians. F32 mAspect; // width/height S32 mViewHeightInPixels; // for ViewHeightInPixels() only @@ -117,12 +119,12 @@ class LLCamera struct frustum_plane { - frustum_plane() : mask(0) {} + frustum_plane() : mask(0) {} LLPlane p; U8 mask; }; frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP - + U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera) @@ -132,12 +134,13 @@ class LLCamera public: LLCamera(); - LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); + LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); + virtual ~LLCamera(){} // no-op virtual destructor void setUserClipPlane(LLPlane plane); void disableUserClipPlane(); U8 calcPlaneMask(const LLPlane& plane); - void setView(F32 new_view); + virtual void setView(F32 vertical_fov_rads); void setViewHeightInPixels(S32 height); void setAspect(F32 new_aspect); void setNear(F32 new_near); @@ -148,6 +151,11 @@ class LLCamera F32 getAspect() const { return mAspect; } // width / height F32 getNear() const { return mNearPlane; } // meters F32 getFar() const { return mFarPlane; } // meters + + // The values returned by the min/max view getters depend upon the aspect ratio + // at the time they are called and therefore should not be cached. + F32 getMinView() const; + F32 getMaxView() const; F32 getYaw() const { diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 25b7100eb7a..5a1efdbe28f 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -38,9 +38,9 @@ #include <set> #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG -#define OCT_ERRS LL_WARNS("OctreeErrors") -#else #define OCT_ERRS LL_ERRS("OctreeErrors") +#else +#define OCT_ERRS LL_WARNS("OctreeErrors") #endif #define LL_OCTREE_PARANOIA_CHECK 0 diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp index 58755871865..33c19dc57cd 100644 --- a/indra/llmessage/llnamevalue.cpp +++ b/indra/llmessage/llnamevalue.cpp @@ -38,7 +38,6 @@ #include "u64.h" #include "llstring.h" -#include "llcamera.h" #include "string_table.h" // Anonymous enumeration to provide constants in this file. diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index ba2846202fe..60a0e65cbf1 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -39,7 +39,6 @@ #include "v3dmath.h" #include "m3math.h" #include "m4math.h" -#include "llcamera.h" #include "llrender.h" diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 77efec5696a..897cc4275d4 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -44,6 +44,7 @@ set(llui_SOURCE_FILES llmultislider.cpp llmultisliderctrl.cpp llpanel.cpp + llprogressbar.cpp llradiogroup.cpp llresizebar.cpp llresizehandle.cpp @@ -95,6 +96,7 @@ set(llui_HEADER_FILES llmultisliderctrl.h llmultislider.h llpanel.h + llprogressbar.h llradiogroup.h llresizebar.h llresizehandle.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 47b7067f630..7441d2f7347 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -422,13 +422,7 @@ void LLButton::draw() // Unselected image assignments S32 local_mouse_x; S32 local_mouse_y; - LLCoordWindow cursor_pos_window; - getWindow()->getCursorPosition(&cursor_pos_window); - LLCoordGL cursor_pos_gl; - getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); - cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]); - cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); - screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); + LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index f3941ff7d10..415419748f1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -456,7 +456,7 @@ class VisibilityPolicy<LLFloater> // singleton implementation for floaters (provides visibility policy) -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=79410 +// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 template <class T> class LLFloaterSingleton : public LLUISingleton<T, VisibilityPolicy<LLFloater> > { diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index f6c621444da..22934450e79 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -982,12 +982,12 @@ void LLPanel::childSetAction(const std::string& id, void(*function)(void*), void } } -void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*)) +void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*), void* value) { LLTextBox* textbox = getChild<LLTextBox>(id); if (textbox) { - textbox->setClickedCallback(function); + textbox->setClickedCallback(function, value); } } diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 355e32f1cd6..c55eb6bba2d 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -220,7 +220,7 @@ class LLPanel : public LLUICtrl // LLButton void childSetAction(const std::string& id, void(*function)(void*), void* value); - void childSetActionTextbox(const std::string& id, void(*function)(void*)); + void childSetActionTextbox(const std::string& id, void(*function)(void*), void* value = NULL); void childSetControlName(const std::string& id, const std::string& control_name); // Error reporting diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp new file mode 100644 index 00000000000..4425bad7bfe --- /dev/null +++ b/indra/llui/llprogressbar.cpp @@ -0,0 +1,180 @@ +/** + * @file llprogressbar.cpp + * @brief LLProgressBar class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "linden_common.h" + +#include "llprogressbar.h" + +#include "indra_constants.h" +#include "llmath.h" +#include "llgl.h" +#include "llui.h" +#include "llfontgl.h" +#include "llimagegl.h" +#include "lltimer.h" +#include "llglheaders.h" + +#include "llfocusmgr.h" + +static LLRegisterWidget<LLProgressBar> r("progress_bar"); + +LLProgressBar::LLProgressBar(const std::string& name, const LLRect &rect) + : LLView(name, rect, FALSE), + mImageBar( NULL ), + mImageShadow( NULL ) +{ + mPercentDone = 0.f; + + // Defaults: + + setImageBar("rounded_square.tga"); + setImageShadow("rounded_square_soft.tga"); + + mColorBackground = LLColor4(0.3254f, 0.4000f, 0.5058f, 1.0f); + mColorBar = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); + mColorBar2 = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); + mColorShadow = LLColor4(0.2000f, 0.2000f, 0.4000f, 1.0f); +} + +LLProgressBar::~LLProgressBar() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +void LLProgressBar::draw() +{ + static LLTimer timer; + + LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); + LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); + LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga"); + LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga"); + LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor"); + + bar_bg_imagep->draw(getLocalRect(), + background_color); + + F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); + LLColor4 bar_color = LLUI::sColorsGroup->getColor("LoginProgressBarFgColor"); + bar_color.mV[3] = alpha; + LLRect progress_rect = getLocalRect(); + progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f)); + bar_fg_imagep->draw(progress_rect); +} + +void LLProgressBar::setPercent(const F32 percent) +{ + mPercentDone = llclamp(percent, 0.f, 100.f); +} + +void LLProgressBar::setImageBar( const std::string &bar_name ) +{ + mImageBar = LLUI::sImageProvider->getUIImage(bar_name)->getImage(); +} + +void LLProgressBar::setImageShadow(const std::string &shadow_name) +{ + mImageShadow = LLUI::sImageProvider->getUIImage(shadow_name)->getImage(); +} + +void LLProgressBar::setColorBar(const LLColor4 &c) +{ + mColorBar = c; +} +void LLProgressBar::setColorBar2(const LLColor4 &c) +{ + mColorBar2 = c; +} +void LLProgressBar::setColorShadow(const LLColor4 &c) +{ + mColorShadow = c; +} +void LLProgressBar::setColorBackground(const LLColor4 &c) +{ + mColorBackground = c; +} + + +// static +LLView* LLProgressBar::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +{ + std::string name("progress_bar"); + node->getAttributeString("name", name); + + LLProgressBar *progress = new LLProgressBar(name, LLRect()); + + + std::string image_bar; + if (node->hasAttribute("image_bar")) node->getAttributeString("image_bar",image_bar); + if (image_bar != LLStringUtil::null) progress->setImageBar(image_bar); + + + std::string image_shadow; + if (node->hasAttribute("image_shadow")) node->getAttributeString("image_shadow",image_shadow); + if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow); + + + LLColor4 color_bar; + if (node->hasAttribute("color_bar")) + { + node->getAttributeColor4("color_bar",color_bar); + progress->setColorBar(color_bar); + } + + + LLColor4 color_bar2; + if (node->hasAttribute("color_bar2")) + { + node->getAttributeColor4("color_bar2",color_bar2); + progress->setColorBar2(color_bar2); + } + + + LLColor4 color_shadow; + if (node->hasAttribute("color_shadow")) + { + node->getAttributeColor4("color_shadow",color_shadow); + progress->setColorShadow(color_shadow); + } + + + LLColor4 color_bg; + if (node->hasAttribute("color_bg")) + { + node->getAttributeColor4("color_bg",color_bg); + progress->setColorBackground(color_bg); + } + + + progress->initFromXML(node, parent); + + return progress; +} diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h new file mode 100644 index 00000000000..6c720290fcf --- /dev/null +++ b/indra/llui/llprogressbar.h @@ -0,0 +1,75 @@ +/** + * @file llprogressbar.h + * @brief LLProgressBar class definition + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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_LLPROGRESSBAR_H +#define LL_LLPROGRESSBAR_H + +#include "llview.h" +#include "llframetimer.h" + +class LLProgressBar + : public LLView +{ +public: + LLProgressBar(const std::string& name, const LLRect &rect); + virtual ~LLProgressBar(); + + void setPercent(const F32 percent); + + void setImageBar(const std::string &bar_name); + void setImageShadow(const std::string &shadow_name); + + void setColorBar(const LLColor4 &c); + void setColorBar2(const LLColor4 &c); + void setColorShadow(const LLColor4 &c); + void setColorBackground(const LLColor4 &c); + + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + + /*virtual*/ void draw(); + +protected: + F32 mPercentDone; + + LLPointer<LLImageGL> mImageBar; + //LLUUID mImageBarID; + //LLString mImageBarName; + LLColor4 mColorBar; + LLColor4 mColorBar2; + + LLPointer<LLImageGL> mImageShadow; + //LLUUID mImageShadowID; + //LLString mImageShadowName; + LLColor4 mColorShadow; + LLColor4 mColorBackground; +}; + +#endif // LL_LLPROGRESSBAR_H diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 07babd9f55d..a7163323bd1 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -464,12 +464,7 @@ void LLScrollbar::draw() { S32 local_mouse_x; S32 local_mouse_y; - LLCoordWindow cursor_pos_window; - getWindow()->getCursorPosition(&cursor_pos_window); - LLCoordGL cursor_pos_gl; - getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); - - screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); + LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); if (hovered) diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index ac2f2a64a3e..c616931cd60 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -33,32 +33,16 @@ #include "lltextbox.h" #include "lluictrlfactory.h" #include "llfocusmgr.h" +#include "llwindow.h" static LLRegisterWidget<LLTextBox> r("text"); LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::string& text, const LLFontGL* font, BOOL mouse_opaque) : LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ), - mFontGL(font ? font : LLFontGL::sSansSerifSmall), - mTextColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), - mDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), - mBackgroundColor( LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ) ), - mBorderColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ), - mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ), - mHoverActive( FALSE ), - mHasHover( FALSE ), - mBackgroundVisible( FALSE ), - mBorderVisible( FALSE ), - mFontStyle(LLFontGL::DROP_SHADOW_SOFT), - mBorderDropShadowVisible( FALSE ), - mUseEllipses( FALSE ), - mHPad(0), - mVPad(0), - mHAlign( LLFontGL::LEFT ), - mVAlign( LLFontGL::TOP ), - mClickedCallback(NULL), - mCallbackUserData(NULL) + mFontGL(font ? font : LLFontGL::sSansSerifSmall) { + initDefaults(); setText( text ); setTabStop(FALSE); } @@ -66,26 +50,9 @@ LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::str LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_width, const LLFontGL* font, BOOL mouse_opaque) : LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), - mFontGL(font ? font : LLFontGL::sSansSerifSmall), - mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), - mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), - mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), - mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), - mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ), - mHoverActive( FALSE ), - mHasHover( FALSE ), - mBackgroundVisible(FALSE), - mBorderVisible(FALSE), - mFontStyle(LLFontGL::DROP_SHADOW_SOFT), - mBorderDropShadowVisible(FALSE), - mUseEllipses( FALSE ), - mHPad(0), - mVPad(0), - mHAlign(LLFontGL::LEFT), - mVAlign( LLFontGL::TOP ), - mClickedCallback(NULL), - mCallbackUserData(NULL) + mFontGL(font ? font : LLFontGL::sSansSerifSmall) { + initDefaults(); setWrappedText(text, max_width); reshapeToFitText(); setTabStop(FALSE); @@ -93,47 +60,34 @@ LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_w LLTextBox::LLTextBox(const std::string& name_and_label, const LLRect& rect) : LLUICtrl(name_and_label, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), - mFontGL(LLFontGL::sSansSerifSmall), - mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), - mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), - mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), - mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), - mBackgroundVisible(FALSE), - mBorderVisible(FALSE), - mFontStyle(LLFontGL::DROP_SHADOW_SOFT), - mBorderDropShadowVisible(FALSE), - mHPad(0), - mVPad(0), - mHAlign(LLFontGL::LEFT), - mVAlign( LLFontGL::TOP ), - mClickedCallback(NULL), - mCallbackUserData(NULL) + mFontGL(LLFontGL::sSansSerifSmall) { + initDefaults(); setText( name_and_label ); setTabStop(FALSE); } -LLTextBox::LLTextBox(const std::string& name_and_label) : - LLUICtrl(name_and_label, LLRect(0, 0, 1, 1), TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP), - mFontGL(LLFontGL::sSansSerifSmall), - mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")), - mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")), - mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")), - mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")), - mBackgroundVisible(FALSE), - mBorderVisible(FALSE), - mFontStyle(LLFontGL::DROP_SHADOW_SOFT), - mBorderDropShadowVisible(FALSE), - mHPad(0), - mVPad(0), - mHAlign(LLFontGL::LEFT), - mVAlign( LLFontGL::TOP ), - mClickedCallback(NULL), - mCallbackUserData(NULL) +void LLTextBox::initDefaults() { - setWrappedText(name_and_label); - reshapeToFitText(); - setTabStop(FALSE); + mTextColor = LLUI::sColorsGroup->getColor("LabelTextColor"); + mDisabledColor = LLUI::sColorsGroup->getColor("LabelDisabledColor"); + mBackgroundColor = LLUI::sColorsGroup->getColor("DefaultBackgroundColor"); + mBorderColor = LLUI::sColorsGroup->getColor("DefaultHighlightLight"); + mHoverColor = LLUI::sColorsGroup->getColor( "LabelSelectedColor" ); + mHoverActive = FALSE; + mHasHover = FALSE; + mBackgroundVisible = FALSE; + mBorderVisible = FALSE; + mFontStyle = LLFontGL::DROP_SHADOW_SOFT; + mBorderDropShadowVisible = FALSE; + mUseEllipses = FALSE; + mLineSpacing = 0; + mHPad = 0; + mVPad = 0; + mHAlign = LLFontGL::LEFT; + mVAlign = LLFontGL::TOP; + mClickedCallback = NULL; + mCallbackUserData = NULL; } BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) @@ -193,12 +147,14 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) { + BOOL handled = LLView::handleHover(x,y,mask); if(mHoverActive) { mHasHover = TRUE; // This should be set every frame during a hover. - return TRUE; + getWindow()->setCursor(UI_CURSOR_ARROW); } - return LLView::handleHover(x,y,mask); + + return (handled || mHasHover); } void LLTextBox::setText(const LLStringExplicit& text) @@ -412,7 +368,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color ) mFontStyle, line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses ); cur_pos += line_length + 1; - y -= llfloor(mFontGL->getLineHeight()); + y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing; } } } @@ -469,6 +425,8 @@ LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f text_box->initFromXML(node, parent); + node->getAttributeS32("line_spacing", text_box->mLineSpacing); + std::string font_style; if (node->getAttributeString("font-style", font_style)) { diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index b1e8e0b7c61..c28d0e5f949 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -54,7 +54,10 @@ class LLTextBox // "Simple" constructors for text boxes that have the same name and label *TO BE DEPRECATED* LLTextBox(const std::string& name_and_label, const LLRect& rect); - LLTextBox(const std::string& name_and_label); + + // Consolidate common member initialization + // 20+ initializers times 3+ constructors is unmaintainable. + void initDefaults(); virtual ~LLTextBox() {} @@ -88,8 +91,7 @@ class LLTextBox void setVPad(S32 pixels) { mVPad = pixels; } void setRightAlign() { mHAlign = LLFontGL::RIGHT; } void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } - void setClickedCallback( void (*cb)(void *data) ){ mClickedCallback = cb; } // mouse down and up within button - void setCallbackUserData( void* data ) { mCallbackUserData = data; } + void setClickedCallback( void (*cb)(void *data), void* data = NULL ){ mClickedCallback = cb; mCallbackUserData = data; } // mouse down and up within button const LLFontGL* getFont() const { return mFontGL; } @@ -124,6 +126,8 @@ class LLTextBox BOOL mBorderDropShadowVisible; BOOL mUseEllipses; + S32 mLineSpacing; + S32 mHPad; S32 mVPad; LLFontGL::HAlign mHAlign; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 92b6cc8bb62..f2562a015dd 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -3520,13 +3520,13 @@ void LLTextEditor::appendColoredText(const std::string &new_text, style->setVisible(true); style->setColor(color); style->setFontName(font_name); - appendStyledText(new_text, allow_undo, prepend_newline, &style); + appendStyledText(new_text, allow_undo, prepend_newline, style); } void LLTextEditor::appendStyledText(const std::string &new_text, bool allow_undo, bool prepend_newline, - const LLStyleSP *stylep) + const LLStyleSP stylep) { if(mParseHTML) { @@ -3540,13 +3540,13 @@ void LLTextEditor::appendStyledText(const std::string &new_text, html->setColor(mLinkColor); if (stylep) { - html->setFontName((*stylep)->getFontString()); + html->setFontName(stylep->getFontString()); } html->mUnderline = TRUE; if (start > 0) appendText(text.substr(0,start),allow_undo, prepend_newline, stylep); html->setLinkHREF(text.substr(start,end-start)); - appendText(text.substr(start, end-start),allow_undo, prepend_newline, &html); + appendText(text.substr(start, end-start),allow_undo, prepend_newline, html); if (end < (S32)text.length()) { text = text.substr(end,text.length() - end); @@ -3567,7 +3567,7 @@ void LLTextEditor::appendStyledText(const std::string &new_text, // Appends new text to end of document void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline, - const LLStyleSP *stylep) + const LLStyleSP stylep) { // Save old state BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()); @@ -3599,7 +3599,7 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool { S32 segment_start = old_length; S32 segment_end = getLength(); - LLTextSegment* segment = new LLTextSegment(*stylep, segment_start, segment_end ); + LLTextSegment* segment = new LLTextSegment(stylep, segment_start, segment_end ); mSegments.push_back(segment); } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 4f41f67ce8e..8209f6d798b 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -139,7 +139,7 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor void insertText(const std::string &text); // appends text at end void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline, - const LLStyleSP *stylep = NULL); + const LLStyleSP stylep = NULL); void appendColoredText(const std::string &wtext, bool allow_undo, bool prepend_newline, @@ -148,7 +148,7 @@ class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor // if styled text starts a line, you need to prepend a newline. void appendStyledText(const std::string &new_text, bool allow_undo, bool prepend_newline, - const LLStyleSP *stylep = NULL); + const LLStyleSP stylep = NULL); // Removes text from the end of document // Does not change highlight or cursor position. diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index f1e7b98a609..a4b16dc2dee 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1645,6 +1645,18 @@ void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y) setCursorPositionScreen(screen_x, screen_y); } +//static +void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y) +{ + LLCoordWindow cursor_pos_window; + LLView::getWindow()->getCursorPosition(&cursor_pos_window); + LLCoordGL cursor_pos_gl; + LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); + cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]); + cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); + viewp->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, x, y); +} + // On Windows, the user typically sets the language when they install the // app (by running it with a shortcut that sets InstallLanguage). On Mac, // or on Windows if the SecondLife.exe executable is run directly, the diff --git a/indra/llui/llui.h b/indra/llui/llui.h index aa3cff433ef..e2629ee2a4a 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -175,6 +175,7 @@ class LLUI static std::string locateSkin(const std::string& filename); static void setCursorPositionScreen(S32 x, S32 y); static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y); + static void getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y); static void setScaleFactor(const LLVector2& scale_factor); static void setLineWidth(F32 width); static LLUIImage* getUIImage(const std::string& name); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index c01845e524f..f7419d615b4 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -551,19 +551,6 @@ LLView* LLUICtrl::fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFacto } -// *NOTE: If other classes derive from LLPanel, they will need to be -// added to this function. -LLPanel* LLUICtrl::getParentPanel() const -{ - LLView* parent = getParent(); - LLPanel* parent_panel = dynamic_cast<LLPanel*>(parent); - while (!parent_panel) - { - parent = parent->getParent(); - } - return (LLPanel*)(parent); -} - // Skip over any parents that are not LLUICtrl's // Used in focus logic since only LLUICtrl elements can have focus LLUICtrl* LLUICtrl::getParentUICtrl() const diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 52ea37ffdd2..4ad9042b9a6 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -130,9 +130,7 @@ class LLUICtrl void setTabStop( BOOL b ); BOOL hasTabStop() const; - // Returns containing panel/floater or NULL if none found. - class LLPanel* getParentPanel() const; - class LLUICtrl* getParentUICtrl() const; + LLUICtrl* getParentUICtrl() const; void* getCallbackUserData() const { return mCallbackUserData; } void setCallbackUserData( void* data ) { mCallbackUserData = data; } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 5b71851520e..5ea9d6b5d83 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -85,7 +85,8 @@ LLView::LLView() : mLastVisible(TRUE), mUseBoundingRect(FALSE), mVisible(TRUE), - mNextInsertionOrdinal(0) + mNextInsertionOrdinal(0), + mHoverCursor(UI_CURSOR_ARROW) { } @@ -102,7 +103,8 @@ LLView::LLView(const std::string& name, BOOL mouse_opaque) : mLastVisible(TRUE), mUseBoundingRect(FALSE), mVisible(TRUE), - mNextInsertionOrdinal(0) + mNextInsertionOrdinal(0), + mHoverCursor(UI_CURSOR_ARROW) { } @@ -123,7 +125,8 @@ LLView::LLView( mLastVisible(TRUE), mUseBoundingRect(FALSE), mVisible(TRUE), - mNextInsertionOrdinal(0) + mNextInsertionOrdinal(0), + mHoverCursor(UI_CURSOR_ARROW) { } @@ -657,7 +660,7 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask) if( !handled && blockMouseEvent(x, y) ) { - LLUI::sWindow->setCursor(UI_CURSOR_ARROW); + LLUI::sWindow->setCursor(mHoverCursor); lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; handled = TRUE; } @@ -2664,6 +2667,13 @@ void LLView::initFromXML(LLXMLNodePtr node, LLView* parent) node->getAttributeBOOL("visible", visible); setVisible(visible); } + + if (node->hasAttribute("hover_cursor")) + { + std::string cursor_string; + node->getAttributeString("hover_cursor", cursor_string); + mHoverCursor = getCursorFromString(cursor_string); + } node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect); node->getAttributeBOOL("mouse_opaque", mMouseOpaque); diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 130c3b52f7a..ff7a1afb387 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -51,6 +51,7 @@ #include "llxmlnode.h" #include "stdenums.h" #include "lluistring.h" +#include "llcursortypes.h" const U32 FOLLOWS_NONE = 0x00; const U32 FOLLOWS_LEFT = 0x01; @@ -649,6 +650,8 @@ class LLView : public LLMouseHandler, public LLMortician mutable dummy_widget_map_t mDummyWidgets; boost::signals::connection mControlConnection; + + ECursorType mHoverCursor; public: static BOOL sDebugRects; // Draw debug rects behind everything. diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 8acf7d88ca7..c2562bcfc96 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -378,7 +378,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd case LL_PATH_EXECUTABLE: prefix = getExecutableDir(); break; - + default: llassert(0); } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 8dc179748ad..66cad59712c 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -35,48 +35,7 @@ #include "llrect.h" #include "llcoord.h" #include "llstring.h" - - -enum ECursorType { - UI_CURSOR_ARROW, - UI_CURSOR_WAIT, - UI_CURSOR_HAND, - UI_CURSOR_IBEAM, - UI_CURSOR_CROSS, - UI_CURSOR_SIZENWSE, - UI_CURSOR_SIZENESW, - UI_CURSOR_SIZEWE, - UI_CURSOR_SIZENS, - UI_CURSOR_NO, - UI_CURSOR_WORKING, - UI_CURSOR_TOOLGRAB, - UI_CURSOR_TOOLLAND, - UI_CURSOR_TOOLFOCUS, - UI_CURSOR_TOOLCREATE, - UI_CURSOR_ARROWDRAG, - UI_CURSOR_ARROWCOPY, // drag with copy - UI_CURSOR_ARROWDRAGMULTI, - UI_CURSOR_ARROWCOPYMULTI, // drag with copy - UI_CURSOR_NOLOCKED, - UI_CURSOR_ARROWLOCKED, - UI_CURSOR_GRABLOCKED, - UI_CURSOR_TOOLTRANSLATE, - UI_CURSOR_TOOLROTATE, - UI_CURSOR_TOOLSCALE, - UI_CURSOR_TOOLCAMERA, - UI_CURSOR_TOOLPAN, - UI_CURSOR_TOOLZOOMIN, - UI_CURSOR_TOOLPICKOBJECT3, - UI_CURSOR_TOOLSIT, - UI_CURSOR_TOOLBUY, - UI_CURSOR_TOOLPAY, - UI_CURSOR_TOOLOPEN, - UI_CURSOR_TOOLPLAY, - UI_CURSOR_TOOLPAUSE, - UI_CURSOR_TOOLMEDIAOPEN, - UI_CURSOR_PIPETTE, - UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor) -}; +#include "llcursortypes.h" class LLSplashScreen; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index c967855e938..a0514373e59 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -50,9 +50,9 @@ #include "llsdserialize.h" #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG -#define CONTROL_ERRS LL_WARNS("ControlErrors") -#else #define CONTROL_ERRS LL_ERRS("ControlErrors") +#else +#define CONTROL_ERRS LL_WARNS("ControlErrors") #endif //this defines the current version of the settings file diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e62e4be0f15..21e491e1b5b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -127,6 +127,7 @@ set(viewer_SOURCE_FILES llfloateravatartextures.cpp llfloaterbeacons.cpp llfloaterbuildoptions.cpp + llfloaterbulkpermission.cpp llfloaterbump.cpp llfloaterbuycontents.cpp llfloaterbuy.cpp @@ -150,9 +151,11 @@ set(viewer_SOURCE_FILES llfloatergroupinfo.cpp llfloatergroupinvite.cpp llfloatergroups.cpp + llfloaterhandler.cpp llfloaterhardwaresettings.cpp llfloaterhtml.cpp llfloaterhtmlhelp.cpp + llfloaterhtmlsimple.cpp llfloaterhud.cpp llfloaterimagepreview.cpp llfloaterinspect.cpp @@ -166,9 +169,11 @@ set(viewer_SOURCE_FILES llfloatermute.cpp llfloaternamedesc.cpp llfloaternewim.cpp + llfloaterobjectiminfo.cpp llfloateropenobject.cpp llfloaterparcel.cpp llfloaterpermissionsmgr.cpp + llfloaterperms.cpp llfloaterpostcard.cpp llfloaterpostprocess.cpp llfloaterpreference.cpp @@ -224,6 +229,7 @@ set(viewer_SOURCE_FILES lljoystickbutton.cpp lllandmarklist.cpp lllogchat.cpp + llloginhandler.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -522,6 +528,7 @@ set(viewer_HEADER_FILES llfloateravatartextures.h llfloaterbeacons.h llfloaterbuildoptions.h + llfloaterbulkpermission.h llfloaterbump.h llfloaterbuy.h llfloaterbuycontents.h @@ -545,9 +552,11 @@ set(viewer_HEADER_FILES llfloatergroupinfo.h llfloatergroupinvite.h llfloatergroups.h + llfloaterhandler.h llfloaterhardwaresettings.h llfloaterhtml.h llfloaterhtmlhelp.h + llfloaterhtmlsimple.h llfloaterhud.h llfloaterimagepreview.h llfloaterinspect.h @@ -561,12 +570,14 @@ set(viewer_HEADER_FILES llfloatermute.h llfloaternamedesc.h llfloaternewim.h + llfloaterobjectiminfo.h llfloateropenobject.h llfloaterparcel.h llfloaterpermissionsmgr.h llfloaterpostcard.h llfloaterpostprocess.h llfloaterpreference.h + llfloaterperms.h llfloaterproperties.h llfloaterregioninfo.h llfloaterreporter.h @@ -618,6 +629,7 @@ set(viewer_HEADER_FILES lllandmarklist.h lllightconstants.h lllogchat.h + llloginhandler.h llmanip.h llmaniprotate.h llmanipscale.h @@ -1030,6 +1042,7 @@ set(viewer_XUI_FILES skins/default/xui/en-us/floater_avatar_textures.xml skins/default/xui/en-us/floater_beacons.xml skins/default/xui/en-us/floater_build_options.xml + skins/default/xui/en-us/floater_bulk_perms.xml skins/default/xui/en-us/floater_bumps.xml skins/default/xui/en-us/floater_buy_contents.xml skins/default/xui/en-us/floater_buy_currency.xml @@ -1052,6 +1065,7 @@ set(viewer_XUI_FILES skins/default/xui/en-us/floater_group_info.xml skins/default/xui/en-us/floater_hardware_settings.xml skins/default/xui/en-us/floater_html.xml + skins/default/xui/en-us/floater_html_simple.xml skins/default/xui/en-us/floater_hud.xml skins/default/xui/en-us/floater_image_preview.xml skins/default/xui/en-us/floater_import.xml @@ -1077,11 +1091,13 @@ set(viewer_XUI_FILES skins/default/xui/en-us/floater_name_description.xml skins/default/xui/en-us/floater_new_im.xml skins/default/xui/en-us/floater_new_outfit_dialog.xml + skins/default/xui/en-us/floater_object_im_info.xml skins/default/xui/en-us/floater_openobject.xml skins/default/xui/en-us/floater_pay_object.xml skins/default/xui/en-us/floater_pay.xml skins/default/xui/en-us/floater_postcard.xml skins/default/xui/en-us/floater_post_process.xml + skins/default/xui/en-us/floater_perm_prefs.xml skins/default/xui/en-us/floater_preferences.xml skins/default/xui/en-us/floater_preview_animation.xml skins/default/xui/en-us/floater_preview_classified.xml diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e6943869dbb..a13d883682f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -906,6 +906,204 @@ <key>Value</key> <real>16.0</real> </map> + <key>BulkChangeIncludeAnimations</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect animations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeAnimations</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect animations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeAnimations</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect animations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeAnimations</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect animations</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeBodyParts</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect body parts</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeClothing</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect clothing</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeGestures</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect gestures</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeLandmarks</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect landmarks</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeNotecards</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect notecards</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeObjects</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect objects</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeScripts</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect scripts</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeSounds</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect sounds</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeIncludeTextures</key> + <map> + <key>Comment</key> + <string>Bulk permission changes affect textures</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BulkChangeEveryoneCopy</key> + <map> + <key>Comment</key> + <string>Bulk changed objects can be copied by everyone</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>BulkChangeNextOwnerCopy</key> + <map> + <key>Comment</key> + <string>Bulk changed objects can be copied by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>BulkChangeNextOwnerModify</key> + <map> + <key>Comment</key> + <string>Bulk changed objects can be modified by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>BulkChangeNextOwnerTransfer</key> + <map> + <key>Comment</key> + <string>Bulk changed objects can be resold or given away by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>BulkChangeShareWithGroup</key> + <map> + <key>Comment</key> + <string>Bulk changed objects are shared with the currently active group</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>ButtonFlashCount</key> <map> <key>Comment</key> @@ -1016,6 +1214,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>CameraAngle</key> + <map> + <key>Comment</key> + <string>Camera field of view angle (Radians)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.047197551</real> + </map> <key>CameraOffset</key> <map> <key>Comment</key> @@ -2404,6 +2613,17 @@ <key>Value</key> <integer>175</integer> </map> + <key>EveryoneCopy</key> + <map> + <key>Comment</key> + <string>Everyone can copy the newly created objects</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>FPSLogFrequency</key> <map> <key>Comment</key> @@ -3100,7 +3320,24 @@ <integer>0</integer> </array> </map> - <key>FloaterOpenObjectRect</key> + + <key>FloaterObjectIMInfo</key> + <map> + <key>Comment</key> + <string>Rectangle for floater object im info windows</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Rect</string> + <key>Value</key> + <array> + <integer>0</integer> + <integer>300</integer> + <integer>300</integer> + <integer>0</integer> + </array> + </map> + <key>FloaterOpenObjectRect</key> <map> <key>Comment</key> <string>Rectangle for Open Object window</string> @@ -3132,6 +3369,22 @@ <integer>0</integer> </array> </map> + <key>FloaterPermPrefsRect</key> + <map> + <key>Comment</key> + <string>Rectangle for initial permissions preferences</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Rect</string> + <key>Value</key> + <array> + <integer>200</integer> + <integer>250</integer> + <integer>250</integer> + <integer>200</integer> + </array> + </map> <key>FloaterRegionInfo</key> <map> <key>Comment</key> @@ -3971,18 +4224,18 @@ <key>Value</key> <real>0.0</real> </map> - <key>InstallLanguage</key> - <map> - <key>Comment</key> - <string>Language passed from installer (for UI)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>default</string> - </map> - <key>InventoryAutoOpenDelay</key> + <key>InstallLanguage</key> + <map> + <key>Comment</key> + <string>Language passed from installer (for UI)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>default</string> + </map> + <key>InventoryAutoOpenDelay</key> <map> <key>Comment</key> <string>Seconds before automatically opening inventory when mouse is over inventory button when performing inventory drag and drop</string> @@ -4966,6 +5219,39 @@ <key>Value</key> <integer>1</integer> </map> + <key>NextOwnerCopy</key> + <map> + <key>Comment</key> + <string>Newly created objects can be copied by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>NextOwnerModify</key> + <map> + <key>Comment</key> + <string>Newly created objects can be modified by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>NextOwnerTransfer</key> + <map> + <key>Comment</key> + <string>Newly created objects can be resold or given away by next owner</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>NewCacheLocation</key> <map> <key>Comment</key> @@ -6858,6 +7144,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>ShareWithGroup</key> + <map> + <key>Comment</key> + <string>Newly created objects are shared with the currently active group</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>ShowActiveSpeakers</key> <map> <key>Comment</key> @@ -7858,17 +8155,6 @@ <integer>100</integer> </array> </map> - <key>ToolboxShowMore</key> - <map> - <key>Comment</key> - <string>Whether to show additional build tool controls</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>TrackFocusObject</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ab2f06ef530..7eca956f7db 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -5830,18 +5830,18 @@ bool LLAgent::teleportCore(bool is_local) return false; } - // Stop all animation before actual teleporting + // Stop all animation before actual teleporting LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp) + if (avatarp) { - for ( LLVOAvatar::AnimIterator anim_it= avatarp->mPlayingAnimations.begin() - ; anim_it != avatarp->mPlayingAnimations.end() - ; anim_it++) - { - avatarp->stopMotion(anim_it->first); - } - avatarp->processAnimationStateChanges(); - } + for ( LLVOAvatar::AnimIterator anim_it= avatarp->mPlayingAnimations.begin(); + anim_it != avatarp->mPlayingAnimations.end(); + ++anim_it) + { + avatarp->stopMotion(anim_it->first); + } + avatarp->processAnimationStateChanges(); + } // Don't call LLFirstUse::useTeleport because we don't know // yet if the teleport will succeed. Look in @@ -6020,6 +6020,42 @@ void LLAgent::setTeleportState(ETeleportState state) } } +void LLAgent::stopCurrentAnimations() +{ + // This function stops all current overriding animations on this + // avatar, propagating this change back to the server. + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + for ( LLVOAvatar::AnimIterator anim_it = + avatarp->mPlayingAnimations.begin(); + anim_it != avatarp->mPlayingAnimations.end(); + anim_it++) + { + if (anim_it->first == + ANIM_AGENT_SIT_GROUND_CONSTRAINED) + { + // don't cancel a ground-sit anim, as viewers + // use this animation's status in + // determining whether we're sitting. ick. + } + else + { + // stop this animation locally + avatarp->stopMotion(anim_it->first, TRUE); + // ...and tell the server to tell everyone. + sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP); + } + } + + // re-assert at least the default standing animation, because + // viewers get confused by avs with no associated anims. + sendAnimationRequest(ANIM_AGENT_STAND, + ANIM_REQUEST_START); + } +} + void LLAgent::fidget() { if (!getAFK()) diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index e8537f2fba0..f561f55e466 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -372,6 +372,7 @@ class LLAgent : public LLObservable BOOL canFly(); // Animation functions + void stopCurrentAnimations(); void requestStopMotion( LLMotion* motion ); void onAnimStop(const LLUUID& id); diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 3f6a30cf329..2a5f0ea2707 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -425,8 +425,10 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ llinfos << "Was asked to go to slurl: " << slurl << llendl; - const bool from_external_browser = true; - if (LLURLDispatcher::dispatch(slurl, from_external_browser)) + std::string url = slurl; + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + if (LLURLDispatcher::dispatch(url, web, trusted_browser)) { // bring window to foreground, as it has just been "launched" from a URL // todo: hmm, how to get there from here? diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index bad47468707..81990b04643 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -48,6 +48,9 @@ #include "llurldispatcher.h" #include <Carbon/Carbon.h> #include "lldir.h" + +class LLWebBrowserCtrl; // for LLURLDispatcher + namespace { // The command line args stored. @@ -260,8 +263,21 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) if(result == noErr) { std::string url = buffer; - const bool from_external_browser = true; - LLURLDispatcher::dispatch(url, from_external_browser); + + // Safari 3.2 silently mangles secondlife:///app/ URLs into + // secondlife:/app/ (only one leading slash). + // Fix them up to meet the URL specification. JC + const std::string prefix = "secondlife:/app/"; + std::string test_prefix = url.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if (test_prefix == prefix) + { + url.replace(0, prefix.length(), "secondlife:///app/"); + } + + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, web, trusted_browser); } return(result); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 962066471f1..d25f827a725 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -48,12 +48,17 @@ #include "llpreviewgesture.h" #include "llgesturemgr.h" #include "llscrolllistctrl.h" +#include "llsdserialize.h" #include "lluploaddialog.h" #include "llviewerobject.h" +#include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "llviewermenufile.h" #include "llviewerwindow.h" +// When uploading multiple files, don't display any of them when uploading more than this number. +static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5; + void dialog_refresh_all(); LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, @@ -193,6 +198,10 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) { lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; + + //std::ostringstream llsdxml; + //LLSDSerialize::toXML(content, llsdxml); + //llinfos << "upload complete content:\n " << llsdxml.str() << llendl; LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); @@ -221,23 +230,39 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) << content["new_asset"].asUUID() << " to inventory." << llendl; if(mPostData["folder_id"].asUUID().notNull()) { - LLPermissions perm; - U32 next_owner_perm; - perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - if (mPostData["inventory_type"].asString() == "snapshot") + //std::ostringstream out; + //LLSDXMLFormatter *formatter = new LLSDXMLFormatter; + //formatter->format(mPostData, out, LLSDFormatter::OPTIONS_PRETTY); + //llinfos << "Post Data: " << out.str() << llendl; + + U32 everyone_perms = PERM_NONE; + U32 group_perms = PERM_NONE; + U32 next_owner_perms = PERM_ALL; + if(content.has("new_next_owner_mask")) { - next_owner_perm = PERM_ALL; + // This is a new sim that provides creation perms so use them. + // Do not assume we got the perms we asked for in mPostData + // since the sim may not have granted them all. + everyone_perms = content["new_everyone_mask"].asInteger(); + group_perms = content["new_group_mask"].asInteger(); + next_owner_perms = content["new_next_owner_mask"].asInteger(); } - else + else { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; + // This old sim doesn't provide creation perms so use old assumption-based perms. + if(mPostData["inventory_type"].asString() != "snapshot") + { + next_owner_perms = PERM_MOVE | PERM_TRANSFER; + } } - perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); + LLPermissions new_perms; + new_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms); S32 creation_date_now = time_corrected(); LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), mPostData["folder_id"].asUUID(), - perm, + new_perms, content["new_asset"].asUUID(), asset_type, inventory_type, @@ -255,10 +280,9 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) if(view) { LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); - if((LLAssetType::AT_TEXTURE == asset_type) - || (LLAssetType::AT_SOUND == asset_type)) + if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type) + && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD) { view->getPanel()->openSelected(); } @@ -289,8 +313,15 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLStringUtil::stripNonprintable(asset_name); LLStringUtil::trim(asset_name); + // Continuing the horrible hack above, we need to extract the originally requested permissions data, if any, + // and use them for each next file to be uploaded. Note the requested perms are not the same as the + // granted ones found in the given "content" structure but can still be found in mPostData. -MG + U32 everyone_perms = mPostData.has("everyone_mask") ? mPostData.get("everyone_mask" ).asInteger() : PERM_NONE; + U32 group_perms = mPostData.has("group_mask") ? mPostData.get("group_mask" ).asInteger() : PERM_NONE; + U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE; upload_new_resource(next_file, asset_name, asset_name, - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + next_owner_perms, group_perms, everyone_perms); } } diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 2844b888dc8..c7a55c969ac 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -684,10 +684,11 @@ class LLChatHandler : public LLCommandHandler { public: // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", false) { } + LLChatHandler() : LLCommandHandler("chat", true) { } // Your code here - bool handle(const LLSD& tokens, const LLSD& queryMap) + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) { if (tokens.size() < 2) return false; S32 channel = tokens[0].asInteger(); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 57f65fed38f..2732a17d3a8 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -199,7 +199,6 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } - // assumes GL state is set for 2D void LLColorSwatchCtrl::draw() { @@ -231,10 +230,23 @@ void LLColorSwatchCtrl::draw() } else { - // Draw grey and an X - gl_rect_2d(interior, LLColor4::grey, TRUE); - - gl_draw_x(interior, LLColor4::black); + if (!mFallbackImageName.empty()) + { + LLPointer<LLViewerImage> fallback_image = gImageList.getImageFromFile(mFallbackImageName); + if( fallback_image->getComponents() == 4 ) + { + gl_rect_2d_checkerboard( interior ); + } + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image); + fallback_image->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } + else + { + // Draw grey and an X + gl_rect_2d(interior, LLColor4::grey, TRUE); + + gl_draw_x(interior, LLColor4::black); + } } LLUICtrl::draw(); diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h index 4b69df8dbb1..4f5360b25ce 100644 --- a/indra/newview/llcolorswatch.h +++ b/indra/newview/llcolorswatch.h @@ -77,6 +77,7 @@ class LLColorSwatchCtrl void setCanApplyImmediately(BOOL apply) { mCanApplyImmediately = apply; } void setOnCancelCallback(LLUICtrlCallback cb) { mOnCancelCallback = cb; } void setOnSelectCallback(LLUICtrlCallback cb) { mOnSelectCallback = cb; } + void setFallbackImageName(const std::string& name) { mFallbackImageName = name; } void showPicker(BOOL take_focus); @@ -104,6 +105,7 @@ class LLColorSwatchCtrl LLUICtrlCallback mOnSelectCallback; LLPointer<LLUIImage> mAlphaGradientImage; + std::string mFallbackImageName; }; #endif // LL_LLBUTTON_H diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 8b86b1be5d0..cfe91bc5b55 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -42,7 +42,7 @@ //--------------------------------------------------------------------------- struct LLCommandHandlerInfo { - bool mAllowFromExternalBrowser; + bool mRequireTrustedBrowser; LLCommandHandler* mHandler; // safe, all of these are static objects }; @@ -50,8 +50,12 @@ class LLCommandHandlerRegistry { public: static LLCommandHandlerRegistry& instance(); - void add(const char* cmd, bool allow_from_external_browser, LLCommandHandler* handler); - bool dispatch(const std::string& cmd, bool from_external_browser, const LLSD& params, const LLSD& queryMap); + void add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler); + bool dispatch(const std::string& cmd, + const LLSD& params, + const LLSD& query_map, + LLWebBrowserCtrl* web, + bool trusted_browser); private: std::map<std::string, LLCommandHandlerInfo> mMap; @@ -67,40 +71,44 @@ LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance() return instance; } -void LLCommandHandlerRegistry::add(const char* cmd, bool allow_from_external_browser, LLCommandHandler* handler) +void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler) { LLCommandHandlerInfo info; - info.mAllowFromExternalBrowser = allow_from_external_browser; + info.mRequireTrustedBrowser = require_trusted_browser; info.mHandler = handler; mMap[cmd] = info; } bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, - bool from_external_browser, const LLSD& params, - const LLSD& queryMap) + const LLSD& query_map, + LLWebBrowserCtrl* web, + bool trusted_browser) { std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd); if (it == mMap.end()) return false; const LLCommandHandlerInfo& info = it->second; - if (from_external_browser && !info.mAllowFromExternalBrowser) + if (!trusted_browser && info.mRequireTrustedBrowser) { // block request from external browser, but report as // "handled" because it was well formatted. + LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; return true; } if (!info.mHandler) return false; - return info.mHandler->handle(params, queryMap); + return info.mHandler->handle(params, query_map, web); } //--------------------------------------------------------------------------- // Automatic registration of commands, runs before main() //--------------------------------------------------------------------------- -LLCommandHandler::LLCommandHandler(const char* cmd, bool allow_from_external_browser) +LLCommandHandler::LLCommandHandler(const char* cmd, + bool require_trusted_browser) { - LLCommandHandlerRegistry::instance().add(cmd, allow_from_external_browser, this); + LLCommandHandlerRegistry::instance().add( + cmd, require_trusted_browser, this); } LLCommandHandler::~LLCommandHandler() @@ -115,9 +123,11 @@ LLCommandHandler::~LLCommandHandler() // static bool LLCommandDispatcher::dispatch(const std::string& cmd, - bool from_external_browser, - const LLSD& params, const LLSD& queryMap) + const LLSD& params, + const LLSD& query_map, + LLWebBrowserCtrl* web, + bool trusted_browser) { return LLCommandHandlerRegistry::instance().dispatch( - cmd, from_external_browser, params, queryMap); + cmd, params, query_map, web, trusted_browser); } diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 8fe40a9a022..bb77b5a5423 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -33,34 +33,38 @@ #ifndef LLCOMMANDHANDLER_H #define LLCOMMANDHANDLER_H -/* To implement a command "foo" that takes one parameter, - a UUID, do this: +/* Example: secondlife:///app/foo/<uuid> + Command "foo" that takes one parameter, a UUID. class LLFooHandler : public LLCommandHandler { public: // Inform the system you handle commands starting - // with "foo" and they are not allowed from external web - // browser links. - LLFooHandler() : LLCommandHandler("foo", false) { } + // with "foo" and they are only allowed from + // "trusted" (pointed at Linden content) browsers + LLFooHandler() : LLCommandHandler("foo", true) { } // Your code here - bool handle(const LLSD& tokens, const LLSD& queryMap) + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) { if (tokens.size() < 1) return false; LLUUID id( tokens[0] ); - return doFoo(id); + return do_foo(id); } }; -// Creating the object registers with the dispatcher. +// *NOTE: Creating the object registers with the dispatcher. LLFooHandler gFooHandler; + */ +class LLWebBrowserCtrl; + class LLCommandHandler { public: - LLCommandHandler(const char* command, bool allow_from_external_browser); + LLCommandHandler(const char* command, bool allow_from_untrusted_browser); // Automatically registers object to get called when // command is executed. All commands can be processed // in links from LLWebBrowserCtrl, but some (like teleport) @@ -69,9 +73,12 @@ class LLCommandHandler virtual ~LLCommandHandler(); virtual bool handle(const LLSD& params, - const LLSD& queryMap) = 0; - // Execute the command with a provided (possibly empty) - // list of parameters. + const LLSD& query_map, + LLWebBrowserCtrl* web) = 0; + // For URL secondlife:///app/foo/bar/baz?cat=1&dog=2 + // @params - array of "bar", "baz", possibly empty + // @query_map - map of "cat" -> 1, "dog" -> 2, possibly empty + // @web - pointer to web browser control, possibly NULL // Return true if you did something, false if the parameters // are invalid or on error. }; @@ -81,9 +88,10 @@ class LLCommandDispatcher { public: static bool dispatch(const std::string& cmd, - bool from_external_browser, const LLSD& params, - const LLSD& queryMap); + const LLSD& query_map, + LLWebBrowserCtrl* web, + bool trusted_browser); // Execute a command registered via the above mechanism, // passing string parameters. // Returns true if command was found and executed correctly. diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 2e7ba1d4223..e5bc3d31705 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -33,7 +33,6 @@ #define LL_LLDYNAMICTEXTURE_H #include "llgl.h" -#include "llcamera.h" #include "llcoord.h" #include "llimagegl.h" diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 7ac50d76100..91f88277a44 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -115,7 +115,7 @@ const std::string LLFilePicker::getFirstFile() const std::string LLFilePicker::getNextFile() { - if (mCurrentFile >= (S32)mFiles.size()) + if (mCurrentFile >= getFileCount()) { mLocked = FALSE; return std::string(); @@ -128,7 +128,7 @@ const std::string LLFilePicker::getNextFile() const std::string LLFilePicker::getCurFile() { - if (mCurrentFile >= (S32)mFiles.size()) + if (mCurrentFile >= getFileCount()) { mLocked = FALSE; return std::string(); @@ -824,7 +824,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter) send_agent_resume(); if (error == noErr) { - if (mFiles.size()) + if (getFileCount()) success = true; } @@ -853,9 +853,9 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) send_agent_resume(); if (error == noErr) { - if (mFiles.size()) + if (getFileCount()) success = true; - if (mFiles.size() > 1) + if (getFileCount() > 1) mLocked = TRUE; } @@ -883,7 +883,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename) send_agent_resume(); if (error == noErr) { - if (mFiles.size()) + if (getFileCount()) success = true; } @@ -1147,7 +1147,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename gtk_widget_show_all(GTK_WIDGET(picker)); gtk_main(); - rtn = (mFiles.size() == 1); + rtn = (getFileCount() == 1); } gViewerWindow->mWindow->afterDialog(); @@ -1191,7 +1191,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) gtk_widget_show_all(GTK_WIDGET(picker)); gtk_main(); - rtn = (mFiles.size() == 1); + rtn = (getFileCount() == 1); } gViewerWindow->mWindow->afterDialog(); diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 83a93575234..4c9b9d590de 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -130,6 +130,11 @@ class LLFilePicker // doing any incrementing. const std::string getCurFile(); + // Returns the index of the current file. + S32 getCurFileNum() const { return mCurrentFile; } + + S32 getFileCount() const { return (S32)mFiles.size(); } + // See llvfs/lldir.h : getBaseFileName and getDirName to extract base or directory names // clear any lists of buffers or whatever, and make sure the file diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index a6863531561..21535895bdd 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -116,7 +116,7 @@ LLFloaterAbout::LLFloaterAbout() __DATE__, __TIME__, gSavedSettings.getString("VersionChannelName").c_str()); support_widget->appendColoredText(version, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), FALSE, FALSE, &viewer_link_style); + support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style); std::string support; support.append("\n\n"); @@ -152,7 +152,7 @@ LLFloaterAbout::LLFloaterAbout() support.append("\n"); support_widget->appendColoredText(support, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor")); - support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), FALSE, FALSE, &server_link_style); + support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style); support = "\n\n"; } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 6c42a71fe64..c7e35bcfb55 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -52,6 +52,7 @@ #include "llfocusmgr.h" #include "llkeyframemotion.h" #include "lllineeditor.h" +#include "llfloaterperms.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "lltextbox.h" @@ -994,7 +995,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata) 0, LLAssetType::AT_NONE, LLInventoryType::IT_ANIMATION, - PERM_NONE, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), name); } else diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp new file mode 100644 index 00000000000..b07fa025d14 --- /dev/null +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -0,0 +1,366 @@ +/** + * @file llfloaterbulkpermissions.cpp + * @author Michelle2 Zenovka + * @brief A floater which allows task inventory item's properties to be changed on mass. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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 "llfloaterbulkpermission.h" +#include "llfloaterperms.h" // for utilities +#include "llagent.h" +#include "llchat.h" +#include "llviewerwindow.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "lscript_rt_interface.h" +#include "llviewercontrol.h" +#include "llviewerobject.h" +#include "llviewerregion.h" +#include "llresmgr.h" +#include "llbutton.h" +#include "lldir.h" +#include "llfloaterchat.h" +#include "llviewerstats.h" +#include "lluictrlfactory.h" +#include "llselectmgr.h" + +#include "roles_constants.h" // for GP_OBJECT_MANIPULATE + + +LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed) : mDone(FALSE) +{ + mID.generate(); + LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml"); + childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("BulkChangeNextOwnerCopy")); + childSetAction("apply", onApplyBtn, this); + childSetAction("close", onCloseBtn, this); + childSetAction("check_all", onCheckAll, this); + childSetAction("check_none", onUncheckAll, this); + childSetCommitCallback("next_owner_copy", &onCommitCopy, this); +} + +void LLFloaterBulkPermission::doApply() +{ + // Inspects a stream of selected object contents and adds modifiable ones to the given array. + class ModifiableGatherer : public LLSelectedNodeFunctor + { + public: + ModifiableGatherer(LLDynamicArray<LLUUID>& q) : mQueue(q) {} + virtual bool apply(LLSelectNode* node) + { + if( node->allowOperationOnNode(PERM_MODIFY, GP_OBJECT_MANIPULATE) ) + { + mQueue.put(node->getObject()->getID()); + } + return true; + } + private: + LLDynamicArray<LLUUID>& mQueue; + }; + LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); + list->deleteAllItems(); + ModifiableGatherer gatherer(mObjectIDs); + LLSelectMgr::getInstance()->getSelection()->applyToNodes(&gatherer); + if(mObjectIDs.empty()) + { + list->addCommentText(getString("nothing_to_modify_text")); + } + else + { + mDone = FALSE; + if (!start()) + { + llwarns << "Unexpected bulk permission change failure." << llendl; + } + } +} + + +// This is the callback method for the viewer object currently being +// worked on. +// NOT static, virtual! +void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object, + InventoryObjectList* inv, + S32, + void* q_id) +{ + //llinfos << "changed object: " << viewer_object->getID() << llendl; + + //Remove this listener from the object since its + //listener callback is now being executed. + + //We remove the listener here because the function + //removeVOInventoryListener removes the listener from a ViewerObject + //which it internally stores. + + //If we call this further down in the function, calls to handleInventory + //and nextObject may update the interally stored viewer object causing + //the removal of the incorrect listener from an incorrect object. + + //Fixes SL-6119:Recompile scripts fails to complete + removeVOInventoryListener(); + + if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) ) + { + handleInventory(viewer_object, inv); + } + else + { + // something went wrong... + // note that we're not working on this one, and move onto the + // next object in the list. + llwarns << "No inventory for " << mCurrentObjectID << llendl; + nextObject(); + } +} + +void LLFloaterBulkPermission::onApplyBtn(void* user_data) +{ + LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data; + self->doApply(); +} + +void LLFloaterBulkPermission::onCloseBtn(void* user_data) +{ + LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data; + self->onClose(false); +} + +//static +void LLFloaterBulkPermission::onCommitCopy(LLUICtrl* ctrl, void* data) +{ + // Implements fair use + BOOL copyable = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy"); + if(!copyable) + { + gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", TRUE); + } + LLCheckBoxCtrl* xfer = static_cast<LLFloaterPerms*>(data)->getChild<LLCheckBoxCtrl>("next_owner_transfer"); + xfer->setEnabled(copyable); +} + +BOOL LLFloaterBulkPermission::start() +{ + // note: number of top-level objects to modify is mObjectIDs.count(). + getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("start_text")); + return nextObject(); +} + +// Go to the next object and start if found. Returns false if no objects left, true otherwise. +BOOL LLFloaterBulkPermission::nextObject() +{ + S32 count; + BOOL successful_start = FALSE; + do + { + count = mObjectIDs.count(); + //llinfos << "Objects left to process = " << count << llendl; + mCurrentObjectID.setNull(); + if(count > 0) + { + successful_start = popNext(); + //llinfos << (successful_start ? "successful" : "unsuccessful") << llendl; + } + } while((mObjectIDs.count() > 0) && !successful_start); + + if(isDone() && !mDone) + { + getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("done_text")); + mDone = TRUE; + } + return successful_start; +} + +// Pop the top object off of the queue. +// Return TRUE if the queue has started, otherwise FALSE. +BOOL LLFloaterBulkPermission::popNext() +{ + // get the head element from the container, and attempt to get its inventory. + BOOL rv = FALSE; + S32 count = mObjectIDs.count(); + if(mCurrentObjectID.isNull() && (count > 0)) + { + mCurrentObjectID = mObjectIDs.get(0); + //llinfos << "mCurrentID: " << mCurrentObjectID << llendl; + mObjectIDs.remove(0); + LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID); + if(obj) + { + //llinfos << "requesting inv for " << mCurrentObjectID << llendl; + LLUUID* id = new LLUUID(mID); + registerVOInventoryListener(obj,id); + requestVOInventory(); + rv = TRUE; + } + else + { + llinfos<<"NULL LLViewerObject" <<llendl; + } + } + + return rv; +} + + +void LLFloaterBulkPermission::doCheckUncheckAll(BOOL check) +{ + gSavedSettings.setBOOL("BulkChangeIncludeAnimations", check); + gSavedSettings.setBOOL("BulkChangeIncludeBodyParts" , check); + gSavedSettings.setBOOL("BulkChangeIncludeClothing" , check); + gSavedSettings.setBOOL("BulkChangeIncludeGestures" , check); + gSavedSettings.setBOOL("BulkChangeIncludeLandmarks" , check); + gSavedSettings.setBOOL("BulkChangeIncludeNotecards" , check); + gSavedSettings.setBOOL("BulkChangeIncludeObjects" , check); + gSavedSettings.setBOOL("BulkChangeIncludeScripts" , check); + gSavedSettings.setBOOL("BulkChangeIncludeSounds" , check); + gSavedSettings.setBOOL("BulkChangeIncludeTextures" , check); +} + + +void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, InventoryObjectList* inv) +{ + LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); + + InventoryObjectList::const_iterator it = inv->begin(); + InventoryObjectList::const_iterator end = inv->end(); + for ( ; it != end; ++it) + { + LLAssetType::EType asstype = (*it)->getType(); + if( + ( asstype == LLAssetType::AT_ANIMATION && gSavedSettings.getBOOL("BulkChangeIncludeAnimations")) || + ( asstype == LLAssetType::AT_BODYPART && gSavedSettings.getBOOL("BulkChangeIncludeBodyParts" )) || + ( asstype == LLAssetType::AT_CLOTHING && gSavedSettings.getBOOL("BulkChangeIncludeClothing" )) || + ( asstype == LLAssetType::AT_GESTURE && gSavedSettings.getBOOL("BulkChangeIncludeGestures" )) || + ( asstype == LLAssetType::AT_LANDMARK && gSavedSettings.getBOOL("BulkChangeIncludeLandmarks" )) || + ( asstype == LLAssetType::AT_NOTECARD && gSavedSettings.getBOOL("BulkChangeIncludeNotecards" )) || + ( asstype == LLAssetType::AT_OBJECT && gSavedSettings.getBOOL("BulkChangeIncludeObjects" )) || + ( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) || + ( asstype == LLAssetType::AT_SOUND && gSavedSettings.getBOOL("BulkChangeIncludeSounds" )) || + ( asstype == LLAssetType::AT_TEXTURE && gSavedSettings.getBOOL("BulkChangeIncludeTextures" ))) + { + LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); + + if (object) + { + LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); + LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item; + LLPermissions perm(new_item->getPermissions()); + + // chomp the inventory name so it fits in the scroll window nicely + // and the user can see the [OK] + std::string invname; + invname=item->getName().substr(0,item->getName().size() < 30 ? item->getName().size() : 30 ); + + LLUIString status_text = getString("status_text"); + status_text.setArg("[NAME]", invname.c_str()); + // Check whether we appear to have the appropriate permissions to change permission on this item. + // Although the server will disallow any forbidden changes, it is a good idea to guess correctly + // so that we can warn the user. The risk of getting this check wrong is therefore the possibility + // of incorrectly choosing to not attempt to make a valid change. + // + // Trouble is this is extremely difficult to do and even when we know the results + // it is difficult to design the best messaging. Therefore in this initial implementation + // we'll always try to set the requested permissions and consider all cases successful + // and perhaps later try to implement a smarter, friendlier solution. -MG + if(true + //gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE) // for group and everyone masks + //|| something else // for next owner perms + ) + { + perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("BulkChange")); + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("BulkChange")); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms("BulkChange")); + new_item->setPermissions(perm); // here's the beef + updateInventory(object,new_item,TASK_INVENTORY_ITEM_KEY,FALSE); + //status_text.setArg("[STATUS]", getString("status_ok_text")); + status_text.setArg("[STATUS]", ""); + } + else + { + //status_text.setArg("[STATUS]", getString("status_bad_text")); + status_text.setArg("[STATUS]", ""); + } + + list->addCommentText(status_text.getString()); + + //TODO if we are an object inside an object we should check a recuse flag and if set + //open the inventory of the object and recurse - Michelle2 Zenovka + + // if(recurse && ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject)) + // { + // I think we need to get the UUID of the object inside the inventory + // call item->fetchFromServer(); + // we need a call back to say item has arrived *sigh* + // we then need to do something like + // LLUUID* id = new LLUUID(mID); + // registerVOInventoryListener(obj,id); + // requestVOInventory(); + // } + } + } + } + + nextObject(); +} + + +// Avoid inventory callbacks etc by just fire and forgetting the message with the permissions update +// we could do this via LLViewerObject::updateInventory but that uses inventory call backs and buggers +// us up and we would have a dodgy item iterator + +void LLFloaterBulkPermission::updateInventory(LLViewerObject* object, LLViewerInventoryItem* item, U8 key, bool is_new) +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); + + // This slices the object into what we're concerned about on the viewer. + // The simulator will take the permissions and transfer ownership. + LLPointer<LLViewerInventoryItem> task_item = + new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), + item->getAssetUUID(), item->getType(), + item->getInventoryType(), + item->getName(), item->getDescription(), + item->getSaleInfo(), + item->getFlags(), + item->getCreationDate()); + task_item->setTransactionID(item->getTransactionID()); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_UpdateData); + msg->addU32Fast(_PREHASH_LocalID, object->mLocalID); + msg->addU8Fast(_PREHASH_Key, key); + msg->nextBlockFast(_PREHASH_InventoryData); + task_item->packMessage(msg); + msg->sendReliable(object->getRegion()->getHost()); +} + diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h new file mode 100644 index 00000000000..814c472fa35 --- /dev/null +++ b/indra/newview/llfloaterbulkpermission.h @@ -0,0 +1,107 @@ +/** + * @file llfloaterbulkpermissions.h + * @brief Allow multiple task inventory properties to be set in one go. + * @author Michelle2 Zenovka + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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_LLBULKPERMISSION_H +#define LL_LLBULKPERMISSION_H + +#include "lldarray.h" +#include "llinventory.h" +#include "llviewerobject.h" +#include "llvoinventorylistener.h" +#include "llmap.h" +#include "lluuid.h" + +#include "llfloater.h" +#include "llscrolllistctrl.h" + +#include "llviewerinventory.h" + +class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener, public LLFloaterSingleton<LLFloaterBulkPermission> +{ +public: + + LLFloaterBulkPermission(const LLSD& seed); + +private: + virtual ~LLFloaterBulkPermission() {} + + BOOL start(); // returns TRUE if the queue has started, otherwise FALSE. + BOOL nextObject(); + BOOL popNext(); + + // This is the callback method for the viewer object currently + // being worked on. + /*virtual*/ void inventoryChanged(LLViewerObject* obj, + InventoryObjectList* inv, + S32 serial_num, + void* queue); + + // This is called by inventoryChanged + void handleInventory(LLViewerObject* viewer_obj, + InventoryObjectList* inv); + + + void updateInventory(LLViewerObject* object, + LLViewerInventoryItem* item, + U8 key, + bool is_new); + + static void onCloseBtn(void* user_data); + static void onApplyBtn(void* user_data); + static void onCommitCopy(LLUICtrl* ctrl, void* data); + static void onCheckAll( void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(TRUE); } + static void onUncheckAll(void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(FALSE); } + + // returns true if this is done + BOOL isDone() const { return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0)); } + + //Read the settings and Apply the permissions + void doApply(); + void doCheckUncheckAll(BOOL check); + +private: + // UI + LLScrollListCtrl* mMessages; + LLButton* mCloseBtn; + + // Object Queue + LLDynamicArray<LLUUID> mObjectIDs; + LLUUID mCurrentObjectID; + BOOL mDone; + + LLUUID mID; + + const char* mStartString; +}; + +#endif + diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index b08dea248fa..7aa6af2fea0 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -1020,14 +1020,24 @@ void LLFloaterBuyLandUI::refreshUI() childSetText("info_size", getString("meters_supports_object", string_args)); + F32 cost_per_sqm = 0.0f; + if (mParcelActualArea > 0) + { + cost_per_sqm = (F32)mParcelPrice / (F32)mParcelActualArea; + } - childSetText("info_price", - llformat( - "L$ %d%s", - mParcelPrice, - mParcelSoldWithObjects - ? "\nsold with objects" - : "")); + LLStringUtil::format_map_t info_price_args; + info_price_args["[PRICE]"] = llformat("%d", mParcelPrice); + info_price_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm); + if (mParcelSoldWithObjects) + { + info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects"); + } + else + { + info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects"); + } + childSetText("info_price", getString("info_price_string", info_price_args)); childSetVisible("info_price", mParcelIsForSale); } else diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index ba02ccc320d..cf1dfa42e03 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -189,7 +189,7 @@ void LLFloaterChat::updateConsoleVisibility() || (getHost() && getHost()->isMinimized() )); // are we hosted in a minimized floater? } -void add_timestamped_line(LLViewerTextEditor* edit, const LLChat &chat, const LLColor4& color) +void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color) { std::string line = chat.mText; bool prepend_newline = true; @@ -199,16 +199,22 @@ void add_timestamped_line(LLViewerTextEditor* edit, const LLChat &chat, const LL prepend_newline = false; } - // If the msg is not from an agent (not yourself though), + // If the msg is from an agent (not yourself though), // extract out the sender name and replace it with the hotlinked name. if (chat.mSourceType == CHAT_SOURCE_AGENT && - chat.mFromID != LLUUID::null && - (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) + chat.mFromID != LLUUID::null) + { + chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); + } + + // If the chat line has an associated url, link it up to the name. + if (!chat.mURL.empty() + && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) { std::string start_line = line.substr(0, chat.mFromName.length() + 1); line = line.substr(chat.mFromName.length() + 1); - const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID); - edit->appendStyledText(start_line, false, prepend_newline, &sourceStyle); + const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL); + edit->appendStyledText(start_line, false, prepend_newline, sourceStyle); prepend_newline = false; } edit->appendColoredText(line, false, prepend_newline, color); diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp index 3579b2a0586..523ce6cb732 100644 --- a/indra/newview/llfloaterevent.cpp +++ b/indra/newview/llfloaterevent.cpp @@ -54,9 +54,10 @@ LLMap< U32, LLFloaterEventInfo* > gEventInfoInstances; class LLEventHandler : public LLCommandHandler { public: - // don't allow from external browsers - LLEventHandler() : LLCommandHandler("event", false) { } - bool handle(const LLSD& tokens, const LLSD& queryMap) + // requires trusted browser to trigger + LLEventHandler() : LLCommandHandler("event", true) { } + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) { if (tokens.size() < 2) { diff --git a/indra/newview/llfloaterhandler.cpp b/indra/newview/llfloaterhandler.cpp new file mode 100644 index 00000000000..4c0461e910c --- /dev/null +++ b/indra/newview/llfloaterhandler.cpp @@ -0,0 +1,77 @@ +/** + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llfloaterhandler.h" + +#include "llfloater.h" +#include "llwebbrowserctrl.h" + +// register with dispatch via global object +LLFloaterHandler gFloaterHandler; + + +LLFloater* get_parent_floater(LLView* view) +{ + LLFloater* floater = NULL; + LLView* parent = view->getParent(); + while (parent) + { + floater = dynamic_cast<LLFloater*>(parent); + if (floater) + { + break; + } + parent = parent->getParent(); + } + return floater; +} + + +bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, LLWebBrowserCtrl *web) +{ + if (params.size() < 2) return false; + LLFloater* floater = NULL; + // *TODO: implement floater lookup by name + if (params[0].asString() == "self") + { + if (web) + { + floater = get_parent_floater(web); + } + } + if (params[1].asString() == "close") + { + if (floater) + { + floater->close(); + return true; + } + } + return false; +} diff --git a/indra/newview/llfloaterhandler.h b/indra/newview/llfloaterhandler.h new file mode 100644 index 00000000000..90e87c07e34 --- /dev/null +++ b/indra/newview/llfloaterhandler.h @@ -0,0 +1,44 @@ +/** + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 LLFLOATERHANDLER_H +#define LLFLOATERHANDLER_H + +// Support for SLURL control of floaters, such as +// secondlife:///app/floater/self/close + +#include "llcommandhandler.h" + +class LLFloaterHandler +: public LLCommandHandler +{ +public: + LLFloaterHandler() : LLCommandHandler("floater", true) { } + bool handle(const LLSD& params, const LLSD& query_map, LLWebBrowserCtrl* web); +}; + +#endif diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index f4a515e0a04..a92634bc311 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -604,6 +604,25 @@ void LLPanelLandGeneral::refresh() mBtnSellLand->setVisible(FALSE); mBtnStopSellLand->setVisible(FALSE); + // show pricing information + S32 area; + S32 claim_price; + S32 rent_price; + F32 dwell; + LLViewerParcelMgr::getInstance()->getDisplayInfo(&area, + &claim_price, + &rent_price, + &for_sale, + &dwell); + + // Area + LLUIString price = childGetText("area_size_text"); + price.setArg("[AREA]", llformat("%d",area)); + mTextPriceLabel->setText(childGetText("area_text")); + mTextPrice->setText(price.getString()); + + mTextDwell->setText(llformat("%.0f", dwell)); + if (for_sale) { mSaleInfoForSale1->setVisible(TRUE); @@ -619,7 +638,15 @@ void LLPanelLandGeneral::refresh() mSaleInfoForSaleNoObjects->setVisible(TRUE); } mSaleInfoNotForSale->setVisible(FALSE); + + F32 cost_per_sqm = 0.0f; + if (area > 0) + { + cost_per_sqm = (F32)parcel->getSalePrice() / (F32)area; + } + mSaleInfoForSale1->setTextArg("[PRICE]", llformat("%d", parcel->getSalePrice())); + mSaleInfoForSale1->setTextArg("[PRICE_PER_SQM]", llformat("%.1f", cost_per_sqm)); if (can_be_sold) { mBtnStopSellLand->setVisible(TRUE); @@ -645,25 +672,6 @@ void LLPanelLandGeneral::refresh() mBtnBuyGroupLand->setEnabled( LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true)); - // show pricing information - S32 area; - S32 claim_price; - S32 rent_price; - F32 dwell; - LLViewerParcelMgr::getInstance()->getDisplayInfo(&area, - &claim_price, - &rent_price, - &for_sale, - &dwell); - - // Area - LLUIString price = getString("area_size_text"); - price.setArg("[AREA]", llformat("%d",area)); - mTextPriceLabel->setText(getString("area_text")); - mTextPrice->setText(price.getString()); - - mTextDwell->setText(llformat("%.0f", dwell)); - if(region_owner) { mBtnReclaimLand->setEnabled( @@ -1716,8 +1724,6 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel) BOOL LLPanelLandOptions::postBuild() { - - mCheckEditObjects = getChild<LLCheckBoxCtrl>( "edit objects check"); childSetCommitCallback("edit objects check", onCommitAny, this); @@ -1829,6 +1835,8 @@ BOOL LLPanelLandOptions::postBuild() mLandingTypeCombo = getChild<LLComboBox>( "landing type"); childSetCommitCallback("landing type", onCommitAny, this); + getChild<LLTextureCtrl>("snapshot_ctrl")->setFallbackImageName("default_land_picture.j2c"); + return TRUE; } diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index f53482a476e..b16351af179 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -43,6 +43,7 @@ #include "llradiogroup.h" #include "lldbstrings.h" #include "lldir.h" +#include "llfloaterperms.h" #include "llviewercontrol.h" #include "llviewermenufile.h" // upload_new_resource() #include "lluictrlfactory.h" @@ -180,7 +181,8 @@ void LLFloaterNameDesc::onBtnOK( void* userdata ) upload_new_resource(fp->mFilenameAndPath, // file fp->childGetValue("name_form").asString(), fp->childGetValue("description_form").asString(), - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms()); fp->close(false); } diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp index 59e95fb9438..bbe278f8857 100644 --- a/indra/newview/llfloaterparcel.cpp +++ b/indra/newview/llfloaterparcel.cpp @@ -51,9 +51,10 @@ LLMap< const LLUUID, LLFloaterParcelInfo* > gPlaceInfoInstances; class LLParcelHandler : public LLCommandHandler { public: - // don't allow from external browsers - LLParcelHandler() : LLCommandHandler("parcel", false) { } - bool handle(const LLSD& params, const LLSD& queryMap) + // requires trusted browser to trigger + LLParcelHandler() : LLCommandHandler("parcel", true) { } + bool handle(const LLSD& params, const LLSD& query_map, + LLWebBrowserCtrl* web) { if (params.size() < 2) { diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp new file mode 100644 index 00000000000..9405bc61b25 --- /dev/null +++ b/indra/newview/llfloaterperms.cpp @@ -0,0 +1,157 @@ +/** + * @file llfloaterperms.cpp + * @brief Asset creation permission preferences. + * @author Coco + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llalertdialog.h" +#include "llcheckboxctrl.h" +#include "llfloaterperms.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" +#include "lluictrlfactory.h" +#include "llpermissions.h" + + +LLFloaterPerms::LLFloaterPerms(const LLSD& seed) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml"); +} + +BOOL LLFloaterPerms::postBuild() +{ + childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy")); + childSetAction("help", onClickHelp, this); + childSetAction("ok", onClickOK, this); + childSetAction("cancel", onClickCancel, this); + childSetCommitCallback("next_owner_copy", &onCommitCopy, this); + + refresh(); + + return TRUE; +} + +//static +void LLFloaterPerms::onClickOK(void* data) +{ + LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data); + self->ok(); + self->close(); +} + +//static +void LLFloaterPerms::onClickCancel(void* data) +{ + LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data); + self->cancel(); + self->close(); +} + +//static +void LLFloaterPerms::onCommitCopy(LLUICtrl* ctrl, void* data) +{ + // Implements fair use + BOOL copyable = gSavedSettings.getBOOL("NextOwnerCopy"); + if(!copyable) + { + gSavedSettings.setBOOL("NextOwnerTransfer", TRUE); + } + LLCheckBoxCtrl* xfer = static_cast<LLFloaterPerms*>(data)->getChild<LLCheckBoxCtrl>("next_owner_transfer"); + xfer->setEnabled(copyable); +} + +void LLFloaterPerms::ok() +{ + refresh(); // Changes were already applied to saved settings. Refreshing internal values makes it official. +} + +void LLFloaterPerms::cancel() +{ + gSavedSettings.setBOOL("ShareWithGroup", mShareWithGroup); + gSavedSettings.setBOOL("EveryoneCopy", mEveryoneCopy); + gSavedSettings.setBOOL("NextOwnerCopy", mNextOwnerCopy); + gSavedSettings.setBOOL("NextOwnerModify", mNextOwnerModify); + gSavedSettings.setBOOL("NextOwnerTransfer", mNextOwnerTransfer); +} + +void LLFloaterPerms::refresh() +{ + mShareWithGroup = gSavedSettings.getBOOL("ShareWithGroup"); + mEveryoneCopy = gSavedSettings.getBOOL("EveryoneCopy"); + mNextOwnerCopy = gSavedSettings.getBOOL("NextOwnerCopy"); + mNextOwnerModify = gSavedSettings.getBOOL("NextOwnerModify"); + mNextOwnerTransfer = gSavedSettings.getBOOL("NextOwnerTransfer"); +} + +void LLFloaterPerms::onClose(bool app_quitting) +{ + // Cancel any unsaved changes before closing. + // Note: when closed due to the OK button this amounts to a no-op. + cancel(); + LLFloater::onClose(app_quitting); +} + +//static +U32 LLFloaterPerms::getGroupPerms(std::string prefix) +{ + return gSavedSettings.getBOOL(prefix+"ShareWithGroup") ? PERM_COPY : PERM_NONE; +} + +//static +U32 LLFloaterPerms::getEveryonePerms(std::string prefix) +{ + return gSavedSettings.getBOOL(prefix+"EveryoneCopy") ? PERM_COPY : PERM_NONE; +} + +//static +U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix) +{ + U32 flags = 0; + if ( gSavedSettings.getBOOL(prefix+"NextOwnerCopy") ) + { + flags |= PERM_COPY; + } + if ( gSavedSettings.getBOOL(prefix+"NextOwnerModify") ) + { + flags |= PERM_MODIFY; + } + if ( gSavedSettings.getBOOL(prefix+"NextOwnerTransfer") ) + { + flags |= PERM_TRANSFER; + } + return flags; +} + + +//static +void LLFloaterPerms::onClickHelp(void* data) +{ + gViewerWindow->alertXml("ClickUploadHelpPermissions"); +} diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h new file mode 100644 index 00000000000..bd9dee1869b --- /dev/null +++ b/indra/newview/llfloaterperms.h @@ -0,0 +1,70 @@ +/** + * @file llfloaterperms.h + * @brief Asset creation permission preferences. + * @author Coco + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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_LLFLOATERPERMPREFS_H +#define LL_LLFLOATERPERMPREFS_H + +#include "llfloater.h" + +class LLFloaterPerms : public LLFloater, public LLFloaterSingleton<LLFloaterPerms> +{ + friend class LLUISingleton<LLFloaterPerms, VisibilityPolicy<LLFloater> >; + +public: + /*virtual*/ void onClose(bool app_quitting = false); + /*virtual*/ BOOL postBuild(); + void ok(); + void cancel(); + static void onClickOK(void*); + static void onClickCancel(void*); + static void onCommitCopy(LLUICtrl* ctrl, void* data); + // Convenience methods to get current permission preference bitfields from saved settings: + static U32 getEveryonePerms(std::string prefix=""); // prefix + "EveryoneCopy" + static U32 getGroupPerms(std::string prefix=""); // prefix + "ShareWithGroup" + static U32 getNextOwnerPerms(std::string prefix=""); // bitfield for prefix + "NextOwner" + "Copy", "Modify", and "Transfer" + +private: + LLFloaterPerms(const LLSD& seed); + void refresh(); + + /// callback for the menus help button + static void onClickHelp(void* data); + + BOOL // cached values only for implementing cancel. + mShareWithGroup, + mEveryoneCopy, + mNextOwnerCopy, + mNextOwnerModify, + mNextOwnerTransfer; +}; + +#endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 15d4d302216..2de00ec4576 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1,6 +1,6 @@ /** * @file llfloaterpreference.cpp - * @brief LLPreferenceCore class implementation + * @brief Global preferences with and without persistence. * * $LicenseInfo:firstyear=2002&license=viewergpl$ * @@ -89,9 +89,10 @@ LLFloaterPreference* LLFloaterPreference::sInstance = NULL; class LLPreferencesHandler : public LLCommandHandler { public: - // don't allow from external browsers - LLPreferencesHandler() : LLCommandHandler("preferences", false) { } - bool handle(const LLSD& tokens, const LLSD& queryMap) + // requires trusted browser + LLPreferencesHandler() : LLCommandHandler("preferences", true) { } + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) { LLFloaterPreference::show(NULL); return true; @@ -259,6 +260,7 @@ void LLPreferenceCore::apply() mInputPanel->apply(); mNetworkPanel->apply(); mDisplayPanel->apply(); + mAudioPanel->apply(); mPrefsChat->apply(); mPrefsVoice->apply(); mPrefsIM->apply(); @@ -477,6 +479,7 @@ void LLFloaterPreference::onBtnApply( void* userdata ) void LLFloaterPreference::onClose(bool app_quitting) { LLPanelLogin::setAlwaysRefresh(false); + cancel(); // will be a no-op if OK or apply was performed just prior. LLFloater::onClose(app_quitting); } @@ -493,8 +496,7 @@ void LLFloaterPreference::onBtnCancel( void* userdata ) cur_focus->onCommit(); } } - fp->cancel(); - fp->close(); + fp->close(); // side effect will also cancel any unsaved changes. } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index f4843ea1a53..db2ea7f41ae 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -369,7 +369,7 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) glLineWidth(2.0f * line_width) ; LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ; gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y, - mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ; + mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ; glLineWidth(line_width) ; //draw four alpha rectangles to cover areas outside of the snapshot image @@ -383,20 +383,20 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ; gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y, - mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; + mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y, - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; + mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; } if(mThumbnailHeight > mPreviewRect.getHeight()) { S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ; gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y , - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ; + mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ; dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ; gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh, - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ; + mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ; } } } @@ -950,7 +950,9 @@ void LLSnapshotLivePreview::saveTexture() 0, LLAssetType::AT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT, - PERM_ALL, + PERM_ALL, // Note: Snapshots to inventory is a special case of content upload + PERM_NONE, // that ignores the user's premissions preferences and continues to + PERM_NONE, // always use these fairly permissive hard-coded initial perms. - MG "Snapshot : " + pos_string); gViewerWindow->playSnapshotAnimAndSound(); } @@ -1424,7 +1426,7 @@ void LLFloaterSnapshot::Impl::onClickMore(void* data) if(getPreviewView(view)) { getPreviewView(view)->setThumbnailImageSize() ; - } + } } } void LLFloaterSnapshot::Impl::onClickLess(void* data) @@ -1664,15 +1666,15 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL if(view->childGetValue("snapshot_width").asInteger() != width || view->childGetValue("snapshot_height").asInteger() != height) { - view->childSetValue("snapshot_width", width); - view->childSetValue("snapshot_height", height); - // hide old preview as the aspect ratio could be wrong - checkAutoSnapshot(previewp, FALSE); + view->childSetValue("snapshot_width", width); + view->childSetValue("snapshot_height", height); + // hide old preview as the aspect ratio could be wrong + checkAutoSnapshot(previewp, FALSE); getPreviewView(view)->updateSnapshot(FALSE, TRUE); if(do_update) { updateControls(view); - } + } } } } diff --git a/indra/newview/llfloatertelehub.cpp b/indra/newview/llfloatertelehub.cpp index 0b4a05867f2..49ece7a19e9 100644 --- a/indra/newview/llfloatertelehub.cpp +++ b/indra/newview/llfloatertelehub.cpp @@ -68,7 +68,6 @@ void LLFloaterTelehub::show() // Find tools floater, glue to bottom if (gFloaterTools) { - gFloaterTools->showMore(FALSE); LLRect tools_rect = gFloaterTools->getRect(); S32 our_width = sInstance->getRect().getWidth(); S32 our_height = sInstance->getRect().getHeight(); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 9e5eb2008b3..1c289912619 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -53,6 +53,7 @@ #include "llpanelobject.h" #include "llpanelvolume.h" #include "llpanelpermissions.h" +#include "llresmgr.h" #include "llselectmgr.h" #include "llslider.h" #include "llstatusbar.h" @@ -106,9 +107,8 @@ void click_popup_rotate_left(void*); void click_popup_rotate_reset(void*); void click_popup_rotate_right(void*); void click_popup_dozer_mode(LLUICtrl *, void *user); -void click_popup_dozer_size(LLUICtrl *, void *user); +void commit_slider_dozer_size(LLUICtrl *, void*); void commit_slider_dozer_force(LLUICtrl *, void*); -void click_dozer_size(LLUICtrl *, void*); void click_apply_to_selection(void*); void commit_radio_zoom(LLUICtrl *, void*); void commit_radio_orbit(LLUICtrl *, void*); @@ -303,27 +303,22 @@ BOOL LLFloaterTools::postBuild() childSetCommitCallback("radio noise",click_popup_dozer_mode, (void*)4); mRadioDozerRevert = getChild<LLCheckBoxCtrl>("radio revert"); childSetCommitCallback("radio revert",click_popup_dozer_mode, (void*)5); - mComboDozerSize = getChild<LLComboBox>("combobox brush size"); - childSetCommitCallback("combobox brush size",click_dozer_size, (void*)0); - if(mComboDozerSize) mComboDozerSize->setCurrentByIndex(0); mBtnApplyToSelection = getChild<LLButton>("button apply to selection"); childSetAction("button apply to selection",click_apply_to_selection, (void*)0); - mCheckShowOwners = getChild<LLCheckBoxCtrl>("checkbox show owners"); - childSetValue("checkbox show owners",gSavedSettings.getBOOL("ShowParcelOwners")); + mSliderDozerSize = getChild<LLSlider>("slider brush size"); + childSetCommitCallback("slider brush size", commit_slider_dozer_size, (void*)0); + childSetValue( "slider brush size", gSavedSettings.getS32("RadioLandBrushSize")); + mSliderDozerForce = getChild<LLSlider>("slider force"); childSetCommitCallback("slider force",commit_slider_dozer_force, (void*)0); // the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here childSetValue( "slider force", log10(gSavedSettings.getF32("LandBrushForce"))); - childSetAction("button more", click_show_more, this); - childSetAction("button less", click_show_more, this); mTab = getChild<LLTabContainer>("Object Info Tabs"); if(mTab) { - mTab->setVisible( gSavedSettings.getBOOL("ToolboxShowMore") ); mTab->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); - mTab->setVisible( gSavedSettings.getBOOL("ToolboxShowMore") ); mTab->setBorderVisible(FALSE); mTab->selectFirstTab(); } @@ -391,10 +386,9 @@ LLFloaterTools::LLFloaterTools() mRadioDozerSmooth(NULL), mRadioDozerNoise(NULL), mRadioDozerRevert(NULL), - mComboDozerSize(NULL), + mSliderDozerSize(NULL), + mSliderDozerForce(NULL), mBtnApplyToSelection(NULL), - mCheckShowOwners(NULL), - mTab(NULL), mPanelPermissions(NULL), @@ -418,19 +412,6 @@ LLFloaterTools::LLFloaterTools() factory_map["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo LLUICtrlFactory::getInstance()->buildFloater(this,"floater_tools.xml",&factory_map,FALSE); - - mLargeHeight = getRect().getHeight(); - mSmallHeight = mLargeHeight; - if (mTab) mSmallHeight -= mTab->getRect().getHeight(); - - // force a toggle initially. seems to be needed to correctly initialize - // both "more" and "less" cases. it also seems to be important to begin - // with the user's preference first so that it's initial position will - // be correct (SL-51192) -MG - BOOL show_more = gSavedSettings.getBOOL("ToolboxShowMore"); // get user's preference - gSavedSettings.setBOOL("ToolboxShowMore", show_more); // sets up forced toggle below - showMore( !show_more ); // does the toggle - showMore( show_more ); // reset the real user's preference } LLFloaterTools::~LLFloaterTools() @@ -474,6 +455,16 @@ void LLFloaterTools::refresh() mTab->enableTabButton(idx_face, all_volume); mTab->enableTabButton(idx_contents, all_volume); + // Refresh object and prim count labels + LLLocale locale(LLLocale::USER_LOCALE); + std::string obj_count_string; + LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount()); + childSetTextArg("obj_count", "[COUNT]", obj_count_string); + std::string prim_count_string; + LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount()); + childSetTextArg("prim_count", "[COUNT]", prim_count_string); + + // Refresh child tabs mPanelPermissions->refresh(); mPanelObject->refresh(); mPanelVolume->refresh(); @@ -702,7 +693,6 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) if (mRadioSelectLand) mRadioSelectLand->setVisible( land_visible ); S32 dozer_mode = gSavedSettings.getS32("RadioLandBrushAction"); - S32 dozer_size = gSavedSettings.getS32("RadioLandBrushSize"); if (mRadioDozerFlatten) { @@ -734,20 +724,16 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mRadioDozerRevert ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 5); mRadioDozerRevert ->setVisible( land_visible ); } - if (mComboDozerSize) - { - mComboDozerSize ->setCurrentByIndex(dozer_size); - mComboDozerSize ->setVisible( land_visible ); - mComboDozerSize ->setEnabled( tool == LLToolBrushLand::getInstance() ); - } if (mBtnApplyToSelection) { mBtnApplyToSelection->setVisible( land_visible ); mBtnApplyToSelection->setEnabled( land_visible && !LLViewerParcelMgr::getInstance()->selectionEmpty() && tool != LLToolSelectLand::getInstance()); } - if (mCheckShowOwners) + if (mSliderDozerSize) { - mCheckShowOwners ->setVisible( land_visible ); + mSliderDozerSize ->setVisible( land_visible ); + childSetVisible("Bulldozer:", land_visible); + childSetVisible("Dozer Size:", land_visible); } if (mSliderDozerForce) { @@ -755,13 +741,10 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) childSetVisible("Strength:", land_visible); } - // - // More panel visibility - // - BOOL show_more = gSavedSettings.getBOOL("ToolboxShowMore"); - - mTab->setVisible(show_more && tool != LLToolBrushLand::getInstance() && tool != LLToolSelectLand::getInstance()); - mPanelLandInfo->setVisible(show_more && (tool == LLToolBrushLand::getInstance() || tool == LLToolSelectLand::getInstance())); + childSetVisible("obj_count", !land_visible); + childSetVisible("prim_count", !land_visible); + mTab->setVisible(!land_visible); + mPanelLandInfo->setVisible(land_visible); } @@ -816,46 +799,12 @@ void LLFloaterTools::onClose(bool app_quitting) // gMenuBarView->arrange(); } -void LLFloaterTools::showMore(BOOL show_more) -{ - BOOL showing_more = gSavedSettings.getBOOL("ToolboxShowMore"); - if (show_more == showing_more) - { - return; - } - - gSavedSettings.setBOOL("ToolboxShowMore", show_more); - - // Visibility updated next frame - JC - // mTab->setVisible(show_more); - - if (show_more) - { - reshape( getRect().getWidth(), mLargeHeight, TRUE); - translate( 0, mSmallHeight - mLargeHeight ); - } - else - { - reshape( getRect().getWidth(), mSmallHeight, TRUE); - translate( 0, mLargeHeight - mSmallHeight ); - } - childSetVisible("button less", show_more); - childSetVisible("button more", !show_more); -} - void LLFloaterTools::showPanel(EInfoPanel panel) { llassert(panel >= 0 && panel < PANEL_COUNT); mTab->selectTabByName(PANEL_NAMES[panel]); } -void click_show_more(void *userdata) -{ - LLFloaterTools *f = (LLFloaterTools *)userdata; - BOOL show_more = !gSavedSettings.getBOOL("ToolboxShowMore"); - f->showMore( show_more ); -} - void click_popup_info(void*) { // gBuildView->setPropertiesPanelOpen(TRUE); @@ -933,22 +882,14 @@ void click_popup_rotate_right(void*) void click_popup_dozer_mode(LLUICtrl *, void *user) { - S32 show_owners = gSavedSettings.getBOOL("ShowParcelOwners"); S32 mode = (S32)(intptr_t) user; gFloaterTools->setEditTool( LLToolBrushLand::getInstance() ); gSavedSettings.setS32("RadioLandBrushAction", mode); - gSavedSettings.setBOOL("ShowParcelOwners", show_owners); -} - -void click_popup_dozer_size(LLUICtrl *, void *user) -{ - S32 size = (S32)(intptr_t) user; - gSavedSettings.setS32("RadioLandBrushSize", size); } -void click_dozer_size(LLUICtrl *ctrl, void *user) +void commit_slider_dozer_size(LLUICtrl *ctrl, void*) { - S32 size = ((LLComboBox*) ctrl)->getCurrentIndex(); + S32 size = (S32)ctrl->getValue().asInteger(); gSavedSettings.setS32("RadioLandBrushSize", size); } diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 81e40c04085..27e05ce2377 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -95,7 +95,6 @@ class LLFloaterTools /*virtual*/ void draw(); void dirty(); - void showMore(BOOL show_more); void showPanel(EInfoPanel panel); void setStatusText(const std::string& text); @@ -168,11 +167,10 @@ class LLFloaterTools LLCheckBoxCtrl *mRadioDozerSmooth; LLCheckBoxCtrl *mRadioDozerNoise; LLCheckBoxCtrl *mRadioDozerRevert; + LLSlider *mSliderDozerSize; LLSlider *mSliderDozerForce; - LLComboBox *mComboDozerSize; LLButton *mBtnApplyToSelection; - LLCheckBoxCtrl *mCheckShowOwners; std::vector<LLButton*> mButtons;//[ 15 ]; @@ -191,8 +189,6 @@ class LLFloaterTools private: BOOL mDirty; - S32 mSmallHeight; - S32 mLargeHeight; std::map<std::string, std::string> mStatusText; }; diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 89c91bbf2b1..2281f1b5989 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -49,10 +49,8 @@ #include "lldraghandle.h" #include "llfirstuse.h" #include "llfocusmgr.h" -#include "llinventorymodel.h" #include "lllandmarklist.h" #include "lllineeditor.h" -#include "llnetmap.h" #include "llpreviewlandmark.h" #include "llregionhandle.h" #include "llscrolllistctrl.h" diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 51b0470e07a..770c1177981 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1500,8 +1500,8 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 else { // Convert the name to a hotlink and add to message. - const LLStyleSP &source_style = LLStyleMap::instance().lookup(source); - mHistoryEditor->appendStyledText(name,false,prepend_newline,&source_style); + const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source); + mHistoryEditor->appendStyledText(name,false,prepend_newline,source_style); } prepend_newline = false; } diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp new file mode 100644 index 00000000000..c311b467791 --- /dev/null +++ b/indra/newview/llloginhandler.cpp @@ -0,0 +1,227 @@ +/** + * @file llloginhandler.cpp + * @brief Handles filling in the login panel information from a SLURL + * such as secondlife:///app/login?first=Bob&last=Dobbs + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llloginhandler.h" + +// viewer includes +#include "llpanellogin.h" // save_password_to_disk() +#include "llstartup.h" // getStartupState() +#include "llurlsimstring.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewernetwork.h" // EGridInfo + +// library includes +#include "llmd5.h" + + +// Must have instance to auto-register with LLCommandDispatcher +LLLoginHandler gLoginHandler; + + +//parses the input url and returns true if afterwards +//a web-login-key, firstname and lastname is set +bool LLLoginHandler::parseDirectLogin(std::string url) +{ + LLURI uri(url); + parse(uri.queryMap()); + + if (mWebLoginKey.isNull() || + mFirstName.empty() || + mLastName.empty()) + { + return false; + } + else + { + return true; + } +} + + +void LLLoginHandler::parse(const LLSD& queryMap) +{ + mWebLoginKey = queryMap["web_login_key"].asUUID(); + mFirstName = queryMap["first_name"].asString(); + mLastName = queryMap["last_name"].asString(); + + EGridInfo grid_choice = GRID_INFO_NONE; + if (queryMap["grid"].asString() == "aditi") + { + grid_choice = GRID_INFO_ADITI; + } + else if (queryMap["grid"].asString() == "agni") + { + grid_choice = GRID_INFO_AGNI; + } + else if (queryMap["grid"].asString() == "siva") + { + grid_choice = GRID_INFO_SIVA; + } + else if (queryMap["grid"].asString() == "damballah") + { + grid_choice = GRID_INFO_DAMBALLAH; + } + else if (queryMap["grid"].asString() == "durga") + { + grid_choice = GRID_INFO_DURGA; + } + else if (queryMap["grid"].asString() == "shakti") + { + grid_choice = GRID_INFO_SHAKTI; + } + else if (queryMap["grid"].asString() == "soma") + { + grid_choice = GRID_INFO_SOMA; + } + else if (queryMap["grid"].asString() == "ganga") + { + grid_choice = GRID_INFO_GANGA; + } + else if (queryMap["grid"].asString() == "vaak") + { + grid_choice = GRID_INFO_VAAK; + } + else if (queryMap["grid"].asString() == "uma") + { + grid_choice = GRID_INFO_UMA; + } + else if (queryMap["grid"].asString() == "mohini") + { + grid_choice = GRID_INFO_MOHINI; + } + else if (queryMap["grid"].asString() == "yami") + { + grid_choice = GRID_INFO_YAMI; + } + else if (queryMap["grid"].asString() == "nandi") + { + grid_choice = GRID_INFO_NANDI; + } + else if (queryMap["grid"].asString() == "mitra") + { + grid_choice = GRID_INFO_MITRA; + } + else if (queryMap["grid"].asString() == "radha") + { + grid_choice = GRID_INFO_RADHA; + } + else if (queryMap["grid"].asString() == "ravi") + { + grid_choice = GRID_INFO_RAVI; + } + else if (queryMap["grid"].asString() == "aruna") + { + grid_choice = GRID_INFO_ARUNA; + } + + if(grid_choice != GRID_INFO_NONE) + { + LLViewerLogin::getInstance()->setGridChoice(grid_choice); + } + + std::string startLocation = queryMap["location"].asString(); + + if (startLocation == "specify") + { + LLURLSimString::setString(queryMap["region"].asString()); + } + else if (startLocation == "home") + { + gSavedSettings.setBOOL("LoginLastLocation", FALSE); + LLURLSimString::setString(LLStringUtil::null); + } + else if (startLocation == "last") + { + gSavedSettings.setBOOL("LoginLastLocation", TRUE); + LLURLSimString::setString(LLStringUtil::null); + } +} + +bool LLLoginHandler::handle(const LLSD& tokens, + const LLSD& query_map, + LLWebBrowserCtrl* web) +{ + parse(query_map); + + //if we haven't initialized stuff yet, this is + //coming in from the GURL handler, just parse + if (STATE_FIRST == LLStartUp::getStartupState()) + { + return true; + } + + std::string password = query_map["password"].asString(); + + if (!password.empty()) + { + gSavedSettings.setBOOL("RememberPassword", TRUE); + + if (password.substr(0,3) != "$1$") + { + LLMD5 pass((unsigned char*)password.c_str()); + char md5pass[33]; /* Flawfinder: ignore */ + pass.hex_digest(md5pass); + password = ll_safe_string(md5pass, 32); + save_password_to_disk(password.c_str()); + } + } + else + { + save_password_to_disk(NULL); + gSavedSettings.setBOOL("RememberPassword", FALSE); + } + + + if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) //on splash page + { + if (!mFirstName.empty() || !mLastName.empty()) + { + // Fill in the name, and maybe the password, preserving the + // remember-password setting. JC + std::string ignore; + BOOL remember; + LLPanelLogin::getFields(ignore, ignore, ignore, remember); + LLPanelLogin::setFields(mFirstName, mLastName, password, remember); + } + + if (mWebLoginKey.isNull()) + { + LLPanelLogin::loadLoginPage(); + } + else + { + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + } + } + return true; +} diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h new file mode 100644 index 00000000000..96149e3f065 --- /dev/null +++ b/indra/newview/llloginhandler.h @@ -0,0 +1,63 @@ +/** + * @file llloginhandler.h + * @brief Handles filling in the login panel information from a SLURL + * such as secondlife:///app/login?first=Bob&last=Dobbs + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 LLLOGINHANDLER_H +#define LLLOGINHANDLER_H + +#include "llcommandhandler.h" + +class LLLoginHandler : public LLCommandHandler +{ + public: + // allow from external browsers + LLLoginHandler() : LLCommandHandler("login", false) { } + /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web); + + // Fill in our internal fields from a SLURL like + // secondlife:///app/login?first=Bob&last=Dobbs + bool parseDirectLogin(std::string url); + + std::string getFirstName() const { return mFirstName; } + std::string getLastName() const { return mLastName; } + LLUUID getWebLoginKey() const { return mWebLoginKey; } + +private: + void parse(const LLSD& queryMap); + +private: + std::string mFirstName; + std::string mLastName; + LLUUID mWebLoginKey; +}; + +extern LLLoginHandler gLoginHandler; + +#endif diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 21b1bee54f6..d836876d668 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -44,6 +44,7 @@ #include "llcallingcard.h" #include "llcolorscheme.h" #include "llviewercontrol.h" +#include "llfloateravatarinfo.h" #include "llfloaterworldmap.h" #include "llfloatermap.h" #include "llframetimer.h" @@ -73,6 +74,7 @@ const F32 MAP_SCALE_MIN = 64; const F32 MAP_SCALE_MID = 172; const F32 MAP_SCALE_MAX = 512; const F32 MAP_SCALE_INCREMENT = 16; +const F32 MAP_MIN_PICK_DIST = 4; const S32 TRACKING_RADIUS = 3; @@ -161,10 +163,11 @@ LLNetMap::LLNetMap( menu->appendSeparator(); menu->append(new LLMenuItemCallGL(std::string("Stop Tracking"), &LLTracker::stopTracking, &LLTracker::isTracking, NULL) ); + menu->append(new LLMenuItemCallGL(std::string("Profile..."), &showAgentProfile, + &isAgentUnderCursor, NULL) ); menu->setVisible(FALSE); addChild(menu); mPopupMenuHandle = menu->getHandle(); - sInstance = this; } @@ -370,6 +373,14 @@ void LLNetMap::draw() LLVector3d pos_global; LLVector3 pos_map; + // Mouse pointer in local coordinates + S32 local_mouse_x; + S32 local_mouse_y; + //localMouse(&local_mouse_x, &local_mouse_y); + LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y); + mClosestAgentToCursor.setNull(); + F32 closest_dist = F32_MAX; + // Draw avatars for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->mActiveRegionList.begin(); iter != LLWorld::getInstance()->mActiveRegionList.end(); ++iter) @@ -413,6 +424,13 @@ void LLNetMap::draw() pos_map.mV[VX], pos_map.mV[VY], show_as_friend ? gFriendMapColor : gAvatarMapColor, pos_map.mV[VZ]); + + F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); + if(dist_to_cursor < MAP_MIN_PICK_DIST && dist_to_cursor < closest_dist) + { + closest_dist = dist_to_cursor; + mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i); + } } } @@ -590,7 +608,14 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) ); if( region ) { - msg.assign( region->getName() ); + msg.assign(""); + std::string fullname; + if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname)) + { + msg.append(fullname); + msg.append("\n"); + } + msg.append( region->getName() ); #ifndef LL_RELEASE_FOR_DOWNLOAD std::string buffer; @@ -774,6 +799,7 @@ BOOL LLNetMap::handleDoubleClick( S32 x, S32 y, MASK mask ) BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) { + mClosestAgentAtLastRightClick = mClosestAgentToCursor; LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if (menu) { @@ -805,3 +831,9 @@ void LLNetMap::handleZoomLevel(void* which) break; } } + +// static +void LLNetMap::showAgentProfile(void*) +{ + LLFloaterAvatarInfo::show(sInstance->mClosestAgentAtLastRightClick); +} diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 3950a081660..214dc4df932 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -108,8 +108,14 @@ class LLNetMap : public LLUICtrl LLTextBox* mTextBoxNorthWest; LLTextBox* mTextBoxSouthWest; +private: + LLUUID mClosestAgentToCursor; + LLUUID mClosestAgentAtLastRightClick; + static BOOL sRotateMap; static LLNetMap* sInstance; + static BOOL isAgentUnderCursor(void*) { return sInstance && sInstance->mClosestAgentToCursor.notNull(); } + static void showAgentProfile(void*); }; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 7d66da30e5c..9c8817da9ad 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -389,7 +389,6 @@ LLPanelAvatarFirstLife::LLPanelAvatarFirstLife(const std::string& name, { } - void LLPanelAvatarFirstLife::enableControls(BOOL self) { childSetEnabled("img", self); @@ -438,6 +437,8 @@ BOOL LLPanelAvatarSecondLife::postBuild(void) childSetDoubleClickCallback("groups", onDoubleClickGroup, this ); + getChild<LLTextureCtrl>("img")->setFallbackImageName("default_profile_picture.j2c"); + return TRUE; } @@ -445,6 +446,9 @@ BOOL LLPanelAvatarFirstLife::postBuild(void) { BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() ); enableControls(own_avatar); + + getChild<LLTextureCtrl>("img")->setFallbackImageName("default_profile_picture.j2c"); + return TRUE; } @@ -1778,7 +1782,7 @@ void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**) msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_BornOn, born_on); msg->getString("PropertiesData","ProfileURL", profile_url); msg->getU32Fast(_PREHASH_PropertiesData, _PREHASH_Flags, flags); - + identified = (flags & AVATAR_IDENTIFIED); transacted = (flags & AVATAR_TRANSACTED); age_verified = (flags & AVATAR_AGEVERIFIED); // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 34731f653f6..64cc19e2fd5 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -116,7 +116,7 @@ class LLClassifiedTeleportHandler : public LLCommandHandler { public: // don't allow from external browsers because it moves you immediately - LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", false) { } + LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", true) { } bool handle(const LLSD& tokens, const LLSD& queryMap) { @@ -139,8 +139,9 @@ class LLClassifiedTeleportHandler : public LLCommandHandler const bool from_search = true; LLPanelClassified::sendClassifiedClickMessage(classified_id, "teleport", from_search); // Invoke teleport - const bool from_external_browser = false; - return LLURLDispatcher::dispatch(url, from_external_browser); + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = true; + return LLURLDispatcher::dispatch(url, web, trusted_browser); } }; // Creating the object registers with the dispatcher. diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index e9fb9d3a177..7fdd052af5f 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -52,6 +52,7 @@ #include "lltextbox.h" #include "llbutton.h" #include "llcombobox.h" +#include "llfloaterbulkpermission.h" #include "llagent.h" #include "llviewerwindow.h" @@ -82,6 +83,7 @@ BOOL LLPanelContents::postBuild() setMouseOpaque(FALSE); childSetAction("button new script",&LLPanelContents::onClickNewScript, this); + childSetAction("button permissions",&LLPanelContents::onClickPermissions, this); return TRUE; } @@ -104,7 +106,6 @@ void LLPanelContents::getState(LLViewerObject *objectp ) if( !objectp ) { childSetEnabled("button new script",FALSE); - //mBtnNewScript->setEnabled( FALSE ); return; } @@ -117,21 +118,12 @@ void LLPanelContents::getState(LLViewerObject *objectp ) && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); - // Edit script button - ok if object is editable and there's an - // unambiguous destination for the object. - if( editable && + // Edit script button - ok if object is editable and there's an unambiguous destination for the object. + childSetEnabled("button new script", + editable && all_volume && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) - || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))) - { - //mBtnNewScript->setEnabled(TRUE); - childSetEnabled("button new script",TRUE); - } - else - { - //mBtnNewScript->setEnabled(FALSE); - childSetEnabled("button new script",FALSE); - } + || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))); } @@ -210,3 +202,11 @@ void LLPanelContents::onClickNewScript(void *userdata) #endif } } + + +// static +void LLPanelContents::onClickPermissions(void *userdata) +{ + LLPanelContents* self = (LLPanelContents*)userdata; + gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterBulkPermission::showInstance()); +} diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index 98e53d6de38..e8a00b9c6e8 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -51,6 +51,7 @@ class LLPanelContents : public LLPanel void refresh(); static void onClickNewScript( void* userdata); + static void onClickPermissions( void* userdata); protected: void getState(LLViewerObject *object); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 8cc7844c0fb..b3d03bba6f8 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -424,7 +424,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id ); - + if (identical) { // All selected have the same texture @@ -765,6 +765,7 @@ void LLPanelFace::getState() if(texture_ctrl) { texture_ctrl->setImageAssetID( LLUUID::null ); + texture_ctrl->setFallbackImageName( "locked_image.j2c" ); texture_ctrl->setEnabled( FALSE ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl. // texture_ctrl->setValid(FALSE); } @@ -772,6 +773,7 @@ void LLPanelFace::getState() if(mColorSwatch) { mColorSwatch->setEnabled( FALSE ); + mColorSwatch->setFallbackImageName("locked_image.j2c" ); mColorSwatch->setValid(FALSE); } childSetEnabled("color trans",FALSE); diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index ba4153b087f..4b48fb35109 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -2085,8 +2085,19 @@ void LLPanelGroupRolesSubTab::handleRoleSelect() gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES)); mRoleTitle->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES)); mRoleDescription->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES)); - mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES)); - + + if ( is_owner_role ) + { + // you can't delete the owner role + can_delete = FALSE; + // ... or hide members with this role + mMemberVisibleCheck->setEnabled(FALSE); + } + else + { + mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES)); + } + if (item->getUUID().isNull()) { // Everyone role, can't edit description or name or delete @@ -2094,8 +2105,6 @@ void LLPanelGroupRolesSubTab::handleRoleSelect() mRoleName->setEnabled(FALSE); can_delete = FALSE; } - //you can't delete the owner role - if ( is_owner_role ) can_delete = FALSE; } else { diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp index f0afa3434ef..11f88695c57 100644 --- a/indra/newview/llpanelland.cpp +++ b/indra/newview/llpanelland.cpp @@ -37,10 +37,13 @@ #include "llagent.h" #include "llbutton.h" +#include "llcheckboxctrl.h" #include "llfloaterland.h" #include "lltextbox.h" +#include "llviewercontrol.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" +#include "llviewerwindow.h" #include "roles_constants.h" #include "lluictrlfactory.h" @@ -65,6 +68,10 @@ BOOL LLPanelLandInfo::postBuild() childSetAction("button subdivide land",onClickDivide,this); childSetAction("button join land",onClickJoin,this); childSetAction("button about land",onClickAbout,this); + childSetAction("button show owners help", onShowOwnersHelp, this); + + mCheckShowOwners = getChild<LLCheckBoxCtrl>("checkbox show owners"); + childSetValue("checkbox show owners", gSavedSettings.getBOOL("ShowParcelOwners")); return TRUE; } @@ -72,7 +79,8 @@ BOOL LLPanelLandInfo::postBuild() // Methods // LLPanelLandInfo::LLPanelLandInfo(const std::string& name) -: LLPanel(name) +: LLPanel(name), + mCheckShowOwners(NULL) { if (!sInstance) { @@ -255,3 +263,8 @@ void LLPanelLandInfo::onClickAbout(void*) LLFloaterLand::showInstance(); } + +void LLPanelLandInfo::onShowOwnersHelp(void* user_data) +{ + gViewerWindow->alertXml("ShowOwnersHelp"); +} diff --git a/indra/newview/llpanelland.h b/indra/newview/llpanelland.h index 7db8e648011..477c5ed9705 100644 --- a/indra/newview/llpanelland.h +++ b/indra/newview/llpanelland.h @@ -50,6 +50,8 @@ class LLPanelLandInfo void refresh(); static void refreshAll(); + + LLCheckBoxCtrl *mCheckShowOwners; protected: static void onClickClaim(void*); @@ -57,6 +59,7 @@ class LLPanelLandInfo static void onClickDivide(void*); static void onClickJoin(void*); static void onClickAbout(void*); + static void onShowOwnersHelp(void*); protected: //LLTextBox* mTextPriceLabel; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 816a8b5765e..20228ed3064 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -32,6 +32,7 @@ #include "llviewerprecompiledheaders.h" #include "llpanellogin.h" + #include "llpanelgeneral.h" #include "indra_constants.h" // for key and mask constants @@ -43,7 +44,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" -#include "llcommandhandler.h" +#include "llcommandhandler.h" // for secondlife:///app/login/ #include "llcombobox.h" #include "llcurl.h" #include "llviewercontrol.h" @@ -78,9 +79,6 @@ #define USE_VIEWER_AUTH 0 -std::string load_password_from_disk(void); -void save_password_to_disk(const char* hashed_password); - const S32 BLACK_BORDER_HEIGHT = 160; const S32 MAX_PASSWORD = 16; @@ -92,8 +90,8 @@ class LLLoginRefreshHandler : public LLCommandHandler { public: // don't allow from external browsers - LLLoginRefreshHandler() : LLCommandHandler("login_refresh", false) { } - bool handle(const LLSD& tokens, const LLSD& queryMap) + LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { } + bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) { @@ -106,191 +104,6 @@ class LLLoginRefreshHandler : public LLCommandHandler LLLoginRefreshHandler gLoginRefreshHandler; -//parses the input url and returns true if afterwards -//a web-login-key, firstname and lastname is set -bool LLLoginHandler::parseDirectLogin(std::string url) -{ - LLURI uri(url); - parse(uri.queryMap()); - - if (mWebLoginKey.isNull() || - mFirstName.empty() || - mLastName.empty()) - { - return false; - } - else - { - return true; - } -} - - -void LLLoginHandler::parse(const LLSD& queryMap) -{ - mWebLoginKey = queryMap["web_login_key"].asUUID(); - mFirstName = queryMap["first_name"].asString(); - mLastName = queryMap["last_name"].asString(); - - EGridInfo grid_choice = GRID_INFO_NONE; - if (queryMap["grid"].asString() == "aditi") - { - grid_choice = GRID_INFO_ADITI; - } - else if (queryMap["grid"].asString() == "agni") - { - grid_choice = GRID_INFO_AGNI; - } - else if (queryMap["grid"].asString() == "siva") - { - grid_choice = GRID_INFO_SIVA; - } - else if (queryMap["grid"].asString() == "damballah") - { - grid_choice = GRID_INFO_DAMBALLAH; - } - else if (queryMap["grid"].asString() == "durga") - { - grid_choice = GRID_INFO_DURGA; - } - else if (queryMap["grid"].asString() == "shakti") - { - grid_choice = GRID_INFO_SHAKTI; - } - else if (queryMap["grid"].asString() == "soma") - { - grid_choice = GRID_INFO_SOMA; - } - else if (queryMap["grid"].asString() == "ganga") - { - grid_choice = GRID_INFO_GANGA; - } - else if (queryMap["grid"].asString() == "vaak") - { - grid_choice = GRID_INFO_VAAK; - } - else if (queryMap["grid"].asString() == "uma") - { - grid_choice = GRID_INFO_UMA; - } - else if (queryMap["grid"].asString() == "mohini") - { - grid_choice = GRID_INFO_MOHINI; - } - else if (queryMap["grid"].asString() == "yami") - { - grid_choice = GRID_INFO_YAMI; - } - else if (queryMap["grid"].asString() == "nandi") - { - grid_choice = GRID_INFO_NANDI; - } - else if (queryMap["grid"].asString() == "mitra") - { - grid_choice = GRID_INFO_MITRA; - } - else if (queryMap["grid"].asString() == "radha") - { - grid_choice = GRID_INFO_RADHA; - } - else if (queryMap["grid"].asString() == "ravi") - { - grid_choice = GRID_INFO_RAVI; - } - else if (queryMap["grid"].asString() == "aruna") - { - grid_choice = GRID_INFO_ARUNA; - } - else if (queryMap["grid"].asString() == "bharati") - { - grid_choice = GRID_INFO_BHARATI; - } - else if (queryMap["grid"].asString() == "chandra") - { - grid_choice = GRID_INFO_CHANDRA; - } - else if (queryMap["grid"].asString() == "danu") - { - grid_choice = GRID_INFO_DANU; - } - else if (queryMap["grid"].asString() == "parvati") - { - grid_choice = GRID_INFO_PARVATI; - } - else if (queryMap["grid"].asString() == "skanda") - { - grid_choice = GRID_INFO_SKANDA; - } - - if(grid_choice != GRID_INFO_NONE) - { - LLViewerLogin::getInstance()->setGridChoice(grid_choice); - } - - std::string startLocation = queryMap["location"].asString(); - - if (startLocation == "specify") - { - LLURLSimString::setString(queryMap["region"].asString()); - } - else if (startLocation == "home") - { - gSavedSettings.setBOOL("LoginLastLocation", FALSE); - LLURLSimString::setString(LLStringUtil::null); - } - else if (startLocation == "last") - { - gSavedSettings.setBOOL("LoginLastLocation", TRUE); - LLURLSimString::setString(LLStringUtil::null); - } -} - -bool LLLoginHandler::handle(const LLSD& tokens, - const LLSD& queryMap) -{ - parse(queryMap); - - //if we haven't initialized stuff yet, this is - //coming in from the GURL handler, just parse - if (STATE_FIRST == LLStartUp::getStartupState()) - { - return true; - } - - std::string password = queryMap["password"].asString(); - - if (!password.empty()) - { - gSavedSettings.setBOOL("RememberPassword", TRUE); - - if (password.substr(0,3) != "$1$") - { - LLMD5 pass((unsigned char*)password.c_str()); - char md5pass[33]; /* Flawfinder: ignore */ - pass.hex_digest(md5pass); - password = ll_safe_string(md5pass, 32); - save_password_to_disk(password.c_str()); - } - } - else - { - save_password_to_disk(NULL); - gSavedSettings.setBOOL("RememberPassword", FALSE); - } - - - if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) //on splash page - { - if (mWebLoginKey.isNull()) { - LLPanelLogin::loadLoginPage(); - } else { - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - } - } - return true; -} - -LLLoginHandler gLoginHandler; // helper class that trys to download a URL from a web site and calls a method // on parent class indicating if the web server is working or not @@ -450,7 +263,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LL_VERSION_PATCH, LL_VIEWER_BUILD ); LLTextBox* channel_text = getChild<LLTextBox>("channel_text"); - channel_text->setTextArg("[CHANNEL]", channel); + channel_text->setTextArg("[CHANNEL]", channel); // though not displayed channel_text->setTextArg("[VERSION]", version); channel_text->setClickedCallback(onClickVersion); channel_text->setCallbackUserData(this); @@ -465,7 +278,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, // get the web browser control LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("login_html"); // Need to handle login secondlife:///app/ URLs - web_browser->setOpenAppSLURLs( true ); + web_browser->setTrusted( true ); // observe browser events web_browser->addObserver( this ); diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index aa41ab70b8a..9d7e386cdad 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -33,36 +33,11 @@ #define LL_LLPANELLOGIN_H #include "llpanel.h" -#include "llcommandhandler.h" -#include "lldbstrings.h" -#include "llmemory.h" -#include "llviewerimage.h" -#include "llstring.h" -#include "llmd5.h" -#include "llwebbrowserctrl.h" - -class LLTextBox; -class LLLineEditor; -class LLCheckBoxCtrl; -class LLButton; -class LLComboBox; - - -class LLLoginHandler : public LLCommandHandler -{ - public: - // allow from external browsers - LLLoginHandler() : LLCommandHandler("login", true) { } - bool handle(const LLSD& tokens, const LLSD& queryMap); - bool parseDirectLogin(std::string url); - void parse(const LLSD& queryMap); - - LLUUID mWebLoginKey; - std::string mFirstName; - std::string mLastName; -}; +#include "llmemory.h" // LLPointer<> +#include "llwebbrowserctrl.h" // LLWebBrowserCtrlObserver + +class LLUIImage; -extern LLLoginHandler gLoginHandler; class LLPanelLogin: public LLPanel, @@ -130,4 +105,7 @@ class LLPanelLogin: BOOL mHtmlAvailable; }; +std::string load_password_from_disk(void); +void save_password_to_disk(const char* hashed_password); + #endif diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index f7f33cb66b4..38214d78d6e 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -849,6 +849,7 @@ void LLPanelObject::getState( ) F32 twist_inc = OBJECT_TWIST_LINEAR_INC; BOOL advanced_is_dimple = FALSE; + BOOL advanced_is_slice = FALSE; BOOL size_is_hole = FALSE; // Tune based on overall volume type @@ -902,8 +903,20 @@ void LLPanelObject::getState( ) break; case MI_BOX: + advanced_cut_visible = TRUE; + advanced_is_slice = TRUE; + break; + case MI_CYLINDER: + advanced_cut_visible = TRUE; + advanced_is_slice = TRUE; + break; + case MI_PRISM: + advanced_cut_visible = TRUE; + advanced_is_slice = TRUE; + break; + default: break; } @@ -995,6 +1008,8 @@ void LLPanelObject::getState( ) childSetVisible("advanced_cut", FALSE); childSetVisible("advanced_dimple", FALSE); + childSetVisible("advanced_slice", FALSE); + if (advanced_cut_visible) { if (advanced_is_dimple) @@ -1002,6 +1017,12 @@ void LLPanelObject::getState( ) childSetVisible("advanced_dimple", TRUE); childSetEnabled("advanced_dimple", enabled); } + + else if (advanced_is_slice) + { + childSetVisible("advanced_slice", TRUE); + childSetEnabled("advanced_slice", enabled); + } else { childSetVisible("advanced_cut", TRUE); @@ -1895,8 +1916,9 @@ void LLPanelObject::clearCtrls() childSetEnabled("scale_hole", FALSE); childSetEnabled("scale_taper", FALSE); - childSetEnabled( "advanced_cut", FALSE ); - childSetEnabled( "advanced_dimple", FALSE ); + childSetEnabled("advanced_cut", FALSE); + childSetEnabled("advanced_dimple", FALSE); + childSetVisible("advanced_slice", FALSE); } // diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index fff5c1985bc..8a75385984d 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -190,9 +190,6 @@ void LLPanelPermissions::refresh() childSetEnabled("Description:",false); childSetText("Object Description",LLStringUtil::null); childSetEnabled("Object Description",false); - - childSetText("prim info",LLStringUtil::null); - childSetEnabled("prim info",false); childSetEnabled("Permissions:",false); @@ -395,33 +392,6 @@ void LLPanelPermissions::refresh() childSetEnabled("Object Description",false); } - - // Pre-compute object info string - S32 prim_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - S32 obj_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); - - std::string object_info_string; - if (1 == obj_count) - { - object_info_string.assign("1 Object, "); - } - else - { - object_info_string = llformat( "%d Objects, ", obj_count); - } - if (1 == prim_count) - { - object_info_string.append("1 Primitive"); - } - else - { - std::string buffer; - buffer = llformat( "%d Primitives", prim_count); - object_info_string.append(buffer); - } - childSetText("prim info",object_info_string); - childSetEnabled("prim info",true); - S32 total_sale_price = 0; S32 individual_sale_price = 0; BOOL is_for_sale_mixed = FALSE; diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index f40c101a4d2..4ae253360a9 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -360,6 +360,7 @@ void LLPanelPlace::displayParcelInfo(const LLVector3& pos_region, mDescEditor->setText(getString("server_update_text")); } mSnapshotCtrl->setImageAssetID(LLUUID::null); + mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c"); } diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index c79022a98f3..897596ea42b 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -46,12 +46,14 @@ #include "llagent.h" #include "llbutton.h" #include "llfocusmgr.h" +#include "llprogressbar.h" #include "llstartup.h" #include "llviewercontrol.h" #include "llviewerimagelist.h" #include "llviewerwindow.h" #include "llappviewer.h" #include "llweb.h" +#include "lluictrlfactory.h" LLProgressView* LLProgressView::sInstance = NULL; @@ -69,28 +71,28 @@ const S32 ANIMATION_FRAMES = 1; //13; LLProgressView::LLProgressView(const std::string& name, const LLRect &rect) : LLPanel(name, rect, FALSE), mPercentDone( 0.f ), + mURLInMessage(false), mMouseDownInActiveArea( false ) { - const S32 CANCEL_BTN_WIDTH = 70; - const S32 CANCEL_BTN_OFFSET = 16; - LLRect r; - r.setOriginAndSize( - getRect().getWidth() - CANCEL_BTN_OFFSET - CANCEL_BTN_WIDTH, CANCEL_BTN_OFFSET, - CANCEL_BTN_WIDTH, BTN_HEIGHT ); - - mCancelBtn = new LLButton(std::string("Quit"), - r, - std::string(""), - LLProgressView::onCancelButtonClicked, - NULL ); - mCancelBtn->setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); - addChild( mCancelBtn ); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml"); + reshape(rect.getWidth(), rect.getHeight()); +} + +BOOL LLProgressView::postBuild() +{ + mProgressBar = getChild<LLProgressBar>("login_progress_bar"); + + mCancelBtn = getChild<LLButton>("cancel_btn"); + mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked ); mFadeTimer.stop(); - setVisible(FALSE); - mOutlineRect.set( 0, 0, 0, 0 ); + getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle())); + + getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage); + getChild<LLTextBox>("message_text")->setCallbackUserData(this); sInstance = this; + return TRUE; } @@ -101,59 +103,11 @@ LLProgressView::~LLProgressView() sInstance = NULL; } -BOOL LLProgressView::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if ( mOutlineRect.pointInRect( x, y ) ) - { - mMouseDownInActiveArea = TRUE; - return TRUE; - }; - - return LLPanel::handleMouseDown(x, y, mask); -} - -BOOL LLProgressView::handleMouseUp(S32 x, S32 y, MASK mask) -{ - if ( mOutlineRect.pointInRect( x, y ) ) - { - if ( mMouseDownInActiveArea ) - { - if ( ! mMessage.empty() ) - { - std::string url_to_open( "" ); - - size_t start_pos = mMessage.find( "http://" ); - if ( start_pos != std::string::npos ) - { - size_t end_pos = mMessage.find_first_of( " \n\r\t", start_pos ); - if ( end_pos != std::string::npos ) - url_to_open = mMessage.substr( start_pos, end_pos - start_pos ); - else - url_to_open = mMessage.substr( start_pos ); - - LLWeb::loadURLExternal( url_to_open ); - }; - }; - return TRUE; - }; - }; - - return LLPanel::handleMouseUp(x, y, mask); -} - BOOL LLProgressView::handleHover(S32 x, S32 y, MASK mask) { if( childrenHandleHover( x, y, mask ) == NULL ) { - lldebugst(LLERR_USER_INPUT) << "hover handled by LLProgressView" << llendl; - if ( mOutlineRect.pointInRect( x, y ) ) - { - gViewerWindow->setCursor(UI_CURSOR_ARROW); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_WAIT); - } + gViewerWindow->setCursor(UI_CURSOR_WAIT); } return TRUE; } @@ -181,7 +135,7 @@ void LLProgressView::setVisible(BOOL visible) setFocus(TRUE); mFadeTimer.stop(); mProgressTimer.start(); - LLView::setVisible(visible); + LLPanel::setVisible(visible); } } @@ -190,19 +144,6 @@ void LLProgressView::draw() { static LLTimer timer; - if (gNoRender) - { - return; - } - - // Make sure the progress view always fills the entire window. - S32 width = gViewerWindow->getWindowWidth(); - S32 height = gViewerWindow->getWindowHeight(); - if( (width != getRect().getWidth()) || (height != getRect().getHeight()) ) - { - reshape( width, height ); - } - // Paint bitmap if we've got one glPushMatrix(); if (gStartImageGL) @@ -211,6 +152,8 @@ void LLProgressView::draw() gGL.getTexUnit(0)->bind(gStartImageGL); gGL.color4f(1.f, 1.f, 1.f, mFadeTimer.getStarted() ? clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, FADE_IN_TIME, 1.f, 0.f) : 1.f); F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight; + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); F32 view_aspect = (F32)width / (F32)height; // stretch image to maintain aspect ratio if (image_aspect > view_aspect) @@ -237,161 +180,37 @@ void LLProgressView::draw() // Handle fade-in animation if (mFadeTimer.getStarted()) { - LLView::draw(); + LLPanel::draw(); if (mFadeTimer.getElapsedTimeF32() > FADE_IN_TIME) { gFocusMgr.removeTopCtrlWithoutCallback(this); - LLView::setVisible(FALSE); + LLPanel::setVisible(FALSE); gStartImageGL = NULL; } return; } - S32 line_x = getRect().getWidth() / 2; - S32 line_one_y = getRect().getHeight() / 2 + 64; - const S32 LINE_SPACING = 25; - S32 line_two_y = line_one_y - LINE_SPACING; - const LLFontGL* font = LLFontGL::sSansSerif; - - LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); - LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); - LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga"); - LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga"); - - LLColor4 background_color = gColors.getColor("LoginProgressBarBgColor"); - - F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); - // background_color.mV[3] = background_color.mV[3]*alpha; - - std::string top_line = LLAppViewer::instance()->getSecondLifeTitle(); - - S32 bar_bottom = line_two_y - 30; - S32 bar_height = 18; - S32 bar_width = getRect().getWidth() * 2 / 3; - S32 bar_left = (getRect().getWidth() / 2) - (bar_width / 2); - - // translucent outline box - S32 background_box_left = ( ( ( getRect().getWidth() / 2 ) - ( bar_width / 2 ) ) / 4 ) * 3; - S32 background_box_top = ( getRect().getHeight() / 2 ) + LINE_SPACING * 5; - S32 background_box_right = getRect().getWidth() - background_box_left; - S32 background_box_bottom = ( getRect().getHeight() / 2 ) - LINE_SPACING * 5; - S32 background_box_width = background_box_right - background_box_left + 1; - S32 background_box_height = background_box_top - background_box_bottom + 1; - -// shadow_imagep->draw( background_box_left + 2, -// background_box_bottom - 2, -// background_box_width, -// background_box_height, -// gColors.getColor( "LoginProgressBoxShadowColor" ) ); -// bar_outline_imagep->draw( background_box_left, -// background_box_bottom, -// background_box_width, -// background_box_height, -// gColors.getColor("LoginProgressBoxBorderColor") ); - - bar_imagep->draw( background_box_left + 1, - background_box_bottom + 1, - background_box_width - 2, - background_box_height - 2, - gColors.getColor("LoginProgressBoxCenterColor") ); - - // we'll need this later for catching a click if it looks like it contains a link - if ( mMessage.find( "http://" ) != std::string::npos ) - mOutlineRect.set( background_box_left, background_box_top, background_box_right, background_box_bottom ); - else - mOutlineRect.set( 0, 0, 0, 0 ); - - // draw loading bar - font->renderUTF8(top_line, 0, - line_x, line_one_y, - //LLColor4::white, - gColors.getColor("LoginProgressBoxTextColor"), - LLFontGL::HCENTER, LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); - font->renderUTF8(mText, 0, - line_x, line_two_y, - //LLColor4::white, - gColors.getColor("LoginProgressBoxTextColor"), - LLFontGL::HCENTER, LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); - -// shadow_imagep->draw( -// bar_left + 2, -// bar_bottom - 2, -// bar_width, -// bar_height, -// gColors.getColor("LoginProgressBoxShadowColor")); - -// bar_imagep->draw( -// bar_left, -// bar_bottom, -// bar_width, -// bar_height, -// LLColor4(0.7f, 0.7f, 0.8f, 1.0f)); - - bar_bg_imagep->draw( - bar_left + 2, - bar_bottom + 2, - bar_width - 4, - bar_height - 4, - background_color); - - LLColor4 bar_color = gColors.getColor("LoginProgressBarFgColor"); - bar_color.mV[3] = alpha; - bar_fg_imagep->draw( - bar_left + 2, - bar_bottom + 2, - llround((bar_width - 4) * (mPercentDone / 100.f)), - bar_height - 4, - bar_color); - - S32 line_three_y = line_two_y - LINE_SPACING * 3; - - // draw the message if there is one - if(!mMessage.empty()) - { - LLColor4 text_message_color = gColors.getColor("LoginProgressBoxTextColor"); - LLWString wmessage = utf8str_to_wstring(mMessage); - const F32 MAX_PIXELS = 640.0f; - S32 chars_left = wmessage.length(); - S32 chars_this_time = 0; - S32 msgidx = 0; - while(chars_left > 0) - { - chars_this_time = font->maxDrawableChars(wmessage.substr(msgidx).c_str(), - MAX_PIXELS, - MAX_STRING - 1, - TRUE); - LLWString wbuffer = wmessage.substr(msgidx, chars_this_time); - font->render(wbuffer, 0, - (F32)line_x, (F32)line_three_y, - //LLColor4::white, - gColors.getColor("LoginProgressBoxTextColor"), - LLFontGL::HCENTER, LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); - msgidx += chars_this_time; - chars_left -= chars_this_time; - line_three_y -= LINE_SPACING; - } - } - // draw children - LLView::draw(); + LLPanel::draw(); } void LLProgressView::setText(const std::string& text) { - mText = text; + getChild<LLTextBox>("progress_text")->setWrappedText(LLStringExplicit(text)); } void LLProgressView::setPercent(const F32 percent) { - mPercentDone = llclamp(percent, 0.f, 100.f); + mProgressBar->setPercent(percent); } void LLProgressView::setMessage(const std::string& msg) { mMessage = msg; + mURLInMessage = mMessage.find( "http://" ) != std::string::npos; + + getChild<LLTextBox>("message_text")->setWrappedText(LLStringExplicit(mMessage)); + getChild<LLTextBox>("message_text")->setHoverActive(mURLInMessage); } void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label) @@ -416,3 +235,25 @@ void LLProgressView::onCancelButtonClicked(void*) sInstance->setVisible(FALSE); } } + +// static +void LLProgressView::onClickMessage(void* data) +{ + LLProgressView* viewp = (LLProgressView*)data; + if ( ! viewp->mMessage.empty() ) + { + std::string url_to_open( "" ); + + size_t start_pos = viewp->mMessage.find( "http://" ); + if ( start_pos != std::string::npos ) + { + size_t end_pos = viewp->mMessage.find_first_of( " \n\r\t", start_pos ); + if ( end_pos != std::string::npos ) + url_to_open = viewp->mMessage.substr( start_pos, end_pos - start_pos ); + else + url_to_open = viewp->mMessage.substr( start_pos ); + + LLWeb::loadURLExternal( url_to_open ); + } + } +} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 84ae8f6e825..d29439635ee 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -37,16 +37,17 @@ class LLImageRaw; class LLButton; +class LLProgressBar; class LLProgressView : public LLPanel { public: LLProgressView(const std::string& name, const LLRect& rect); virtual ~LLProgressView(); + + BOOL postBuild(); /*virtual*/ void draw(); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); @@ -61,16 +62,18 @@ class LLProgressView : public LLPanel void setCancelButtonVisible(BOOL b, const std::string& label); static void onCancelButtonClicked( void* ); + static void onClickMessage(void*); protected: + LLProgressBar* mProgressBar; F32 mPercentDone; - std::string mText; std::string mMessage; LLButton* mCancelBtn; LLFrameTimer mFadeTimer; LLFrameTimer mProgressTimer; LLRect mOutlineRect; bool mMouseDownInActiveArea; + bool mURLInMessage; static LLProgressView* sInstance; }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index ca310cf8e47..3de0cf80ce5 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -113,6 +113,7 @@ #include "llinventorymodel.h" #include "llinventoryview.h" #include "llkeyboard.h" +#include "llloginhandler.h" // gLoginHandler, SLURL support #include "llpanellogin.h" #include "llmutelist.h" #include "llnotify.h" @@ -654,16 +655,23 @@ bool idle_startup() // // Log on to system // - if ((!gLoginHandler.mFirstName.empty() && - !gLoginHandler.mLastName.empty() && - !gLoginHandler.mWebLoginKey.isNull()) - || gLoginHandler.parseDirectLogin(LLStartUp::sSLURLCommand) ) + if (!LLStartUp::sSLURLCommand.empty()) { - firstname = gLoginHandler.mFirstName; - lastname = gLoginHandler.mLastName; - web_login_key = gLoginHandler.mWebLoginKey; + // this might be a secondlife:///app/login URL + gLoginHandler.parseDirectLogin(LLStartUp::sSLURLCommand); + } + if (!gLoginHandler.getFirstName().empty() + || !gLoginHandler.getLastName().empty() + || !gLoginHandler.getWebLoginKey().isNull() ) + { + // We have at least some login information on a SLURL + firstname = gLoginHandler.getFirstName(); + lastname = gLoginHandler.getLastName(); + web_login_key = gLoginHandler.getWebLoginKey(); - show_connect_box = false; + // Show the login screen if we don't have everything + show_connect_box = + firstname.empty() || lastname.empty() || web_login_key.isNull(); } else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) { @@ -814,11 +822,11 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { //reset the values that could have come in from a slurl - if (!gLoginHandler.mWebLoginKey.isNull()) + if (!gLoginHandler.getWebLoginKey().isNull()) { - firstname = gLoginHandler.mFirstName; - lastname = gLoginHandler.mLastName; - web_login_key = gLoginHandler.mWebLoginKey; + firstname = gLoginHandler.getFirstName(); + lastname = gLoginHandler.getLastName(); + web_login_key = gLoginHandler.getWebLoginKey(); } if (show_connect_box) @@ -1779,6 +1787,8 @@ bool idle_startup() gFrameIntervalSeconds = 0.f; } + // Initialize FOV + LLViewerCamera::getInstance()->setView(gSavedSettings.getF32("CameraAngle")); // Make sure agent knows correct aspect ratio LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWindowDisplayHeight()); if (gViewerWindow->mWindow->getFullscreen()) @@ -3947,8 +3957,9 @@ bool LLStartUp::dispatchURL() // ok, if we've gotten this far and have a startup URL if (!sSLURLCommand.empty()) { - const bool from_external_browser = true; - LLURLDispatcher::dispatch(sSLURLCommand, from_external_browser); + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(sSLURLCommand, web, trusted_browser); } else if (LLURLSimString::parse()) { @@ -3964,8 +3975,9 @@ bool LLStartUp::dispatchURL() || (dy*dy > SLOP*SLOP) ) { std::string url = LLURLSimString::getURL(); - const bool from_external_browser = true; - LLURLDispatcher::dispatch(url, from_external_browser); + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, web, trusted_browser); } return true; } diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index ac80f1b6692..278f7ea9d14 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -757,7 +757,7 @@ static void onClickParcelInfo(void* data) static void onClickBalance(void* data) { - LLFloaterBuyCurrency::buyCurrency(); + onClickBuyCurrency(data); } static void onClickBuyCurrency(void* data) diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp index 2d3fb566e08..bc8c353de04 100644 --- a/indra/newview/llstylemap.cpp +++ b/indra/newview/llstylemap.cpp @@ -47,13 +47,13 @@ LLStyleMap::~LLStyleMap() LLStyleMap &LLStyleMap::instance() { - static LLStyleMap mStyleMap; - return mStyleMap; + static LLStyleMap style_map; + return style_map; } // This is similar to the [] accessor except that if the entry doesn't already exist, // then this will create the entry. -const LLStyleSP &LLStyleMap::lookup(const LLUUID &source) +const LLStyleSP &LLStyleMap::lookupAgent(const LLUUID &source) { // Find this style in the map or add it if not. This map holds links to residents' profiles. if (find(source) == end()) @@ -77,6 +77,37 @@ const LLStyleSP &LLStyleMap::lookup(const LLUUID &source) return (*this)[source]; } +// This is similar to lookupAgent for any generic URL encoded style. +const LLStyleSP &LLStyleMap::lookup(const LLUUID& id, const std::string& link) +{ + // Find this style in the map or add it if not. + iterator iter = find(id); + if (iter == end()) + { + LLStyleSP style(new LLStyle); + style->setVisible(true); + style->setFontName(LLStringUtil::null); + if (id != LLUUID::null && !link.empty()) + { + style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); + style->setLinkHREF(link); + } + else + style->setColor(LLColor4::white); + (*this)[id] = style; + } + else + { + LLStyleSP style = (*iter).second; + if ( style->getLinkHREF() != link ) + { + style->setLinkHREF(link); + } + } + + return (*this)[id]; +} + void LLStyleMap::update() { for (style_map_t::iterator iter = begin(); iter != end(); ++iter) diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h index fbf12a04a38..8d9da8e3b24 100644 --- a/indra/newview/llstylemap.h +++ b/indra/newview/llstylemap.h @@ -47,7 +47,8 @@ class LLStyleMap : public style_map_t LLStyleMap(); ~LLStyleMap(); // Just like the [] accessor but it will add the entry in if it doesn't exist. - const LLStyleSP &lookup(const LLUUID &source); + const LLStyleSP &lookupAgent(const LLUUID &source); + const LLStyleSP &lookup(const LLUUID &source, const std::string& link); static LLStyleMap &instance(); // Forces refresh of the entries, call when something changes (e.g. link color). diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 7bdea15ac44..29dbc08fae1 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -111,7 +111,9 @@ class LLFloaterTexturePicker : public LLFloater const std::string& label, PermissionMask immediate_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, - BOOL can_apply_immediately); + BOOL can_apply_immediately, + const std::string& fallback_image_name); + virtual ~LLFloaterTexturePicker(); // LLView overrides @@ -164,12 +166,13 @@ class LLFloaterTexturePicker : public LLFloater LLTextureCtrl* mOwner; LLUUID mImageAssetID; // Currently selected texture + std::string mFallbackImageName; // What to show if currently selected texture is null. LLUUID mWhiteImageAssetID; LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. LLUUID mOriginalImageAssetID; - std::string mLabel; + std::string mLabel; LLTextBox* mTentativeLabel; LLTextBox* mResolutionLabel; @@ -194,7 +197,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( const std::string& label, PermissionMask immediate_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, - BOOL can_apply_immediately) + BOOL can_apply_immediately, + const std::string& fallback_image_name) : LLFloater( std::string("texture picker"), rect, @@ -203,6 +207,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( TEX_PICKER_MIN_WIDTH, TEX_PICKER_MIN_HEIGHT ), mOwner( owner ), mImageAssetID( owner->getImageAssetID() ), + mFallbackImageName( fallback_image_name ), mWhiteImageAssetID( gSavedSettings.getString( "UIImgWhiteUUID" ) ), mOriginalImageAssetID(owner->getImageAssetID()), mLabel(label), @@ -549,6 +554,11 @@ void LLFloaterTexturePicker::draw() mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); } + else if (!mFallbackImageName.empty()) + { + mTexturep = gImageList.getImageFromFile(mFallbackImageName); + mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); + } if (mTentativeLabel) { @@ -1130,7 +1140,9 @@ void LLTextureCtrl::showPicker(BOOL take_focus) mLabel, mImmediateFilterPermMask, mNonImmediateFilterPermMask, - mCanApplyImmediately); + mCanApplyImmediately, + mFallbackImageName); + mFloaterHandle = floaterp->getHandle(); gFloaterView->getParentFloater(this)->addDependentFloater(floaterp); @@ -1289,15 +1301,21 @@ void LLTextureCtrl::draw() { mBorder->setKeyboardFocusHighlight(hasFocus()); - if (mImageAssetID.isNull() || !mValid) + if (!mValid) { mTexturep = NULL; } - else + else if (!mImageAssetID.isNull()) { mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); } + else if (!mFallbackImageName.empty()) + { + // Show fallback image. + mTexturep = gImageList.getImageFromFile(mFallbackImageName); + mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); + } // Border LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index cf83c628b84..5e369ec29ec 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -115,9 +115,12 @@ class LLTextureCtrl const LLUUID& getImageAssetID() const { return mImageAssetID; } void setDefaultImageAssetID( const LLUUID& id ) { mDefaultImageAssetID = id; } + const LLUUID& getDefaultImageAssetID() const { return mDefaultImageAssetID; } const std::string& getDefaultImageName() const { return mDefaultImageName; } - const LLUUID& getDefaultImageAssetID() const { return mDefaultImageAssetID; } + + void setFallbackImageName( const std::string& name ) { mFallbackImageName = name; } + const std::string& getFallbackImageName() const { return mFallbackImageName; } void setCaption(const std::string& caption); void setCanApplyImmediately(BOOL b); @@ -163,6 +166,7 @@ class LLTextureCtrl LLUUID mImageItemID; LLUUID mImageAssetID; LLUUID mDefaultImageAssetID; + std::string mFallbackImageName; std::string mDefaultImageName; LLHandle<LLFloater> mFloaterHandle; LLTextBox* mTentativeLabel; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 5f26155bc0e..477146a473b 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -64,26 +64,33 @@ class LLURLDispatcherImpl static bool isSLURLCommand(const std::string& url); - static bool dispatch(const std::string& url, bool from_external_browser); + static bool dispatch(const std::string& url, + LLWebBrowserCtrl* web, + bool trusted_browser); // returns true if handled or explicitly blocked. static bool dispatchRightClick(const std::string& url); private: static bool dispatchCore(const std::string& url, - bool from_external_browser, bool right_mouse); + bool right_mouse, + LLWebBrowserCtrl* web, + bool trusted_browser); // handles both left and right click - static bool dispatchHelp(const std::string& url, BOOL right_mouse); + static bool dispatchHelp(const std::string& url, bool right_mouse); // Handles sl://app.floater.html.help by showing Help floater. // Returns true if handled. - static bool dispatchApp(const std::string& url, bool from_external_browser, BOOL right_mouse); + static bool dispatchApp(const std::string& url, + bool right_mouse, + LLWebBrowserCtrl* web, + bool trusted_browser); // Handles secondlife:///app/agent/<agent_id>/about and similar // by showing panel in Search floater. // Returns true if handled or explicitly blocked. - static bool dispatchRegion(const std::string& url, BOOL right_mouse); + static bool dispatchRegion(const std::string& url, bool right_mouse); // handles secondlife://Ahern/123/45/67/ // Returns true if handled. @@ -127,11 +134,14 @@ bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url) } // static -bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool from_external_browser, bool right_mouse) +bool LLURLDispatcherImpl::dispatchCore(const std::string& url, + bool right_mouse, + LLWebBrowserCtrl* web, + bool trusted_browser) { if (url.empty()) return false; if (dispatchHelp(url, right_mouse)) return true; - if (dispatchApp(url, from_external_browser, right_mouse)) return true; + if (dispatchApp(url, right_mouse, web, trusted_browser)) return true; if (dispatchRegion(url, right_mouse)) return true; /* @@ -145,23 +155,27 @@ bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool from_externa } // static -bool LLURLDispatcherImpl::dispatch(const std::string& url, bool from_external_browser) +bool LLURLDispatcherImpl::dispatch(const std::string& url, + LLWebBrowserCtrl* web, + bool trusted_browser) { llinfos << "url: " << url << llendl; const bool right_click = false; - return dispatchCore(url, from_external_browser, right_click); + return dispatchCore(url, right_click, web, trusted_browser); } // static bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url) { llinfos << "url: " << url << llendl; - const bool from_external_browser = false; const bool right_click = true; - return dispatchCore(url, from_external_browser, right_click); + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + return dispatchCore(url, right_click, web, trusted_browser); } + // static -bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse) +bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, bool right_mouse) { #if LL_LIBXUL_ENABLED if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) @@ -175,8 +189,9 @@ bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse) // static bool LLURLDispatcherImpl::dispatchApp(const std::string& url, - bool from_external_browser, - BOOL right_mouse) + bool right_mouse, + LLWebBrowserCtrl* web, + bool trusted_browser) { if (!isSLURL(url)) { @@ -189,12 +204,12 @@ bool LLURLDispatcherImpl::dispatchApp(const std::string& url, std::string cmd = pathArray.get(0); pathArray.erase(0); // erase "cmd" bool handled = LLCommandDispatcher::dispatch( - cmd, from_external_browser, pathArray, uri.queryMap()); + cmd, pathArray, uri.queryMap(), web, trusted_browser); return handled; } // static -bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse) +bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mouse) { if (!isSLURL(url)) { @@ -359,10 +374,13 @@ std::string LLURLDispatcherImpl::stripProtocol(const std::string& url) class LLTeleportHandler : public LLCommandHandler { public: - // not allowed from outside the app - LLTeleportHandler() : LLCommandHandler("teleport", false) { } + // Teleport requests *must* come from a trusted browser + // inside the app, otherwise a malicious web page could + // cause a constant teleport loop. JC + LLTeleportHandler() : LLCommandHandler("teleport", true) { } - bool handle(const LLSD& tokens, const LLSD& queryMap) + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) { // construct a "normal" SLURL, resolve the region to // a global position, and teleport to it @@ -401,10 +419,13 @@ bool LLURLDispatcher::isSLURLCommand(const std::string& url) } // static -bool LLURLDispatcher::dispatch(const std::string& url, bool from_external_browser) +bool LLURLDispatcher::dispatch(const std::string& url, + LLWebBrowserCtrl* web, + bool trusted_browser) { - return LLURLDispatcherImpl::dispatch(url, from_external_browser); + return LLURLDispatcherImpl::dispatch(url, web, trusted_browser); } + // static bool LLURLDispatcher::dispatchRightClick(const std::string& url) { @@ -414,13 +435,20 @@ bool LLURLDispatcher::dispatchRightClick(const std::string& url) // static bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url) { - // text editors are by definition internal to our code - const bool from_external_browser = false; - return LLURLDispatcherImpl::dispatch(url, from_external_browser); + // *NOTE: Text editors are considered sources of trusted URLs + // in order to make objectim and avatar profile links in chat + // history work. While a malicious resident could chat an app + // SLURL, the receiving resident will see it and must affirmatively + // click on it. + // *TODO: Make this trust model more refined. JC + const bool trusted_browser = true; + LLWebBrowserCtrl* web = NULL; + return LLURLDispatcherImpl::dispatch(url, web, trusted_browser); } // static -std::string LLURLDispatcher::buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z) +std::string LLURLDispatcher::buildSLURL(const std::string& regionname, + S32 x, S32 y, S32 z) { std::string slurl = SLURL_SLURL_PREFIX + regionname + llformat("/%d/%d/%d",x,y,z); slurl = LLWeb::escapeURL( slurl ); diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h index a8629626b1b..6640ca11b35 100644 --- a/indra/newview/llurldispatcher.h +++ b/indra/newview/llurldispatcher.h @@ -31,6 +31,9 @@ #ifndef LLURLDISPATCHER_H #define LLURLDISPATCHER_H +class LLWebBrowserCtrl; + + class LLURLDispatcher { public: @@ -40,13 +43,20 @@ class LLURLDispatcher static bool isSLURLCommand(const std::string& url); // Is this a special secondlife://app/ URL? - static bool dispatch(const std::string& url, bool from_external_browser); + static bool dispatch(const std::string& url, + LLWebBrowserCtrl* web, + bool trusted_browser); // At startup time and on clicks in internal web browsers, // teleport, open map, or run requested command. - // Handles: + // @param url // secondlife://RegionName/123/45/67/ // secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show // sl://app/foo/bar + // @param web + // Pointer to LLWebBrowserCtrl sending URL, can be NULL + // @param trusted_browser + // True if coming inside the app AND from a brower instance + // that navigates to trusted (Linden Lab) pages. // Returns true if someone handled the URL. static bool dispatchRightClick(const std::string& url); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 5f6fcb70e3c..f9ced0f53fd 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -138,9 +138,9 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, mVelocityStat.addValue(dpos); mAngularVelocityStat.addValue(drot); // update pixel meter ratio using default fov, not modified one - mPixelMeterRatio = mViewHeightInPixels / (2.f*tanf(mCameraFOVDefault*0.5)); + mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); // update screen pixel area - mScreenPixelArea =(S32)((F32)mViewHeightInPixels * ((F32)mViewHeightInPixels * mAspect)); + mScreenPixelArea =(S32)((F32)getViewHeightInPixels() * ((F32)getViewHeightInPixels() * getAspect())); } const LLMatrix4 &LLViewerCamera::getProjection() const @@ -732,3 +732,38 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) } return all_verts; } + +// changes local camera and broadcasts change +/* virtual */ void LLViewerCamera::setView(F32 vertical_fov_rads) +{ + F32 old_fov = LLViewerCamera::getInstance()->getDefaultFOV(); + + // cap the FoV + vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); + + if (vertical_fov_rads == old_fov) return; + + // send the new value to the simulator + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_AgentFOV); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); + + msg->nextBlockFast(_PREHASH_FOVBlock); + msg->addU32Fast(_PREHASH_GenCounter, 0); + msg->addF32Fast(_PREHASH_VerticalAngle, vertical_fov_rads); + + gAgent.sendReliableMessage(); + + // sync the camera with the new value + LLCamera::setView(vertical_fov_rads); // call base implementation +} + +void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) { + vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); + setView(vertical_fov_rads); + mCameraFOVDefault = vertical_fov_rads; +} + diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index cc37851d050..8aec405bf0d 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -55,9 +55,6 @@ class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> public: LLViewerCamera(); -// const LLVector3 &getPositionAgent() const; -// const LLVector3d &getPositionGlobal() const; - void updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest); @@ -80,7 +77,10 @@ class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right); LLVector3 roundToPixel(const LLVector3 &pos_agent); - void setDefaultFOV(F32 fov) { mCameraFOVDefault = fov; } + // Sets the current matrix + /* virtual */ void setView(F32 vertical_fov_rads); + // Sets the current matrix AND remembers result as default view + void setDefaultFOV(F32 vertical_fov_rads); F32 getDefaultFOV() { return mCameraFOVDefault; } BOOL cameraUnderWater() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e8ce3e02eac..6e37e6253f0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -107,6 +107,7 @@ #include "llfloatergroups.h" #include "llfloaterhtml.h" #include "llfloaterhtmlhelp.h" +#include "llfloaterhtmlsimple.h" #include "llfloaterhud.h" #include "llfloaterinspect.h" #include "llfloaterlagmeter.h" @@ -116,6 +117,7 @@ #include "llfloatermute.h" #include "llfloateropenobject.h" #include "llfloaterpermissionsmgr.h" +#include "llfloaterperms.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" #include "llfloaterregioninfo.h" @@ -329,7 +331,6 @@ void handle_agent_stop_moving(void*); void print_packets_lost(void*); void drop_packet(void*); void velocity_interpolate( void* data ); -void update_fov(S32 increments); void toggle_wind_audio(void); void toggle_water_audio(void); void handle_rebake_textures(void*); @@ -358,7 +359,8 @@ void run_vectorize_perf_test(void *) // Debug UI void handle_web_search_demo(void*); -void handle_slurl_test(void*); +void handle_web_browser_test(void*); +void handle_buy_currency_test(void*); void handle_save_to_xml(void*); void handle_load_from_xml(void*); @@ -1018,7 +1020,8 @@ extern BOOL gDebugSelectMgr; void init_debug_ui_menu(LLMenuGL* menu) { - menu->append(new LLMenuItemCallGL("SLURL Test", &handle_slurl_test)); + menu->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test)); + menu->append(new LLMenuItemCallGL("Buy Currency Test", &handle_buy_currency_test)); menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui)); menu->append(new LLMenuItemToggleGL("Async Keystrokes", &gHandleKeysAsync)); menu->append(new LLMenuItemCallGL( "Dump SelectMgr", &dump_select_mgr)); @@ -3048,86 +3051,6 @@ void velocity_interpolate( void* data ) } -void update_fov(S32 increments) -{ - F32 old_fov = LLViewerCamera::getInstance()->getDefaultFOV(); - // for each increment, FoV is 20% bigger - F32 new_fov = old_fov * pow(1.2f, increments); - - // cap the FoV - new_fov = llclamp(new_fov, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); - - if (new_fov != old_fov) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentFOV); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); - - msg->nextBlockFast(_PREHASH_FOVBlock); - msg->addU32Fast(_PREHASH_GenCounter, 0); - msg->addF32Fast(_PREHASH_VerticalAngle, new_fov); - - gAgent.sendReliableMessage(); - - // force agent to update dirty patches - LLViewerCamera::getInstance()->setDefaultFOV(new_fov); - LLViewerCamera::getInstance()->setView(new_fov); - } -} - -class LLViewZoomOut : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - update_fov(1); - return true; - } -}; - -class LLViewZoomIn : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - update_fov(-1); - return true; - } -}; - -class LLViewZoomDefault : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - F32 old_fov = LLViewerCamera::getInstance()->getView(); - // for each increment, FoV is 20% bigger - F32 new_fov = DEFAULT_FIELD_OF_VIEW; - - if (new_fov != old_fov) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentFOV); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); - msg->nextBlockFast(_PREHASH_FOVBlock); - msg->addU32Fast(_PREHASH_GenCounter, 0); - msg->addF32Fast(_PREHASH_VerticalAngle, new_fov); - - gAgent.sendReliableMessage(); - - // force agent to update dirty patches - LLViewerCamera::getInstance()->setDefaultFOV(new_fov); - LLViewerCamera::getInstance()->setView(new_fov); - } - return true; - } -}; - - - void toggle_wind_audio(void) { if (gAudiop) @@ -4291,12 +4214,7 @@ class LLToolsStopAllAnimations : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp) - { - avatarp->deactivateAllMotions(); - avatarp->startDefaultMotions(); - } + gAgent.stopCurrentAnimations(); return true; } }; @@ -5291,6 +5209,10 @@ class LLShowFloater : public view_listener_t { LLFloaterBeacons::toggleInstance(LLSD()); } + else if (floater_name == "perm prefs") + { + LLFloaterPerms::toggleInstance(LLSD()); + } return true; } }; @@ -5474,7 +5396,6 @@ class LLLandEdit : public view_listener_t LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal ); - gFloaterTools->showMore(TRUE); gFloaterView->bringToFront( gFloaterTools ); // Switch to land edit toolset @@ -7003,7 +6924,7 @@ void handle_save_to_xml(void*) LLFloater* frontmost = gFloaterView->getFrontmost(); if (!frontmost) { - gViewerWindow->alertXml("NoFrontmostFloater"); + gViewerWindow->alertXml("NoFrontmostFloater"); return; } @@ -7036,17 +6957,54 @@ void handle_load_from_xml(void*) } } -void handle_slurl_test(void*) +void handle_web_browser_test(void*) { const bool open_links_externally = false; const bool open_app_slurls = true; LLFloaterHtml::getInstance()->show( "http://secondlife.com/app/search/slurls.html", - "SLURL Test", + "Web Browser Test", open_links_externally, open_app_slurls); } +void handle_buy_currency_test(void*) +{ + std::string url = + "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]"; + + LLStringUtil::format_map_t replace; + replace["[AGENT_ID]"] = gAgent.getID().asString(); + replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString(); + + // *TODO: Replace with call to LLUI::getLanguage() after windows-setup + // branch merges in. JC + std::string language = "en-us"; + language = gSavedSettings.getString("Language"); + if (language.empty() || language == "default") + { + language = gSavedSettings.getString("InstallLanguage"); + } + if (language.empty() || language == "default") + { + language = gSavedSettings.getString("SystemLanguage"); + } + if (language.empty() || language == "default") + { + language = "en-us"; + } + + replace["[LANGUAGE]"] = language; + LLStringUtil::format(url, replace); + + llinfos << "buy currency url " << url << llendl; + + LLFloaterHtmlSimple* floater = LLFloaterHtmlSimple::showInstance(url); + // Needed so we can use secondlife:///app/floater/self/close SLURLs + floater->setTrusted(true); + floater->center(); +} + void handle_rebake_textures(void*) { LLVOAvatar* avatar = gAgent.getAvatarObject(); @@ -7418,6 +7376,24 @@ static void addMenu(view_listener_t *menu, const std::string& name) void initialize_menus() { + // A parameterized event handler used as ctrl-8/9/0 zoom controls below. + class LLZoomer : public view_listener_t + { + public: + // The "mult" parameter says whether "val" is a multiplier or used to set the value. + LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {} + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal; + LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad); + gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it. + return true; + } + private: + F32 mVal; + bool mMult; + }; + // File menu init_menu_file(); @@ -7457,9 +7433,9 @@ void initialize_menus() addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); - addMenu(new LLViewZoomOut(), "View.ZoomOut"); - addMenu(new LLViewZoomIn(), "View.ZoomIn"); - addMenu(new LLViewZoomDefault(), "View.ZoomDefault"); + addMenu(new LLZoomer(1.2f), "View.ZoomOut"); + addMenu(new LLZoomer(1/1.2f), "View.ZoomIn"); + addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault"); addMenu(new LLViewFullscreen(), "View.Fullscreen"); addMenu(new LLViewDefaultUISize(), "View.DefaultUISize"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 27badfb1ddc..9448a00e68d 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -43,6 +43,7 @@ #include "llfloatersnapshot.h" #include "llinventorymodel.h" // gInventory #include "llresourcedata.h" +#include "llfloaterperms.h" #include "llstatusbar.h" #include "llviewercontrol.h" // gSavedSettings #include "llviewerimagelist.h" @@ -322,7 +323,9 @@ class LLFileUploadBulk : public view_listener_t LLStringUtil::stripNonprintable(asset_name); LLStringUtil::trim(asset_name); - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); // file + upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms()); + // *NOTE: Ew, we don't iterate over the file list here, // we handle the next files in upload_done_callback() } @@ -515,7 +518,9 @@ void upload_new_resource(const std::string& src_filename, std::string name, std::string desc, S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, - U32 next_owner_perm, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, const std::string& display_name, LLAssetStorage::LLStoreAssetCallback callback, void *userdata) @@ -803,7 +808,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, t_disp_name = src_filename; } upload_new_resource(tid, asset_type, name, desc, compression_info, // tid - destination_folder_type, inv_type, next_owner_perm, + destination_folder_type, inv_type, next_owner_perms, group_perms, everyone_perms, display_name, callback, userdata); } else @@ -875,15 +880,15 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); if(folder_id.notNull()) { - U32 next_owner_perm = data->mNextOwnerPerm; - if(PERM_NONE == next_owner_perm) + U32 next_owner_perms = data->mNextOwnerPerm; + if(PERM_NONE == next_owner_perms) { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; + next_owner_perms = PERM_MOVE | PERM_TRANSFER; } create_inventory_item(gAgent.getID(), gAgent.getSessionID(), folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), data->mAssetInfo.getDescription(), data->mAssetInfo.mType, - data->mInventoryType, NOT_WEARABLE, next_owner_perm, + data->mInventoryType, NOT_WEARABLE, next_owner_perms, LLPointer<LLInventoryCallback>(NULL)); } else @@ -925,7 +930,9 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty std::string desc, S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, - U32 next_owner_perm, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, const std::string& display_name, LLAssetStorage::LLStoreAssetCallback callback, void *userdata) @@ -984,10 +991,14 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty body["inventory_type"] = LLInventoryType::lookup(inv_type); body["name"] = name; body["description"] = desc; + body["next_owner_mask"] = LLSD::Integer(next_owner_perms); + body["group_mask"] = LLSD::Integer(group_perms); + body["everyone_mask"] = LLSD::Integer(everyone_perms); - std::ostringstream llsdxml; - LLSDSerialize::toXML(body, llsdxml); - lldebugs << "posting body to capability: " << llsdxml.str() << llendl; + //std::ostringstream llsdxml; + //LLSDSerialize::toPrettyXML(body, llsdxml); + //llinfos << "posting body to capability: " << llsdxml.str() << llendl; + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); } else @@ -1015,7 +1026,7 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty data->mAssetInfo.mType = asset_type; data->mAssetInfo.mCreatorID = gAgentID; data->mInventoryType = inv_type; - data->mNextOwnerPerm = next_owner_perm; + data->mNextOwnerPerm = next_owner_perms; data->mUserData = userdata; data->mAssetInfo.setName(name); data->mAssetInfo.setDescription(desc); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index f43e5bfc92c..36dd1d78b79 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -40,21 +40,29 @@ class LLTransactionID; void init_menu_file(); -void upload_new_resource(const std::string& src_filename, std::string name, - std::string desc, S32 compression_info, +void upload_new_resource(const std::string& src_filename, + std::string name, + std::string desc, + S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, - U32 next_owner_perm = 0x0, // PERM_NONE + U32 next_owner_perms = 0x0, // PERM_NONE + U32 group_perms = 0x0, // PERM_NONE + U32 everyone_perms = 0x0, // PERM_NONE const std::string& display_name = LLStringUtil::null, LLAssetStorage::LLStoreAssetCallback callback = NULL, void *userdata = NULL); -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, +void upload_new_resource(const LLTransactionID &tid, + LLAssetType::EType type, std::string name, - std::string desc, S32 compression_info, + std::string desc, + S32 compression_info, LLAssetType::EType destination_folder_type, LLInventoryType::EType inv_type, - U32 next_owner_perm = 0x0, // PERM_NONE + U32 next_owner_perms = 0x0, // PERM_NONE + U32 group_perms = 0x0, // PERM_NONE + U32 everyone_perms = 0x0, // PERM_NONE const std::string& display_name = LLStringUtil::null, LLAssetStorage::LLStoreAssetCallback callback = NULL, void *userdata = NULL); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 426edb37caf..eeedb982505 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1803,15 +1803,51 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_FROM_TASK: - if (is_busy && !is_owned_by_me) { - return; + if (is_busy && !is_owned_by_me) + { + return; + } + chat.mText = name + separator_string + message.substr(message_offset); + chat.mFromName = name; + + // Build a link to open the object IM info window. + std::string location = ll_safe_string((char*)binary_bucket,binary_bucket_size); + + LLSD query_string; + query_string["owner"] = from_id; + query_string["slurl"] = location.c_str(); + query_string["name"] = name; + if (from_group) + { + query_string["groupowned"] = "true"; + } + + if (session_id.notNull()) + { + chat.mFromID = session_id; + } + else + { + // This message originated on a region without the updated code for task id and slurl information. + // We just need a unique ID for this object that isn't the owner ID. + // If it is the owner ID it will overwrite the style that contains the link to that owner's profile. + // This isn't ideal - it will make 1 style for all objects owned by the the same person/group. + // This works because the only thing we can really do in this case is show the owner name and link to their profile. + chat.mFromID = from_id ^ gAgent.getSessionID(); + } + + std::ostringstream link; + link << "secondlife:///app/objectim/" << session_id + << LLURI::mapToQueryString(query_string); + + chat.mURL = link.str(); + + // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because + // IMs from objcts don't open IM sessions. + chat.mSourceType = CHAT_SOURCE_OBJECT; + LLFloaterChat::addChat(chat, FALSE, FALSE); } - chat.mText = name + separator_string + message.substr(message_offset); - // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because - // IMs from objcts don't open IM sessions. - chat.mSourceType = CHAT_SOURCE_OBJECT; - LLFloaterChat::addChat(chat, FALSE, FALSE); break; case IM_FROM_TASK_AS_ALERT: if (is_busy && !is_owned_by_me) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 38e376b511e..edb339eab48 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1342,8 +1342,9 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) case SLURL_MESSAGE_TYPE: // received URL std::string url = (const char*)data; - const bool from_external_browser = true; - if (LLURLDispatcher::dispatch(url, from_external_browser)) + LLWebBrowserCtrl* web = NULL; + const bool trusted_browser = false; + if (LLURLDispatcher::dispatch(url, web, trusted_browser)) { // bring window to foreground, as it has just been "launched" from a URL mWindow->bringToFront(); diff --git a/indra/newview/skins/default/textures/default_land_picture.j2c b/indra/newview/skins/default/textures/default_land_picture.j2c new file mode 100644 index 0000000000000000000000000000000000000000..34df0291ae08c9303151a2d68942f473d718dd32 GIT binary patch literal 24492 zcmV)cK&Zd}PybN>F8}}l00961009610000000000009610096100000000000|x;C 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 Ph!&<P*PAhfG(!K`o5q&w literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/default_profile_picture.j2c b/indra/newview/skins/default/textures/default_profile_picture.j2c new file mode 100644 index 0000000000000000000000000000000000000000..c53a22e8165c6e9fb1e6039644b113273a9b79b4 GIT binary patch literal 6128 zcmV<M7Z2$FPybN>F8}}l004jh004jh0000000000004jh004jh00000000000|x;C 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%0AVs~4<ghexAyh}jOC|3jGL#%`ts#2zaVmsq zE_{XuM-rL*1RS+9P13Gz(9T$iLG1W(H2T2*Na%sNhd+mVBBwQ1_syh-;J@%eNy=i2 zko(P<pAB_w&HzRY4(Y3y^;O*oDX1>`?V#57@L~(yppGgdfBd)K<mzNT9ZWg_d-*2O z6Epay24nYZE0jVtXMvoAjWCDr#+Zrn3u)VAZl$(~-pzeWJ#RU<lwKao2EIc$t}ec( z<|si^h7X{FO6TW61zWU9g4AuWzZt(;Q1{6z)2%p6iSFeI<&HGsz<J)F&??QXL~nWN zZq%Lk&Y{v{a=C4|eTGKgz%%*Wo(O0<a?g}=csVb~>qRT;Z5g6a=dJojF*)2Af7ssS z=c3i_euBMXp>&xb%Ysr?d*2^S3shVl4mPggr2f-#Jk#p7sALOUr`TRP=z=zDnJX|i zOm?E)2rtM@nZ+l;vQ{890AqLkmPe4kr`;PZ(I*j92j(>{$;mW+_s-=8SvU`banLT$ zBux4@xk(JsD?$W?;Oc=6<3=cPJzshEqQ4ePLrU5(>S#lVwgp5Q*2xbREecsTisZdT z4YP5V)EO<(<AKg75q9B-c;lx+bjsujV((Zp-E<Kl$?@z*NE}Xwc>fQ>zw@_1!F+sU z6xyyU62kXKzXpu1=w8z6S%XZWOKsr(td<QVhn@BUejSkPv#=Ej8-s2pW_BF8URNw! z(tPMYS#t7t=Zp7Bi!nh1%pz#~D$~O-#*?APhw$5`RiVO(nJl_+yo`y`w$01Bqfm>$ zFA0^gzR<;`)dlUP3%7NR1}i#}SBCEKo6l1ur1D{E&F(VzS+}Jp6vTMf_QIM{xV9Cj zvT<!GYx0CGk*}e++`+2Vy){oIDhd9U6?hP=p6xa;#wOjk_6ARs%LfVagu(CQuNH~= zUKtNXfbPr%w0bFd!2xD?$T*M%H&w@@DjG0<9sFafV4Glt+)dCAMMo5olQByE59cCn z8UKF)QKMVSgebA6B1sGQhL<7-_($JgC=rVU3{L`cQ}kJsaETZOF1B6#s06viB*re4 z!m@#EOFH>A=DRJGcDy_BQP<b4vGOPXSZWJb6rpn2beRjF&mzjhfylkxx*NhB(x*Wf zLeTI>5l%&YHeQ(hP9pwuZ&MD*Z`x5V;~u?5>8yO+G|xCA4$OP)Ed5h2ERJ_jq#I?^ z1mkSpa{YLUR@HYl6Lx-U1qt77^S8_CA|%BUccQ7+&Gjh~_khuLXJ+;T7mFY`G}E+^ z2*EA2pm0(#N5U&1=(xJQJhKSC3+<S8Ry*f$IDenV=oB}H&1@qs)ifeH+Lol@P%@yU z4bf163PWe85{wS^HKBRZwH?w9H+vsukn@HN!P{s$nDX}Iw7KgngVO{jl`Mk9&+DIe z%Bv@jB@It{7w@9q$WHpgZU_Y>^chCfgV#@^JV{m43uZ9HdS*lieK~RE)8TNtlJ$+w zFh{}g^gJI8=<t*etUQA+4vv=+58283V}09DS>-DW7Sy$JkWgnmzu6Mk4UmYNo9QYf zgV0u5^0}5_VT)rZSeQ-?>vLPvaM6ReW};47M4%_cl0%CM&g*1mN~W)V<R1v)y3HxX zw!@Rjozr~Z^8%vQ31|Q;k@$$#<gwr|rmhK+)_NUZsHT?ZGOh<(@uELXHr-QDip16P zC+(?R=KMu5lU{M{+<^r17Hrao0=M1-(fB0mPcUmyk@eXEmIE@;yi8inf{B5>YX8~K C!{NpN literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/locked_image.j2c b/indra/newview/skins/default/textures/locked_image.j2c new file mode 100644 index 0000000000000000000000000000000000000000..9e8998d675954d2592b9753bcf461d967a01c4f3 GIT binary patch literal 6140 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 JUTY&3{|`aZ-gN)~ literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 9e1d9b5196d..34c9dea7e64 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -369,4 +369,8 @@ <texture name="skin_thumbnail_default.png" preload="true" /> <texture name="skin_thumbnail_silver.png" preload="true" /> + + <texture name="default_land_picture.j2c"/> + <texture name="default_profile_picture.j2c"/> + <texture name="locked_image.j2c"/> </textures> -- GitLab