diff options
Diffstat (limited to 'indra/newview')
561 files changed, 21627 insertions, 9926 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c577d062f9..7d78ec9e3c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -234,12 +234,14 @@ set(viewer_SOURCE_FILES llfloatercamera.cpp llfloatercamerapresets.cpp llfloaterchatvoicevolume.cpp + llfloaterclassified.cpp llfloatercolorpicker.cpp llfloaterconversationlog.cpp llfloaterconversationpreview.cpp llfloatercreatelandmark.cpp llfloaterdeleteprefpreset.cpp llfloaterdestinations.cpp + llfloaterdisplayname.cpp llfloatereditenvironmentbase.cpp llfloatereditextdaycycle.cpp llfloaterenvironmentadjust.cpp @@ -295,9 +297,11 @@ set(viewer_SOURCE_FILES llfloaterpay.cpp llfloaterperms.cpp llfloaterpostprocess.cpp + llfloaterprofile.cpp llfloaterpreference.cpp llfloaterpreferenceviewadvanced.cpp llfloaterpreviewtrash.cpp + llfloaterprofiletexture.cpp llfloaterproperties.cpp llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp @@ -330,7 +334,6 @@ set(viewer_SOURCE_FILES llfloatervoiceeffect.cpp llfloatervoicevolume.cpp llfloaterwebcontent.cpp - llfloaterwebprofile.cpp llfloaterwhitelistentry.cpp llfloaterwindowsize.cpp llfloaterworldmap.cpp @@ -476,7 +479,6 @@ set(viewer_SOURCE_FILES llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp llpanelmediasettingssecurity.cpp - llpanelme.cpp llpanelnearbymedia.cpp llpanelobject.cpp llpanelobjectinventory.cpp @@ -486,8 +488,6 @@ set(viewer_SOURCE_FILES llpanelpeople.cpp llpanelpeoplemenus.cpp llpanelpermissions.cpp - llpanelpick.cpp - llpanelpicks.cpp llpanelplaceinfo.cpp llpanelplaceprofile.cpp llpanelplaces.cpp @@ -496,6 +496,8 @@ set(viewer_SOURCE_FILES llpanelpresetspulldown.cpp llpanelprimmediacontrols.cpp llpanelprofile.cpp + llpanelprofileclassifieds.cpp + llpanelprofilepicks.cpp llpanelsnapshot.cpp llpanelsnapshotinventory.cpp llpanelsnapshotlocal.cpp @@ -657,6 +659,7 @@ set(viewer_SOURCE_FILES llviewercontrol.cpp llviewercontrollistener.cpp llviewerdisplay.cpp + llviewerdisplayname.cpp llviewerfloaterreg.cpp llviewerfoldertype.cpp llviewergenericmessage.cpp @@ -870,12 +873,14 @@ set(viewer_HEADER_FILES llfloatercamerapresets.h llfloatercamera.h llfloaterchatvoicevolume.h + llfloaterclassified.h llfloatercolorpicker.h llfloaterconversationlog.h llfloaterconversationpreview.h llfloatercreatelandmark.h llfloaterdeleteprefpreset.h llfloaterdestinations.h + llfloaterdisplayname.h llfloatereditenvironmentbase.h llfloatereditextdaycycle.h llfloaterenvironmentadjust.h @@ -934,9 +939,11 @@ set(viewer_HEADER_FILES llfloaterpay.h llfloaterperms.h llfloaterpostprocess.h + llfloaterprofile.h llfloaterpreference.h llfloaterpreferenceviewadvanced.h llfloaterpreviewtrash.h + llfloaterprofiletexture.h llfloaterproperties.h llfloaterregiondebugconsole.h llfloaterregioninfo.h @@ -969,7 +976,6 @@ set(viewer_HEADER_FILES llfloatervoiceeffect.h llfloatervoicevolume.h llfloaterwebcontent.h - llfloaterwebprofile.h llfloaterwhitelistentry.h llfloaterwindowsize.h llfloaterworldmap.h @@ -1105,7 +1111,6 @@ set(viewer_HEADER_FILES llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h llpanelmediasettingssecurity.h - llpanelme.h llpanelnearbymedia.h llpanelobject.h llpanelobjectinventory.h @@ -1115,8 +1120,6 @@ set(viewer_HEADER_FILES llpanelpeople.h llpanelpeoplemenus.h llpanelpermissions.h - llpanelpick.h - llpanelpicks.h llpanelplaceinfo.h llpanelplaceprofile.h llpanelplaces.h @@ -1125,6 +1128,8 @@ set(viewer_HEADER_FILES llpanelpresetspulldown.h llpanelprimmediacontrols.h llpanelprofile.h + llpanelprofileclassifieds.h + llpanelprofilepicks.h llpanelsnapshot.h llpanelteleporthistory.h llpaneltiptoast.h @@ -1287,6 +1292,7 @@ set(viewer_HEADER_FILES llviewercontrol.h llviewercontrollistener.h llviewerdisplay.h + llviewerdisplayname.h llviewerfloaterreg.h llviewerfoldertype.h llviewergenericmessage.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 28179fc1f5..4aa5a3a58e 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.2 +6.6.8 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 3dfe3f6634..2644f5f449 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -167,10 +167,8 @@ icon="Command_Picks_Icon" label_ref="Command_Picks_Label" tooltip_ref="Command_Picks_Tooltip" - execute_function="Floater.ToggleOrBringToFront" - execute_parameters="picks" - is_running_function="Floater.IsOpen" - is_running_parameters="picks" + execute_function="Avatar.TogglePicks" + is_running_function="Avatar.IsPicksTabOpen" /> <command name="places" available_in_toybox="true" diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 55babc88bc..8d5349550f 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -85,7 +85,6 @@ <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/> <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> - <binding key="" mask="NONE" mouse="LMB" command="walk_to"/> <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/> </third_person> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 16d8cd9f06..6861153d43 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -544,17 +544,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AvalinePhoneSeparator</key> - <map> - <key>Comment</key> - <string>Separator of phone parts to have Avaline numbers human readable in Voice Control Panel</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>-</string> - </map> <key>AvatarAxisDeadZone0</key> <map> <key>Comment</key> @@ -1371,7 +1360,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>20.0</real> + <real>40.0</real> </map> <key>DiskCacheDirName</key> <map> @@ -4758,7 +4747,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> + <string>https://search.[GRID]/?query_term=[QUERY]&search_type=[TYPE][COLLECTION]&maturity=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> <key>GuidebookURL</key> <map> @@ -5806,6 +5795,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>DiskCacheVersion</key> + <map> + <key>Comment</key> + <string>Version number of disk cache</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LocalFileSystemBrowsingEnabled</key> <map> <key>Comment</key> @@ -6808,6 +6808,9 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> + <!-- *HACK: On first run, set this to 0 for new users, + otherwise the default is 1 to maintain consistent experience + for existing users. Hardcoded in llnetmap.cpp --> <integer>1</integer> </map> <key>MiniMapScale</key> @@ -6821,6 +6824,17 @@ <key>Value</key> <real>128.0</real> </map> + <key>MiniMapShowPropertyLines</key> + <map> + <key>Comment</key> + <string>Whether or not to show parcel borders on the MiniMap.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>1</real> + </map> <key>MouseSensitivity</key> <map> <key>Comment</key> @@ -7099,13 +7113,13 @@ <key>NonvisibleObjectsInMemoryTime</key> <map> <key>Comment</key> - <string>Number of frames non-visible objects stay in memory before being removed. 0 means never to remove.</string> + <string>Number of frames non-visible objects stay in memory before being removed. 0 means max.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>U32</string> <key>Value</key> - <integer>300</integer> + <integer>64</integer> </map> <key>NoPreload</key> <map> @@ -11022,7 +11036,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>1024</integer> + <integer>2048</integer> </map> <key>SceneLoadLowMemoryBound</key> <map> @@ -15737,6 +15751,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>AllowSelectAvatar</key> + <map> + <key>Comment</key> + <string>Allows user to select and move avatars, move is viewer sided, does not propagate to server, also supresses avatar position updates while avatars are selected</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>WebProfileFloaterRect</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 02d83925ea..b26194f278 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -202,7 +202,7 @@ VARYING vec2 vary_texcoord2; uniform float env_intensity; uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) +#ifdef HAS_ALPHA_MASK uniform float minimum_alpha; #endif @@ -227,11 +227,12 @@ void main() vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); diffcol.rgb *= vertex_color.rgb; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) - - // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points - float bias = 0.001953125; // 1/512, or half an 8-bit quantization - if (diffcol.a < minimum_alpha-bias) +#ifdef HAS_ALPHA_MASK +#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND + if (diffcol.a*vertex_color.a < minimum_alpha) +#else + if (diffcol.a < minimum_alpha) +#endif { discard; } diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml index 2241a12545..6cfc0b0be2 100644 --- a/indra/newview/character/avatar_skeleton.xml +++ b/indra/newview/character/avatar_skeleton.xml @@ -2,15 +2,15 @@ <bone aliases="hip avatar_mPelvis" connected="false" end="0.000 0.000 0.084" group="Torso" name="mPelvis" pivot="0.000000 0.000000 1.067015" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"> <collision_volume end="0.030 0.000 0.095" group="Collision" name="PELVIS" pos="-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17" support="base"/> <collision_volume end="-0.100 0.000 0.000" group="Collision" name="BUTT" pos="-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1" support="base"/> - <bone connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mSpine1" connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mSpine2" connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> <bone aliases="abdomen avatar_mTorso" connected="true" end="-0.015 0.000 0.205" group="Torso" name="mTorso" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"> <collision_volume end="0.028 0.000 0.094" group="Collision" name="BELLY" pos="0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15" support="base"/> <collision_volume end="0.000 0.100 0.000" group="Collision" name="LEFT_HANDLE" pos="0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/> <collision_volume end="0.000 -0.100 0.000" group="Collision" name="RIGHT_HANDLE" pos="0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/> <collision_volume end="-0.100 0.000 0.000" group="Collision" name="LOWER_BACK" pos="0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/> - <bone connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mSpine3" connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mSpine4" connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> <bone aliases="chest avatar_mChest" connected="true" end="-0.010 0.000 0.250" group="Torso" name="mChest" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"> <collision_volume end="-0.096 0.000 0.152" group="Collision" name="CHEST" pos="0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2" support="base"/> <collision_volume end="0.080 0.000 -0.006" group="Collision" name="LEFT_PEC" pos="0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/> @@ -23,58 +23,58 @@ <bone aliases="figureHair avatar_mSkull" connected="false" end="0.000 0.000 0.033" group="Extra" name="mSkull" pivot="0.000000 0.000000 0.079000" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/> <bone aliases="avatar_mEyeRight" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeRight" pivot="0.098466 -0.036000 0.079000" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" support="base"/> <bone aliases="avatar_mEyeLeft" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeLeft" pivot="0.098461 0.036000 0.079000" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/> - <bone connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceRoot" connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceEyeAltRight" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyeAltLeft" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceForeheadLeft" connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceForeheadRight" connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowOuterLeft" connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowCenterLeft" connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowInnerLeft" connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowOuterRight" connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowCenterRight" connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyebrowInnerRight" connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyeLidUpperLeft" connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyeLidLowerLeft" connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyeLidUpperRight" connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyeLidLowerRight" connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEar1Left" connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceEar2Left" connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> - <bone connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEar1Right" connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceEar2Right" connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> - <bone connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceNoseLeft" connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceNoseCenter" connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceNoseRight" connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceCheekLowerLeft" connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceCheekUpperLeft" connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceCheekLowerRight" connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceCheekUpperRight" connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceJaw" connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceChin" connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceTeethLower" connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceLipLowerLeft" connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipLowerRight" connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipLowerCenter" connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceTongueBase" connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceTongueTip" connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> - <bone connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceJawShaper" connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceForeheadCenter" connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceNoseBase" connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceTeethUpper" connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mFaceLipUpperLeft" connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipUpperRight" connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipCornerLeft" connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipCornerRight" connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceLipUpperCenter" connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> - <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyecornerInnerLeft" connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceEyecornerInnerRight" connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mFaceNoseBridge" connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> @@ -86,29 +86,29 @@ <collision_volume end="0.000 0.100 -0.001" group="Collision" name="L_LOWER_ARM" pos="0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/> <bone aliases="lHand avatar_mWristLeft" connected="true" end="0.000 0.060 0.000" group="Arms" name="mWristLeft" pivot="-0.000000 0.204846 0.000000" pos="-0.000 0.205 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"> <collision_volume end="0.005 0.049 -0.001" group="Collision" name="L_HAND" pos="0.01 0.05 0.0" rot="-3.000000 0.00000 -10.000000" scale="0.05 0.08 0.03" support="base"/> - <bone connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.001 0.049 -0.008" group="Hand" name="mHandMiddle2Left" pivot="-0.001 0.040 -0.006" pos="-0.001 0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.002 0.033 -0.006" group="Hand" name="mHandMiddle3Left" pivot="-0.001 0.049 -0.008" pos="-0.001 0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandMiddle1Left" connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandMiddle2Left" connected="true" end="-0.001 0.049 -0.008" group="Hand" name="mHandMiddle2Left" pivot="-0.001 0.040 -0.006" pos="-0.001 0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandMiddle3Left" connected="true" end="-0.002 0.033 -0.006" group="Hand" name="mHandMiddle3Left" pivot="-0.001 0.049 -0.008" pos="-0.001 0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="0.017 0.036 -0.006" group="Hand" name="mHandIndex1Left" pivot="0.038 0.097 0.015" pos="0.038 0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.014 0.032 -0.006" group="Hand" name="mHandIndex2Left" pivot="0.017 0.036 -0.006" pos="0.017 0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.011 0.025 -0.004" group="Hand" name="mHandIndex3Left" pivot="0.014 0.032 -0.006" pos="0.014 0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandIndex1Left" connected="false" end="0.017 0.036 -0.006" group="Hand" name="mHandIndex1Left" pivot="0.038 0.097 0.015" pos="0.038 0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandIndex2Left" connected="true" end="0.014 0.032 -0.006" group="Hand" name="mHandIndex2Left" pivot="0.017 0.036 -0.006" pos="0.017 0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandIndex3Left" connected="true" end="0.011 0.025 -0.004" group="Hand" name="mHandIndex3Left" pivot="0.014 0.032 -0.006" pos="0.014 0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="-0.013 0.038 -0.008" group="Hand" name="mHandRing1Left" pivot="-0.010 0.099 0.009" pos="-0.010 0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.013 0.040 -0.009" group="Hand" name="mHandRing2Left" pivot="-0.013 0.038 -0.008" pos="-0.013 0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.010 0.028 -0.006" group="Hand" name="mHandRing3Left" pivot="-0.013 0.040 -0.009" pos="-0.013 0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandRing1Left" connected="false" end="-0.013 0.038 -0.008" group="Hand" name="mHandRing1Left" pivot="-0.010 0.099 0.009" pos="-0.010 0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandRing2Left" connected="true" end="-0.013 0.040 -0.009" group="Hand" name="mHandRing2Left" pivot="-0.013 0.038 -0.008" pos="-0.013 0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandRing3Left" connected="true" end="-0.010 0.028 -0.006" group="Hand" name="mHandRing3Left" pivot="-0.013 0.040 -0.009" pos="-0.013 0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="-0.024 0.025 -0.006" group="Hand" name="mHandPinky1Left" pivot="-0.031 0.095 0.003" pos="-0.031 0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.015 0.018 -0.004" group="Hand" name="mHandPinky2Left" pivot="-0.024 0.025 -0.006" pos="-0.024 0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.013 0.016 -0.004" group="Hand" name="mHandPinky3Left" pivot="-0.015 0.018 -0.004" pos="-0.015 0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandPinky1Left" connected="false" end="-0.024 0.025 -0.006" group="Hand" name="mHandPinky1Left" pivot="-0.031 0.095 0.003" pos="-0.031 0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandPinky2Left" connected="true" end="-0.015 0.018 -0.004" group="Hand" name="mHandPinky2Left" pivot="-0.024 0.025 -0.006" pos="-0.024 0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandPinky3Left" connected="true" end="-0.013 0.016 -0.004" group="Hand" name="mHandPinky3Left" pivot="-0.015 0.018 -0.004" pos="-0.015 0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="0.028 0.032 0.000" group="Hand" name="mHandThumb1Left" pivot="0.031 0.026 0.004" pos="0.031 0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.023 0.031 0.000" group="Hand" name="mHandThumb2Left" pivot="0.028 0.032 -0.001" pos="0.028 0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.015 0.025 0.000" group="Hand" name="mHandThumb3Left" pivot="0.023 0.031 -0.001" pos="0.023 0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandThumb1Left" connected="false" end="0.028 0.032 0.000" group="Hand" name="mHandThumb1Left" pivot="0.031 0.026 0.004" pos="0.031 0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandThumb2Left" connected="true" end="0.023 0.031 0.000" group="Hand" name="mHandThumb2Left" pivot="0.028 0.032 -0.001" pos="0.028 0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandThumb3Left" connected="true" end="0.015 0.025 0.000" group="Hand" name="mHandThumb3Left" pivot="0.023 0.031 -0.001" pos="0.023 0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> @@ -123,49 +123,49 @@ <collision_volume end="0.000 -0.100 -0.001" group="Collision" name="R_LOWER_ARM" pos="0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/> <bone aliases="rHand avatar_mWristRight" connected="true" end="0.000 -0.060 0.000" group="Arms" name="mWristRight" pivot="-0.000000 -0.205000 -0.000000" pos="0.000 -0.205 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"> <collision_volume end="0.005 -0.049 -0.001" group="Collision" name="R_HAND" pos="0.01 -0.05 0.0" rot="3.000000 0.00000 10.000000" scale="0.05 0.08 0.03" support="base"/> - <bone connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.001 -0.049 -0.008" group="Hand" name="mHandMiddle2Right" pivot="-0.001 -0.040 -0.006" pos="-0.001 -0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.002 -0.033 -0.006" group="Hand" name="mHandMiddle3Right" pivot="-0.001 -0.049 -0.008" pos="-0.001 -0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandMiddle1Right" connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandMiddle2Right" connected="true" end="-0.001 -0.049 -0.008" group="Hand" name="mHandMiddle2Right" pivot="-0.001 -0.040 -0.006" pos="-0.001 -0.040 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandMiddle3Right" connected="true" end="-0.002 -0.033 -0.006" group="Hand" name="mHandMiddle3Right" pivot="-0.001 -0.049 -0.008" pos="-0.001 -0.049 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="0.017 -0.036 -0.006" group="Hand" name="mHandIndex1Right" pivot="0.038 -0.097 0.015" pos="0.038 -0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.014 -0.032 -0.006" group="Hand" name="mHandIndex2Right" pivot="0.017 -0.036 -0.006" pos="0.017 -0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.011 -0.025 -0.004" group="Hand" name="mHandIndex3Right" pivot="0.014 -0.032 -0.006" pos="0.014 -0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandIndex1Right" connected="false" end="0.017 -0.036 -0.006" group="Hand" name="mHandIndex1Right" pivot="0.038 -0.097 0.015" pos="0.038 -0.097 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandIndex2Right" connected="true" end="0.014 -0.032 -0.006" group="Hand" name="mHandIndex2Right" pivot="0.017 -0.036 -0.006" pos="0.017 -0.036 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandIndex3Right" connected="true" end="0.011 -0.025 -0.004" group="Hand" name="mHandIndex3Right" pivot="0.014 -0.032 -0.006" pos="0.014 -0.032 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="-0.013 -0.038 -0.008" group="Hand" name="mHandRing1Right" pivot="-0.010 -0.099 0.009" pos="-0.010 -0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.013 -0.040 -0.009" group="Hand" name="mHandRing2Right" pivot="-0.013 -0.038 -0.008" pos="-0.013 -0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.010 -0.028 -0.006" group="Hand" name="mHandRing3Right" pivot="-0.013 -0.040 -0.009" pos="-0.013 -0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandRing1Right" connected="false" end="-0.013 -0.038 -0.008" group="Hand" name="mHandRing1Right" pivot="-0.010 -0.099 0.009" pos="-0.010 -0.099 0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandRing2Right" connected="true" end="-0.013 -0.040 -0.009" group="Hand" name="mHandRing2Right" pivot="-0.013 -0.038 -0.008" pos="-0.013 -0.038 -0.008" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandRing3Right" connected="true" end="-0.010 -0.028 -0.006" group="Hand" name="mHandRing3Right" pivot="-0.013 -0.040 -0.009" pos="-0.013 -0.040 -0.009" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="-0.024 -0.025 -0.006" group="Hand" name="mHandPinky1Right" pivot="-0.031 -0.095 0.003" pos="-0.031 -0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.015 -0.018 -0.004" group="Hand" name="mHandPinky2Right" pivot="-0.024 -0.025 -0.006" pos="-0.024 -0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.013 -0.016 -0.004" group="Hand" name="mHandPinky3Right" pivot="-0.015 -0.018 -0.004" pos="-0.015 -0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandPinky1Right" connected="false" end="-0.024 -0.025 -0.006" group="Hand" name="mHandPinky1Right" pivot="-0.031 -0.095 0.003" pos="-0.031 -0.095 0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandPinky2Right" connected="true" end="-0.015 -0.018 -0.004" group="Hand" name="mHandPinky2Right" pivot="-0.024 -0.025 -0.006" pos="-0.024 -0.025 -0.006" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandPinky3Right" connected="true" end="-0.013 -0.016 -0.004" group="Hand" name="mHandPinky3Right" pivot="-0.015 -0.018 -0.004" pos="-0.015 -0.018 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> - <bone connected="false" end="0.028 -0.032 0.000" group="Hand" name="mHandThumb1Right" pivot="0.031 -0.026 0.004" pos="0.031 -0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.023 -0.031 0.000" group="Hand" name="mHandThumb2Right" pivot="0.028 -0.032 -0.001" pos="0.028 -0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.015 -0.025 0.000" group="Hand" name="mHandThumb3Right" pivot="0.023 -0.031 -0.001" pos="0.023 -0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHandThumb1Right" connected="false" end="0.028 -0.032 0.000" group="Hand" name="mHandThumb1Right" pivot="0.031 -0.026 0.004" pos="0.031 -0.026 0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandThumb2Right" connected="true" end="0.023 -0.031 0.000" group="Hand" name="mHandThumb2Right" pivot="0.028 -0.032 -0.001" pos="0.028 -0.032 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHandThumb3Right" connected="true" end="0.015 -0.025 0.000" group="Hand" name="mHandThumb3Right" pivot="0.023 -0.031 -0.001" pos="0.023 -0.031 -0.001" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> </bone> </bone> </bone> - <bone connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mWingsRoot" connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing1Left" connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing2Left" connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing3Left" connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing4Left" connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mWing4FanLeft" connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> - <bone connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mWing1Right" connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing2Right" connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing3Right" connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mWing4Right" connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mWing4FanRight" connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> @@ -200,30 +200,30 @@ </bone> </bone> </bone> - <bone connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mTail1" connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mTail2" connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mTail3" connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mTail4" connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mTail5" connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mTail6" connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> </bone> </bone> - <bone connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> - <bone connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mGroin" connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHindLimbsRoot" connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb1Left" connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb2Left" connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb3Left" connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb4Left" connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> - <bone connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> - <bone connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> + <bone aliases="avatar_mHindLimb1Right" connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb2Right" connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb3Right" connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"> + <bone aliases="avatar_mHindLimb4Right" connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/> </bone> </bone> </bone> diff --git a/indra/newview/cube.dae b/indra/newview/cube.dae new file mode 100644 index 0000000000..085b2c7309 --- /dev/null +++ b/indra/newview/cube.dae @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1"> + <asset> + <contributor> + modified from https://gist.github.com/wtsnz/bfa11c40e04594b260255b5dc7956f26 + </contributor> + <created>2018-10-25T16:29:03Z</created> + <modified>2022-02-18T00:00:00Z</modified> + <unit meter="1.000000"/> + <up_axis>Y_UP</up_axis> + </asset> + + <library_materials> + <material id="Blue" name="Blue"> + <instance_effect url="#effect_Blue"/> + </material> + </library_materials> + + + <library_effects> + <effect id="effect_Blue"> + <profile_COMMON> + <technique sid="common"> + <phong> + <ambient> + <color>0 0 0 1</color> + </ambient> + <diffuse> + <color>0.137255 0.403922 0.870588 1</color> + </diffuse> + <specular> + <color>0.5 0.5 0.5 1</color> + </specular> + <shininess> + <float>16</float> + </shininess> + <transparent opaque="A_ONE"> + <color>0 0 0 1</color> + </transparent> + <transparency> + <float>1</float> + </transparency> + <index_of_refraction> + <float>1</float> + </index_of_refraction> + </phong> + </technique> + </profile_COMMON> + </effect> + </library_effects> + + + <library_geometries> + <geometry id="F1" name="default_physics_shape"> + <mesh> + + <source id="cube-vertex-positions"> + <float_array id="ID2-array" count="72">-0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 -0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 -0.5 0.5 -0.5 0.5 -0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 0.5 -0.5 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 0.5 -0.5 </float_array> + <technique_common> + <accessor source="#ID2-array" count="24" stride="3"> + <param name="X" type="float"/> + <param name="Y" type="float"/> + <param name="Z" type="float"/> + </accessor> + </technique_common> + </source> + + <vertices id="cube-vertices"> + <input semantic="POSITION" source="#cube-vertex-positions"/> + </vertices> + + <triangles count="12" material="geometryElement5"> + <input semantic="VERTEX" offset="0" source="#cube-vertices"/> + <p>0 1 2 0 2 3 4 5 6 4 6 7 8 9 10 8 10 11 12 13 14 12 14 15 16 17 18 16 18 19 20 21 22 20 22 23 </p> + </triangles> + + </mesh> + </geometry> + </library_geometries> + <library_visual_scenes> + + + <visual_scene id="reportScene"> + <!-- No Spaces allowed in Name --> + <node id="F1" name="Face1"> + <instance_geometry url="#F1"> + <bind_material> + <technique_common> + <instance_material symbol="geometryElement5" target="#Blue"/> + </technique_common> + </bind_material> + </instance_geometry> + </node> + </visual_scene> + </library_visual_scenes> + + + <scene> + <instance_visual_scene url="#reportScene"/> + </scene> + + +</COLLADA> diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 7513908cb4..60e26274cb 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -351,11 +351,29 @@ DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp" DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "NoStartPage"
ClearErrors
+INSTALL_FILES_START:
+
Call RemoveProgFilesOnInst # Remove existing files to prevent certain errors when running the new version of the viewer
# This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py
%%INSTALL_FILES%%
+IfErrors 0 INSTALL_FILES_DONE
+ StrCmp $SKIP_DIALOGS "true" INSTALL_FILES_DONE
+ MessageBox MB_ABORTRETRYIGNORE $(ErrorSecondLifeInstallRetry) IDABORT INSTALL_FILES_CANCEL IDRETRY INSTALL_FILES_START
+ # MB_ABORTRETRYIGNORE does not accept IDIGNORE
+ Goto INSTALL_FILES_DONE
+
+INSTALL_FILES_CANCEL:
+ # We are quiting, cleanup.
+ # Silence warnings from RemoveProgFilesOnInst.
+ StrCpy $SKIP_DIALOGS "true"
+ Call RemoveProgFilesOnInst
+ MessageBox MB_OK $(ErrorSecondLifeInstallSupport)
+ Quit
+
+INSTALL_FILES_DONE:
+
# Pass the installer's language to the client to use as a default
StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
@@ -622,7 +640,9 @@ Function RemoveProgFilesOnInst Push $0
StrCpy $0 0
-PREINSTALLREMOVE:
+ClearErrors
+
+PREINSTALL_REMOVE:
# Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
Delete "$INSTDIR\$INSTEXE"
@@ -642,17 +662,17 @@ RMDir /r "$INSTDIR\llplugin" IntOp $0 $0 + 1
-IfErrors 0 PREINSTALLDONE
- IntCmp $0 1 PREINSTALLREMOVE #try again once
- StrCmp $SKIP_DIALOGS "true" PREINSTALLDONE
- MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALLFAIL IDRETRY PREINSTALLREMOVE
+IfErrors 0 PREINSTALL_DONE
+ IntCmp $0 1 PREINSTALL_REMOVE #try again once
+ StrCmp $SKIP_DIALOGS "true" PREINSTALL_DONE
+ MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALL_FAIL IDRETRY PREINSTALL_REMOVE
# MB_ABORTRETRYIGNORE does not accept IDIGNORE
- Goto PREINSTALLDONE
+ Goto PREINSTALL_DONE
-PREINSTALLFAIL:
+PREINSTALL_FAIL:
Quit
-PREINSTALLDONE:
+PREINSTALL_DONE:
# We are no longer including release notes with the viewer, so remove them.
Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk"
diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsi Binary files differindex 648ddbfb85..73f23086be 100644 --- a/indra/newview/installers/windows/lang_da.nsi +++ b/indra/newview/installers/windows/lang_da.nsi diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi index 188c30197a..7cc70e4c76 100755 --- a/indra/newview/installers/windows/lang_de.nsi +++ b/indra/newview/installers/windows/lang_de.nsi @@ -73,6 +73,10 @@ LangString CloseSecondLifeUnInstMB ${LANG_GERMAN} "Second Life kann nicht entfer ; CheckNetworkConnection
LangString CheckNetworkConnectionDP ${LANG_GERMAN} "Prüfe Netzwerkverbindung..."
+; error during installation
+LangString ErrorSecondLifeInstallRetry ${LANG_GERMAN} "Second Life konnte nicht korrekt installiert werden, einige Dateien wurden eventuell nicht korrekt von der Installationroutine kopiert."
+LangString ErrorSecondLifeInstallSupport ${LANG_GERMAN} "Bitte laden Sie den Viewer erneut von https://secondlife.com/support/downloads/ und versuchen Sie die Installation erneut. Sollte das Problem weiterhin bestehen, dann kontaktieren Sie unseren Support unter https://support.secondlife.com."
+
; ask to remove user's data files
LangString RemoveDataFilesMB ${LANG_GERMAN} "Möchten Sie alle anderen zu Second Life gehörigen Dateien ebenfalls ENTFERNEN?$\n$\nWir empfehlen, die Einstellungen und Cache-Dateien zu behalten, wenn Sie andere Versionen von Second Life installiert haben oder eine Deinstallation durchführen, um Second Life auf eine neuere Version zu aktualisieren."
diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi Binary files differindex 0639d51e10..2eaf97d023 100644 --- a/indra/newview/installers/windows/lang_en-us.nsi +++ b/indra/newview/installers/windows/lang_en-us.nsi diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi Binary files differindex ee30651a38..364cc9f67e 100755 --- a/indra/newview/installers/windows/lang_es.nsi +++ b/indra/newview/installers/windows/lang_es.nsi diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi Binary files differindex 7cd90ec314..2f34c0c87a 100755 --- a/indra/newview/installers/windows/lang_fr.nsi +++ b/indra/newview/installers/windows/lang_fr.nsi diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi Binary files differindex 194062da9a..51214d3a9c 100755 --- a/indra/newview/installers/windows/lang_it.nsi +++ b/indra/newview/installers/windows/lang_it.nsi diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi Binary files differindex a54005ba14..296703d1a3 100755 --- a/indra/newview/installers/windows/lang_ja.nsi +++ b/indra/newview/installers/windows/lang_ja.nsi diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi Binary files differindex 355d806866..299645bbb7 100644 --- a/indra/newview/installers/windows/lang_pl.nsi +++ b/indra/newview/installers/windows/lang_pl.nsi diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi Binary files differindex 97f5d2b44a..542c8654b5 100755 --- a/indra/newview/installers/windows/lang_pt-br.nsi +++ b/indra/newview/installers/windows/lang_pt-br.nsi diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi Binary files differindex 65a9f4846d..4e53a4957d 100755 --- a/indra/newview/installers/windows/lang_ru.nsi +++ b/indra/newview/installers/windows/lang_ru.nsi diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi Binary files differindex e71886cc66..bae5029ad1 100755 --- a/indra/newview/installers/windows/lang_tr.nsi +++ b/indra/newview/installers/windows/lang_tr.nsi diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi Binary files differindex f5f0c6cbdf..7922d9df52 100755 --- a/indra/newview/installers/windows/lang_zh.nsi +++ b/indra/newview/installers/windows/lang_zh.nsi diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7f6f6e5997..5250369813 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -96,6 +96,7 @@ #include "stringize.h" #include "boost/foreach.hpp" #include "llcorehttputil.h" +#include "lluiusage.h" using namespace LLAvatarAppearanceDefines; @@ -574,6 +575,8 @@ void LLAgent::ageChat() //----------------------------------------------------------------------------- void LLAgent::moveAt(S32 direction, bool reset) { + LLUIUsage::instance().logCommand("Agent.MoveAt"); + mMoveTimer.reset(); LLFirstUse::notMoving(false); @@ -716,6 +719,9 @@ void LLAgent::moveYaw(F32 mag, bool reset_view) U32 mask = AGENT_CONTROL_YAW_POS | AGENT_CONTROL_YAW_NEG; if ((getControlFlags() & mask) == mask) { + // Rotation into both directions should cancel out + // But keep sending controls to simulator, + // it's needed for script based controls gAgentCamera.setYawKey(0); } @@ -4023,6 +4029,7 @@ void LLAgent::startTeleportRequest() } if (hasPendingTeleportRequest()) { + LLUIUsage::instance().logCommand("Agent.StartTeleportRequest"); mTeleportCanceled.reset(); if (!isMaturityPreferenceSyncedWithServer()) { diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index f981e08ff7..21df036cb7 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -74,10 +74,10 @@ public: void decrementNumberOfPicks() { --mNumberOfPicks; } -private: - void onServerRespond(LLAvatarPicks* picks); +private: + /** * Sets number of Picks. */ diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 39c9fa1bca..909f32cd21 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -60,6 +60,7 @@ #include "llappviewer.h" #include "llcoros.h" #include "lleventcoro.h" +#include "lluiusage.h" #include "llavatarpropertiesprocessor.h" @@ -1426,6 +1427,9 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear, bool replace, LLPointer<LLInventoryCallback> cb) { + LL_DEBUGS("UIUsage") << "wearItemsOnAvatar" << LL_ENDL; + LLUIUsage::instance().logCommand("Avatar.WearItem"); + bool first = true; LLInventoryObject::const_object_list_t items_to_link; @@ -2761,6 +2765,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName() << "'" << LL_ENDL; + LLUIUsage::instance().logCommand("Avatar.WearCategory"); if (gAgentCamera.cameraCustomizeAvatar()) { @@ -3968,6 +3973,8 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo { if (!isAgentAvatarValid()) return; + LLUIUsage::instance().logCommand("Avatar.CreateNewOutfit"); + LL_DEBUGS("Avatar") << "creating new outfit" << LL_ENDL; gAgentWearables.notifyLoadingStarted(); @@ -4006,6 +4013,9 @@ void LLAppearanceMgr::wearBaseOutfit() void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) { + LL_DEBUGS("UIUsage") << "removeItemsFromAvatar" << LL_ENDL; + LLUIUsage::instance().logCommand("Avatar.RemoveItem"); + if (ids_to_remove.empty()) { LL_WARNS() << "called with empty list, nothing to do" << LL_ENDL; @@ -4485,6 +4495,8 @@ public: "Quick Appearance"); if ( gInventory.getCategory( folder_uuid ) != NULL ) { + // Assume this is coming from the predefined avatars web floater + LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance"); LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false); // *TODOw: This may not be necessary if initial outfit is chosen already -- josh diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 92a5fe5893..e98e18a96e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -557,7 +557,7 @@ static void settings_to_globals() gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); - LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); + LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); #if LL_DARWIN gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); @@ -1450,6 +1450,8 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df suspend" ) // give listeners a chance to run llcoro::suspend(); + // if one of our coroutines threw an uncaught exception, rethrow it now + LLCoros::instance().rethrow(); } if (!LLApp::isExiting()) @@ -2490,10 +2492,24 @@ bool LLAppViewer::initConfiguration() //Load settings files list std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); LLXMLNodePtr root; - BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL); + BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL); if (!success) { - LL_ERRS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; + LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; + if (gDirUtilp->fileExists(settings_file_list)) + { + LL_ERRS() << "Cannot load default configuration file settings_files.xml. " + << "Please reinstall viewer from https://secondlife.com/support/downloads/ " + << "and contact https://support.secondlife.com if issue persists after reinstall." + << LL_ENDL; + } + else + { + LL_ERRS() << "Default configuration file settings_files.xml not found. " + << "Please reinstall viewer from https://secondlife.com/support/downloads/ " + << "and contact https://support.secondlife.com if issue persists after reinstall." + << LL_ENDL; + } } mSettingsLocationList = new SettingsFiles(); @@ -2716,19 +2732,14 @@ bool LLAppViewer::initConfiguration() if (clp.hasOption("graphicslevel")) { - // User explicitly requested --graphicslevel on the command line. We - // expect this switch has already set RenderQualityPerformance. Check - // that value for validity. - U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance"); - if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel)) - { - // graphicslevel is valid: save it and engage it later. Capture - // the requested value separately from the settings variable - // because, if this is the first run, LLViewerWindow's constructor - // will call LLFeatureManager::applyRecommendedSettings(), which - // overwrites this settings variable! - mForceGraphicsLevel = graphicslevel; - } + // User explicitly requested --graphicslevel on the command line. We + // expect this switch has already set RenderQualityPerformance. Check + // that value for validity later. + // Capture the requested value separately from the settings variable + // because, if this is the first run, LLViewerWindow's constructor + // will call LLFeatureManager::applyRecommendedSettings(), which + // overwrites this settings variable! + mForceGraphicsLevel = gSavedSettings.getU32("RenderQualityPerformance"); } LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); @@ -3086,7 +3097,7 @@ bool LLAppViewer::initWindow() // Initialize GL stuff // - if (mForceGraphicsLevel) + if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel))) { LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false); gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel); @@ -3296,9 +3307,18 @@ LLSD LLAppViewer::getViewerInfo() const info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined"; if(LLVoiceClient::getInstance()->voiceEnabled()) { - LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion(); + LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion(); + const std::string build_version = version.mBuildVersion; std::ostringstream version_string; - version_string << version.serverType << " " << version.serverVersion << std::endl; + if (std::equal(build_version.begin(), build_version.begin() + version.serverVersion.size(), + version.serverVersion.begin())) + { // Normal case: Show type and build version. + version_string << version.serverType << " " << build_version << std::endl; + } + else + { // Mismatch: Show both versions. + version_string << version.serverVersion << "/" << build_version << std::endl; + } info["VOICE_VERSION"] = version_string.str(); } else @@ -3491,7 +3511,7 @@ void LLAppViewer::cleanupSavedSettings() } } - gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale ); + gSavedSettings.setF32("MapScale", LLWorldMapView::getScaleSetting()); // Some things are cached in LLAgent. if (gAgent.isInitialized()) @@ -4262,6 +4282,15 @@ U32 LLAppViewer::getTextureCacheVersion() } //static +U32 LLAppViewer::getDiskCacheVersion() +{ + // Viewer disk cache version intorduced in Simple Cache Viewer, change if the cache format changes. + const U32 DISK_CACHE_VERSION = 1; + + return DISK_CACHE_VERSION ; +} + +//static U32 LLAppViewer::getObjectCacheVersion() { // Viewer object cache version, change if object update @@ -4281,21 +4310,30 @@ bool LLAppViewer::initCache() // initialize the new disk cache using saved settings const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName"); + const U32 MB = 1024 * 1024; + const uintmax_t MIN_CACHE_SIZE = 256 * MB; + const uintmax_t MAX_CACHE_SIZE = 9984ll * MB; + const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB; + const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); + const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal"); + const F64 texture_cache_percent = 100.0 - disk_cache_percent; + // note that the maximum size of this cache is defined as a percentage of the // total cache size - the 'CacheSize' pref - for all caches. - const unsigned int cache_total_size_mb = gSavedSettings.getU32("CacheSize"); - const double disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal"); - const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100; - const uintmax_t disk_cache_bytes = disk_cache_mb * 1024 * 1024; + const uintmax_t disk_cache_size = uintmax_t(cache_total_size * disk_cache_percent / 100); const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo"); bool texture_cache_mismatch = false; + bool remove_vfs_files = false; if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) { texture_cache_mismatch = true; if(!read_only) { gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); + + //texture cache version was bumped up in Simple Cache Viewer, and at this point old vfs files are not needed + remove_vfs_files = true; } } @@ -4337,11 +4375,23 @@ bool LLAppViewer::initCache() } const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); - LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); + LLDiskCache::initParamSingleton(cache_dir, disk_cache_size, enable_cache_debug_info); if (!read_only) { - if (mPurgeCache) + if (gSavedSettings.getS32("DiskCacheVersion") != LLAppViewer::getDiskCacheVersion()) + { + LLDiskCache::getInstance()->clearCache(); + remove_vfs_files = true; + gSavedSettings.setS32("DiskCacheVersion", LLAppViewer::getDiskCacheVersion()); + } + + if (remove_vfs_files) + { + LLDiskCache::getInstance()->removeOldVFSFiles(); + } + + if (mPurgeCache) { LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); purgeCache(); @@ -4360,18 +4410,10 @@ bool LLAppViewer::initCache() LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); // Init the texture cache - // Allocate 80% of the cache size for textures - const S32 MB = 1024 * 1024; - const S64 MIN_CACHE_SIZE = 256 * MB; - const S64 MAX_CACHE_SIZE = 9984ll * MB; - - S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; - cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); - - S64 texture_cache_size = cache_size; + // Allocate the remaining percent which is not allocated to the disk cache + const S64 texture_cache_size = S64(cache_total_size * texture_cache_percent / 100); - S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); - texture_cache_size -= extra; + LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); @@ -5061,8 +5103,7 @@ void LLAppViewer::idle() audio_update_wind(false); // this line actually commits the changes we've made to source positions, etc. - const F32 max_audio_decode_time = 0.002f; // 2 ms decode time - gAudiop->idle(max_audio_decode_time); + gAudiop->idle(); } } @@ -5423,7 +5464,7 @@ void LLAppViewer::disconnectViewer() gFloaterView->restoreAll(); } - if (LLSelectMgr::getInstance()) + if (LLSelectMgr::instanceExists()) { LLSelectMgr::getInstance()->deselectAll(); } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 7ab21f35cd..f28a90c703 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -130,6 +130,7 @@ public: static U32 getTextureCacheVersion() ; static U32 getObjectCacheVersion() ; + static U32 getDiskCacheVersion() ; const std::string& getSerialNumber() { return mSerialNumber; } @@ -153,16 +154,16 @@ public: void removeMarkerFiles(); void removeDumpDir(); - // LLAppViewer testing helpers. - // *NOTE: These will potentially crash the viewer. Only for debugging. - virtual void forceErrorLLError(); - virtual void forceErrorBreakpoint(); - virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInfiniteLoop(); - virtual void forceErrorSoftwareException(); - virtual void forceErrorDriverCrash(); - virtual void forceErrorCoroutineCrash(); - virtual void forceErrorThreadCrash(); + // LLAppViewer testing helpers. + // *NOTE: These will potentially crash the viewer. Only for debugging. + virtual void forceErrorLLError(); + virtual void forceErrorBreakpoint(); + virtual void forceErrorBadMemoryAccess(); + virtual void forceErrorInfiniteLoop(); + virtual void forceErrorSoftwareException(); + virtual void forceErrorDriverCrash(); + virtual void forceErrorCoroutineCrash(); + virtual void forceErrorThreadCrash(); // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 1797d2dd6e..3e450e6dec 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -48,6 +48,7 @@ #include "llfloatergroups.h" #include "llfloaterreg.h" #include "llfloaterpay.h" +#include "llfloaterprofile.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterwebcontent.h" #include "llfloaterworldmap.h" @@ -62,11 +63,14 @@ #include "llnotificationsutil.h" // for LLNotificationsUtil #include "llpaneloutfitedit.h" #include "llpanelprofile.h" +#include "llparcel.h" #include "llrecentpeople.h" #include "lltrans.h" #include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure +#include "llviewernetwork.h" //LLGridManager +#include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "lltrans.h" #include "llcallingcard.h" @@ -74,6 +78,7 @@ #include "llsidepanelinventory.h" #include "llavatarname.h" #include "llagentui.h" +#include "lluiusage.h" // Flags for kick message const U32 KICK_FLAGS_DEFAULT = 0x0; @@ -81,6 +86,19 @@ const U32 KICK_FLAGS_FREEZE = 1 << 0; const U32 KICK_FLAGS_UNFREEZE = 1 << 1; +std::string getProfileURL(const std::string& agent_name, bool feed_only) +{ + std::string url = "[WEB_PROFILE_URL][AGENT_NAME][FEED_ONLY]"; + LLSD subs; + subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); + subs["AGENT_NAME"] = agent_name; + subs["FEED_ONLY"] = feed_only ? "/?feed_only=true" : ""; + url = LLWeb::expandURLSubstitutions(url, subs); + LLStringUtil::toLower(url); + return url; +} + + // static void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) { @@ -96,7 +114,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin payload["id"] = id; payload["name"] = name; - LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); + LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); // add friend to recent people list LLRecentPeople::instance().add(id); @@ -316,57 +334,144 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float make_ui_sound("UISndStartIM"); } -static const char* get_profile_floater_name(const LLUUID& avatar_id) +// static +void LLAvatarActions::showProfile(const LLUUID& avatar_id) { - // Use different floater XML for our profile to be able to save its rect. - return avatar_id == gAgentID ? "my_profile" : "profile"; + if (avatar_id.notNull()) + { + LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id)); + } } -static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) +// static +void LLAvatarActions::showPicks(const LLUUID& avatar_id) { - std::string url = getProfileURL(av_name.getAccountName()); + if (avatar_id.notNull()) + { + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); + if (profilefloater) + { + profilefloater->showPick(); + } + } +} - // PROFILES: open in webkit window - LLFloaterWebContent::Params p; - p.url(url).id(agent_id.asString()); - LLFloaterReg::showInstance(get_profile_floater_name(agent_id), p); +// static +void LLAvatarActions::showPick(const LLUUID& avatar_id, const LLUUID& pick_id) +{ + if (avatar_id.notNull()) + { + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); + if (profilefloater) + { + profilefloater->showPick(pick_id); + } + } +} + +// static +void LLAvatarActions::createPick() +{ + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgent.getID()))); + LLViewerRegion* region = gAgent.getRegion(); + if (profilefloater && region) + { + LLPickData data; + data.pos_global = gAgent.getPositionGlobal(); + data.sim_name = region->getName(); + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + data.name = parcel->getName(); + data.desc = parcel->getDesc(); + data.snapshot_id = parcel->getSnapshotID(); + data.parcel_id = parcel->getID(); + } + else + { + data.name = region->getName(); + } + + profilefloater->createPick(data); + } } // static -void LLAvatarActions::showProfile(const LLUUID& id) +bool LLAvatarActions::isPickTabSelected(const LLUUID& avatar_id) { - if (id.notNull()) + if (avatar_id.notNull()) + { + LLFloaterProfile* profilefloater = LLFloaterReg::findTypedInstance<LLFloaterProfile>("profile", LLSD().with("id", avatar_id)); + if (profilefloater) + { + return profilefloater->isPickTabSelected(); + } + } + return false; +} + +// static +void LLAvatarActions::showClassifieds(const LLUUID& avatar_id) +{ + if (avatar_id.notNull()) + { + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); + if (profilefloater) + { + profilefloater->showClassified(); + } + } +} + +// static +void LLAvatarActions::showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit) +{ + if (avatar_id.notNull()) { - LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_show_profile, _1, _2)); + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); + if (profilefloater) + { + profilefloater->showClassified(classified_id, edit); + } } } +// static +void LLAvatarActions::createClassified() +{ + LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgent.getID()))); + if (profilefloater) + { + profilefloater->createClassified(); + } +} + //static -bool LLAvatarActions::profileVisible(const LLUUID& id) +bool LLAvatarActions::profileVisible(const LLUUID& avatar_id) { LLSD sd; - sd["id"] = id; - LLFloater* browser = getProfileFloater(id); - return browser && browser->isShown(); + sd["id"] = avatar_id; + LLFloater* floater = getProfileFloater(avatar_id); + return floater && floater->isShown(); } //static -LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& id) +LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& avatar_id) { - LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> - (LLFloaterReg::findInstance(get_profile_floater_name(id), LLSD().with("id", id))); - return browser; + LLFloaterProfile* floater = LLFloaterReg::findTypedInstance<LLFloaterProfile>("profile", LLSD().with("id", avatar_id)); + return floater; } //static -void LLAvatarActions::hideProfile(const LLUUID& id) +void LLAvatarActions::hideProfile(const LLUUID& avatar_id) { LLSD sd; - sd["id"] = id; - LLFloater* browser = getProfileFloater(id); - if (browser) + sd["id"] = avatar_id; + LLFloater* floater = getProfileFloater(avatar_id); + if (floater) { - browser->closeFloater(); + floater->closeFloater(); } } @@ -990,7 +1095,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL } // static -void LLAvatarActions::toggleBlock(const LLUUID& id) +bool LLAvatarActions::toggleBlock(const LLUUID& id) { LLAvatarName av_name; LLAvatarNameCache::get(id, &av_name); @@ -1000,10 +1105,12 @@ void LLAvatarActions::toggleBlock(const LLUUID& id) if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) { LLMuteList::getInstance()->remove(mute); + return false; } else { LLMuteList::getInstance()->add(mute); + return true; } } @@ -1312,6 +1419,8 @@ bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& respo void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message) { const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + LLUIUsage::instance().logCommand("Agent.SendFriendRequest"); + send_improved_im(target_id, target_name, message, diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 7c721076c8..86183cc119 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -38,6 +38,8 @@ class LLInventoryPanel; class LLFloater; class LLView; +std::string getProfileURL(const std::string& agent_name, bool feed_only = false); + /** * Friend-related actions (add, remove, offer teleport, etc) */ @@ -91,13 +93,20 @@ public: */ static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); - /** - * Show avatar profile. - */ - static void showProfile(const LLUUID& id); - static void hideProfile(const LLUUID& id); - static bool profileVisible(const LLUUID& id); - static LLFloater* getProfileFloater(const LLUUID& id); + /** + * Show avatar profile. + */ + static void showProfile(const LLUUID& avatar_id); + static void showPicks(const LLUUID& avatar_id); + static void showPick(const LLUUID& avatar_id, const LLUUID& pick_id); + static void createPick(); + static void showClassifieds(const LLUUID& avatar_id); + static void showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit = false); + static void createClassified(); + static void hideProfile(const LLUUID& avatar_id); + static bool profileVisible(const LLUUID& avatar_id); + static bool isPickTabSelected(const LLUUID& avatar_id); + static LLFloater* getProfileFloater(const LLUUID& avatar_id); /** * Show avatar on world map. @@ -126,9 +135,10 @@ public: static void shareWithAvatars(LLView * panel); /** - * Block/unblock the avatar. + * Block/unblock the avatar by id. + * Returns true if blocked, returns false if unblocked */ - static void toggleBlock(const LLUUID& id); + static bool toggleBlock(const LLUUID& id); /** * Mute/unmute avatar. diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index b0715a3afd..c0990d9d11 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -241,21 +241,6 @@ void LLAvatarList::setDirty(bool val /*= true*/, bool force_refresh /*= false*/) } } -void LLAvatarList::addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name) -{ - LL_DEBUGS("Avaline") << "Adding avaline item into the list: " << item_name << "|" << item_id << ", session: " << session_id << LL_ENDL; - LLAvalineListItem* item = new LLAvalineListItem(/*hide_number=*/false); - item->setAvatarId(item_id, session_id, true, false); - item->setName(item_name); - item->showLastInteractionTime(mShowLastInteractionTime); - item->showSpeakingIndicator(mShowSpeakingIndicator); - item->setOnline(false); - - addItem(item, item_id); - mIDs.push_back(item_id); - sort(); -} - ////////////////////////////////////////////////////////////////////////// // PROTECTED SECTION ////////////////////////////////////////////////////////////////////////// @@ -296,18 +281,10 @@ void LLAvatarList::refresh() { // *NOTE: If you change the UI to show a different string, // be sure to change the filter code below. - if (LLRecentPeople::instance().isAvalineCaller(buddy_id)) - { - const LLSD& call_data = LLRecentPeople::instance().getData(buddy_id); - addAvalineItem(buddy_id, call_data["session_id"].asUUID(), call_data["call_number"].asString()); - } - else - { - std::string display_name = getAvatarName(av_name); - addNewItem(buddy_id, - display_name.empty() ? waiting_str : display_name, - LLAvatarTracker::instance().isBuddyOnline(buddy_id)); - } + std::string display_name = getAvatarName(av_name); + addNewItem(buddy_id, + display_name.empty() ? waiting_str : display_name, + LLAvatarTracker::instance().isBuddyOnline(buddy_id)); modified = true; nadded++; @@ -463,7 +440,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); - if ( mContextMenu && !isAvalineItemSelected()) + if ( mContextMenu) { uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); @@ -523,21 +500,6 @@ BOOL LLAvatarList::handleHover(S32 x, S32 y, MASK mask) return handled; } -bool LLAvatarList::isAvalineItemSelected() -{ - std::vector<LLPanel*> selected_items; - getSelectedItems(selected_items); - std::vector<LLPanel*>::iterator it = selected_items.begin(); - - for(; it != selected_items.end(); ++it) - { - if (dynamic_cast<LLAvalineListItem*>(*it)) - return true; - } - - return false; -} - void LLAvatarList::setVisible(BOOL visible) { if ( visible == FALSE && mContextMenu ) @@ -626,63 +588,3 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_ } return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2); } - -/************************************************************************/ -/* class LLAvalineListItem */ -/************************************************************************/ -LLAvalineListItem::LLAvalineListItem(bool hide_number/* = true*/) : LLAvatarListItem(false) -, mIsHideNumber(hide_number) -{ - // should not use buildPanel from the base class to ensure LLAvalineListItem::postBuild is called. - buildFromFile( "panel_avatar_list_item.xml"); -} - -BOOL LLAvalineListItem::postBuild() -{ - BOOL rv = LLAvatarListItem::postBuild(); - - if (rv) - { - setOnline(true); - showLastInteractionTime(false); - setShowProfileBtn(false); - setShowInfoBtn(false); - mAvatarIcon->setValue("Avaline_Icon"); - mAvatarIcon->setToolTip(std::string("")); - } - return rv; -} - -// to work correctly this method should be called AFTER setAvatarId for avaline callers with hidden phone number -void LLAvalineListItem::setName(const std::string& name) -{ - if (mIsHideNumber) - { - static U32 order = 0; - typedef std::map<LLUUID, U32> avaline_callers_nums_t; - static avaline_callers_nums_t mAvalineCallersNums; - - llassert(getAvatarId() != LLUUID::null); - - const LLUUID &uuid = getAvatarId(); - - if (mAvalineCallersNums.find(uuid) == mAvalineCallersNums.end()) - { - mAvalineCallersNums[uuid] = ++order; - LL_DEBUGS("Avaline") << "Set name for new avaline caller: " << uuid << ", order: " << order << LL_ENDL; - } - LLStringUtil::format_map_t args; - args["[ORDER]"] = llformat("%u", mAvalineCallersNums[uuid]); - std::string hidden_name = LLTrans::getString("AvalineCaller", args); - - LL_DEBUGS("Avaline") << "Avaline caller: " << uuid << ", name: " << hidden_name << LL_ENDL; - LLAvatarListItem::setAvatarName(hidden_name); - LLAvatarListItem::setAvatarToolTip(hidden_name); - } - else - { - const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name); - LLAvatarListItem::setAvatarName(formatted_phone); - LLAvatarListItem::setAvatarToolTip(formatted_phone); - } -} diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 1a672c279b..48b0e70454 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -98,7 +98,6 @@ public: virtual S32 notifyParent(const LLSD& info); - void addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name); void handleDisplayNamesOptionChanged(); void setShowCompleteName(bool show) { mShowCompleteName = show;}; @@ -118,8 +117,6 @@ protected: private: - bool isAvalineItemSelected(); - bool mIgnoreOnlineStatus; bool mShowLastInteractionTime; bool mDirty; @@ -189,27 +186,4 @@ protected: virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; }; -/** - * Represents Avaline caller in Avatar list in Voice Control Panel and group chats. - */ -class LLAvalineListItem : public LLAvatarListItem -{ -public: - - /** - * Constructor - * - * @param hide_number - flag indicating if number should be hidden. - * In this case It will be shown as "Avaline Caller 1", "Avaline Caller 1", etc. - */ - LLAvalineListItem(bool hide_number = true); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void setName(const std::string& name); - -private: - bool mIsHideNumber; -}; - #endif // LL_LLAVATARLIST_H diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index f41eb3daf4..dd0d06a8c8 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -36,6 +36,7 @@ #include "llstartup.h" // Linden library includes +#include "llavataractions.h" // for getProfileUrl #include "lldate.h" #include "lltrans.h" #include "llui.h" // LLUI::getLanguage() @@ -94,54 +95,98 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat } } - -void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method) +void LLAvatarPropertiesProcessor::sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method) { + // this is the startup state when send_complete_agent_movement() message is sent. + // Before this messages won't work so don't bother trying + if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) + { + return; + } + + if (avatar_id.isNull()) + { + return; + } + // Suppress duplicate requests while waiting for a response from the network if (isPendingRequest(avatar_id, type)) { // waiting for a response, don't re-request return; } - // indicate we're going to make a request - addPendingRequest(avatar_id, type); - std::vector<std::string> strings; - strings.push_back( avatar_id.asString() ); - send_generic_message(method, strings); + std::string cap; + + switch (type) + { + case APT_PROPERTIES: + // indicate we're going to make a request + sendAvatarPropertiesRequestMessage(avatar_id); + // can use getRegionCapability("AgentProfile"), but it is heavy + // initAgentProfileCapRequest(avatar_id, cap); + break; + case APT_PICKS: + case APT_GROUPS: + case APT_NOTES: + if (cap.empty()) + { + // indicate we're going to make a request + sendGenericRequest(avatar_id, type, method); + } + else + { + initAgentProfileCapRequest(avatar_id, cap); + } + break; + default: + sendGenericRequest(avatar_id, type, method); + break; + } } -void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) +void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method) { - // this is the startup state when send_complete_agent_movement() message is sent. - // Before this, the AvatarPropertiesRequest message - // won't work so don't bother trying - if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) - { - return; - } + // indicate we're going to make a request + addPendingRequest(avatar_id, type); - if (isPendingRequest(avatar_id, APT_PROPERTIES)) - { - // waiting for a response, don't re-request - return; - } - // indicate we're going to make a request - addPendingRequest(avatar_id, APT_PROPERTIES); + std::vector<std::string> strings; + strings.push_back(avatar_id.asString()); + send_generic_message(method, strings); +} - LLMessageSystem *msg = gMessageSystem; +void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id) +{ + addPendingRequest(avatar_id, APT_PROPERTIES); - msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast( _PREHASH_AvatarID, avatar_id); - gAgent.sendReliableMessage(); + LLMessageSystem *msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_AvatarID, avatar_id); + gAgent.sendReliableMessage(); +} + +void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url) +{ + addPendingRequest(avatar_id, APT_PROPERTIES); + addPendingRequest(avatar_id, APT_PICKS); + addPendingRequest(avatar_id, APT_GROUPS); + addPendingRequest(avatar_id, APT_NOTES); + LLCoros::instance().launch("requestAgentUserInfoCoro", + boost::bind(requestAvatarPropertiesCoro, cap_url, avatar_id)); +} + +void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) +{ + sendRequest(avatar_id, APT_PROPERTIES, "AvatarPropertiesRequest"); } void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id) { - sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest"); + sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest"); } void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id) @@ -174,7 +219,7 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* return; } - LL_INFOS() << "Sending avatarinfo update" << LL_ENDL; + LL_WARNS() << "Sending avatarinfo update. This trims profile descriptions!!!" << LL_ENDL; // This value is required by sendAvatarPropertiesUpdate method. //A profile should never be mature. (From the original code) @@ -266,6 +311,113 @@ bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avata return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED)); } +// static +void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAvatarPropertiesCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + std::string finalUrl = cap_url + "/" + agent_id.asString(); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status + || !result.has("id") + || agent_id != result["id"].asUUID()) + { + LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; + LLAvatarPropertiesProcessor* self = getInstance(); + self->removePendingRequest(agent_id, APT_PROPERTIES); + self->removePendingRequest(agent_id, APT_PICKS); + self->removePendingRequest(agent_id, APT_GROUPS); + self->removePendingRequest(agent_id, APT_NOTES); + return; + } + + // Avatar Data + + LLAvatarData avatar_data; + std::string birth_date; + + avatar_data.agent_id = agent_id; + avatar_data.avatar_id = agent_id; + avatar_data.image_id = result["sl_image_id"].asUUID(); + avatar_data.fl_image_id = result["fl_image_id"].asUUID(); + avatar_data.partner_id = result["partner_id"].asUUID(); + avatar_data.about_text = result["sl_about_text"].asString(); + avatar_data.fl_about_text = result["fl_about_text"].asString(); + avatar_data.born_on = result["member_since"].asDate(); + avatar_data.profile_url = getProfileURL(agent_id.asString()); + + avatar_data.flags = 0; + avatar_data.caption_index = 0; + + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(agent_id, APT_PROPERTIES); + self->notifyObservers(agent_id, &avatar_data, APT_PROPERTIES); + + // Picks + + LLSD picks_array = result["picks"]; + LLAvatarPicks avatar_picks; + avatar_picks.agent_id = agent_id; // Not in use? + avatar_picks.target_id = agent_id; + + for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) + { + const LLSD& pick_data = *it; + avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); + } + + // Request processed, no longer pending + self->removePendingRequest(agent_id, APT_PICKS); + self->notifyObservers(agent_id, &avatar_picks, APT_PICKS); + + // Groups + + LLSD groups_array = result["groups"]; + LLAvatarGroups avatar_groups; + avatar_groups.agent_id = agent_id; // Not in use? + avatar_groups.avatar_id = agent_id; // target_id + + for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) + { + const LLSD& group_info = *it; + LLAvatarGroups::LLGroupData group_data; + group_data.group_powers = 0; // Not in use? + group_data.group_title = group_info["name"].asString(); // Missing data, not in use? + group_data.group_id = group_info["id"].asUUID(); + group_data.group_name = group_info["name"].asString(); + group_data.group_insignia_id = group_info["image_id"].asUUID(); + + avatar_groups.group_list.push_back(group_data); + } + + self->removePendingRequest(agent_id, APT_GROUPS); + self->notifyObservers(agent_id, &avatar_groups, APT_GROUPS); + + // Notes + LLAvatarNotes avatar_notes; + + avatar_notes.agent_id = agent_id; + avatar_notes.target_id = agent_id; + avatar_notes.notes = result["notes"].asString(); + + // Request processed, no longer pending + self->removePendingRequest(agent_id, APT_NOTES); + self->notifyObservers(agent_id, &avatar_notes, APT_NOTES); +} + void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**) { LLAvatarData avatar_data; @@ -312,6 +464,21 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m That will suppress the warnings and be compatible with old server versions. WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply */ + + LLInterestsData interests_data; + + msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, interests_data.agent_id ); + msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AvatarID, interests_data.avatar_id ); + msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_WantToMask, interests_data.want_to_mask ); + msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_WantToText, interests_data.want_to_text ); + msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_SkillsMask, interests_data.skills_mask ); + msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_SkillsText, interests_data.skills_text ); + msg->getString( _PREHASH_PropertiesData, _PREHASH_LanguagesText, interests_data.languages_text ); + + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(interests_data.avatar_id, APT_INTERESTS_INFO); + self->notifyObservers(interests_data.avatar_id, &interests_data, APT_INTERESTS_INFO); } void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**) @@ -385,7 +552,7 @@ void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**) { LLAvatarPicks avatar_picks; - msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.target_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.agent_id); msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id); S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data); @@ -551,6 +718,29 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_ gAgent.sendReliableMessage(); } +void LLAvatarPropertiesProcessor::sendInterestsInfoUpdate(const LLInterestsData* interests_data) +{ + if(!interests_data) + { + return; + } + + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage(_PREHASH_AvatarInterestsUpdate); + msg->nextBlockFast( _PREHASH_AgentData); + msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast( _PREHASH_SessionID, gAgent.getSessionID() ); + msg->nextBlockFast( _PREHASH_PropertiesData); + msg->addU32Fast( _PREHASH_WantToMask, interests_data->want_to_mask); + msg->addStringFast( _PREHASH_WantToText, interests_data->want_to_text); + msg->addU32Fast( _PREHASH_SkillsMask, interests_data->skills_mask); + msg->addStringFast( _PREHASH_SkillsText, interests_data->skills_text); + msg->addString( _PREHASH_LanguagesText, interests_data->languages_text); + + gAgent.sendReliableMessage(); +} + void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) { if (!new_pick) return; diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index b063048c26..f778634d25 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -56,10 +56,22 @@ enum EAvatarProcessorType APT_PICKS, APT_PICK_INFO, APT_TEXTURES, + APT_INTERESTS_INFO, APT_CLASSIFIEDS, APT_CLASSIFIED_INFO }; +struct LLInterestsData +{ + LLUUID agent_id; + LLUUID avatar_id; //target id + U32 want_to_mask; + std::string want_to_text; + U32 skills_mask; + std::string skills_text; + std::string languages_text; +}; + struct LLAvatarData { LLUUID agent_id; @@ -223,6 +235,8 @@ public: void sendClassifiedDelete(const LLUUID& classified_id); + void sendInterestsInfoUpdate(const LLInterestsData* interests_data); + // Returns translated, human readable string for account type, such // as "Resident" or "Linden Employee". Used for profiles, inspectors. static std::string accountType(const LLAvatarData* avatar_data); @@ -234,6 +248,8 @@ public: static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data); + static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id); + static void processAvatarPropertiesReply(LLMessageSystem* msg, void**); static void processAvatarInterestsReply(LLMessageSystem* msg, void**); @@ -252,7 +268,10 @@ public: protected: - void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method); + void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); + void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); + void sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id); + void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url); void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type); diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index fe94cd27b6..275f17b02a 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -320,9 +320,16 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio // make sure we won't re-report, coro will update timer with correct time later regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_REPORTS); - std::string coroname = - LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro", - boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro, url, regionp->getHandle())); + try + { + std::string coroname = + LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro", + boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro, url, regionp->getHandle())); + } + catch (std::bad_alloc&) + { + LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL; + } } } @@ -343,10 +350,17 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi // make sure we won't re-request, coro will update timer with correct time later regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST); - // First send a request to get the latest data - std::string coroname = - LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro", - boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro, url, regionp->getHandle())); + try + { + // First send a request to get the latest data + std::string coroname = + LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro", + boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro, url, regionp->getHandle())); + } + catch (std::bad_alloc&) + { + LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL; + } } } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 8d1e9a438e..1ad2157df0 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -53,6 +53,7 @@ #include "llviewerobjectlist.h" #include "llvoavatar.h" #include "llavataractions.h" +#include "lluiusage.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -294,6 +295,8 @@ void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const void LLAvatarTracker::terminateBuddy(const LLUUID& id) { LL_DEBUGS() << "LLAvatarTracker::terminateBuddy()" << LL_ENDL; + LLUIUsage::instance().logCommand("Agent.TerminateFriendship"); + LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id); if(!buddy) return; mBuddyInfo.erase(id); @@ -640,6 +643,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) if(mBuddyInfo.find(agent_related) != mBuddyInfo.end()) { (mBuddyInfo[agent_related])->setRightsTo(new_rights); + mChangedBuddyIDs.insert(agent_related); } } else diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index e400609a74..72f667a0b8 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -568,8 +568,6 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL // how to chat gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE); - LLUIUsage::instance().logCommand("Chat.Send"); // Pseudo-command - // Look for "/20 foo" channel chats. S32 channel = 0; LLWString out_text = stripChannelNumber(wtext, &channel); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index bdd516e1de..7ff24f64ac 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -48,6 +48,7 @@ #include "llspeakers.h" //for LLIMSpeakerMgr #include "lltrans.h" #include "llfloaterreg.h" +#include "llfloaterreporter.h" #include "llfloatersidepanelcontainer.h" #include "llmutelist.h" #include "llstylemap.h" @@ -118,6 +119,7 @@ public: mSourceType(CHAT_SOURCE_UNKNOWN), mFrom(), mSessionID(), + mCreationTime(time_corrected()), mMinUserNameWidth(0), mUserNameFont(NULL), mUserNameTextBox(NULL), @@ -403,6 +405,48 @@ public: { LLAvatarActions::pay(getAvatarId()); } + else if (level == "report_abuse") + { + std::string time_string; + if (mTime > 0) // have frame time + { + time_t current_time = time_corrected(); + time_t message_time = current_time - LLFrameTimer::getElapsedSeconds() + mTime; + + time_string = "[" + LLTrans::getString("TimeMonth") + "]/[" + + LLTrans::getString("TimeDay") + "]/[" + + LLTrans::getString("TimeYear") + "] [" + + LLTrans::getString("TimeHour") + "]:[" + + LLTrans::getString("TimeMin") + "]"; + + LLSD substitution; + + substitution["datetime"] = (S32)message_time; + LLStringUtil::format(time_string, substitution); + } + else + { + // From history. This might be empty or not full. + // See LLChatLogParser::parse + time_string = getChild<LLTextBox>("time_box")->getValue().asString(); + + // Just add current date if not full. + // Should be fine since both times are supposed to be stl + if (!time_string.empty() && time_string.size() < 7) + { + time_string = "[" + LLTrans::getString("TimeMonth") + "]/[" + + LLTrans::getString("TimeDay") + "]/[" + + LLTrans::getString("TimeYear") + "] " + time_string; + + LLSD substitution; + // To avoid adding today's date to yesterday's timestamp, + // use creation time instead of current time + substitution["datetime"] = (S32)mCreationTime; + LLStringUtil::format(time_string, substitution); + } + } + LLFloaterReporter::showFromChat(mAvatarID, mFrom, time_string, mText); + } else if(level == "block_unblock") { LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagVoiceChat); @@ -477,6 +521,10 @@ public: { return canModerate(userdata); } + else if (level == "report_abuse") + { + return gAgentID != mAvatarID; + } else if (level == "can_ban_member") { return canBanGroupMember(getAvatarId()); @@ -634,6 +682,12 @@ public: mSessionID = chat.mSessionID; mSourceType = chat.mSourceType; + // To be able to report a message, we need a copy of it's text + // and it's easier to store text directly than trying to get + // it from a lltextsegment or chat's mEditor + mText = chat.mText; + mTime = chat.mTime; + //*TODO overly defensive thing, source type should be maintained out there if((chat.mFromID.isNull() && chat.mFromName.empty()) || (chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())) { @@ -983,6 +1037,9 @@ protected: EChatSourceType mSourceType; std::string mFrom; LLUUID mSessionID; + std::string mText; + F64 mTime; // IM's frame time + time_t mCreationTime; // Views's time S32 mMinUserNameWidth; const LLFontGL* mUserNameFont; diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 80d810d159..036ff17074 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -290,9 +290,14 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op ) pickerp->getCurG (), pickerp->getCurB (), subject->mColor.mV[VALPHA] ); // keep current alpha - subject->mColor = updatedColor; - subject->setControlValue(updatedColor.getValue()); - pickerp->setRevertOnCancel(TRUE); + + bool color_changed = subject->mColor != updatedColor; + if (color_changed) + { + subject->mColor = updatedColor; + subject->setControlValue(updatedColor.getValue()); + } + if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback) { subject->mOnCancelCallback( subject, LLSD()); @@ -306,6 +311,13 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op ) // just commit change subject->onCommit (); } + + if (pick_op == COLOR_CANCEL || pick_op == COLOR_SELECT) + { + // both select and cancel close LLFloaterColorPicker + // but COLOR_CHANGE does not + subject->setFocus(TRUE); + } } } } diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp index 86e23e7c83..97b16a5e93 100644 --- a/indra/newview/llconversationloglist.cpp +++ b/indra/newview/llconversationloglist.cpp @@ -391,7 +391,8 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata) "can_invite_to_group" == command_name || "can_share" == command_name || "can_block" == command_name || - "can_pay" == command_name) + "can_pay" == command_name || + "report_abuse" == command_name) { return is_p2p; } diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index a685639427..9ec4fb085b 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -182,6 +182,7 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 items.push_back(std::string("map")); items.push_back(std::string("share")); items.push_back(std::string("pay")); + items.push_back(std::string("report_abuse")); items.push_back(std::string("block_unblock")); items.push_back(std::string("MuteText")); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 20fa6d490b..48c7df40df 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -272,9 +272,9 @@ BOOL LLConversationViewSession::postBuild() default: break; } - } - refresh(); + refresh(); // requires vmi + } return TRUE; } @@ -490,17 +490,20 @@ void LLConversationViewSession::refresh() { // Refresh the session view from its model data LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); - vmi->resetRefresh(); + if (vmi) + { + vmi->resetRefresh(); - if (mSessionTitle) - { - if (!highlightFriendTitle(vmi)) - { - LLStyle::Params title_style; - title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); - mSessionTitle->setText(vmi->getDisplayName(), title_style); - } - } + if (mSessionTitle) + { + if (!highlightFriendTitle(vmi)) + { + LLStyle::Params title_style; + title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); + mSessionTitle->setText(vmi->getDisplayName(), title_style); + } + } + } // Update all speaking indicators LLSpeakingIndicatorManager::updateSpeakingIndicators(); @@ -524,8 +527,11 @@ void LLConversationViewSession::refresh() } requestArrange(); - // Do the regular upstream refresh - LLFolderViewFolder::refresh(); + if (vmi) + { + // Do the regular upstream refresh + LLFolderViewFolder::refresh(); + } } void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) @@ -627,8 +633,11 @@ BOOL LLConversationViewParticipant::postBuild() } updateChildren(); - LLFolderViewItem::postBuild(); - refresh(); + if (getViewModelItem()) + { + LLFolderViewItem::postBuild(); + refresh(); + } return TRUE; } @@ -712,10 +721,10 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); + + // Do the regular upstream refresh + LLFolderViewItem::refresh(); } - - // Do the regular upstream refresh - LLFolderViewItem::refresh(); } void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 7d4961c598..4d9ef99319 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -80,9 +80,14 @@ LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() { } +void LLDoNotDisturbNotificationStorage::reset() +{ + setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")); +} + void LLDoNotDisturbNotificationStorage::initialize() { - setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")); + reset(); getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); } diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index c6f0bf1ab5..237d58b4de 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -61,6 +61,7 @@ public: void loadNotifications(); void updateNotifications(); void removeNotification(const char * name, const LLUUID& id); + void reset(); protected: diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 2372ea01a6..2a0f4c93ac 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -133,6 +133,7 @@ public: inline LLFace* getFace(const S32 i) const; inline S32 getNumFaces() const; face_list_t& getFaces() { return mFaces; } + const face_list_t& getFaces() const { return mFaces; } //void removeFace(const S32 i); // SJB: Avoid using this, it's slow LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index e674707c01..6c1abb24c9 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -58,6 +58,7 @@ static BOOL deferred_render = FALSE; // minimum alpha before discarding a fragment static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255 + // minimum alpha before discarding a fragment when rendering impostors static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f; @@ -147,6 +148,10 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) + for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) + { + prepare_alpha_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], false, false); // note: bindDeferredShader will get called during render loop for materials + } // first pass, render rigged objects only and render to depth buffer forwardRender(true); @@ -215,9 +220,15 @@ void LLDrawPoolAlpha::render(S32 pass) { minimum_alpha = MINIMUM_IMPOSTOR_ALPHA; } + prepare_forward_shader(fullbright_shader, minimum_alpha); prepare_forward_shader(simple_shader, minimum_alpha); + for (int i = 0; i < LLMaterial::SHADER_COUNT; ++i) + { + prepare_forward_shader(LLPipeline::sUnderWaterRender ? &gDeferredMaterialWaterProgram[i] : &gDeferredMaterialProgram[i], minimum_alpha); + } + //first pass -- rigged only and drawn to depth buffer forwardRender(true); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 63e7887d81..361a7666fa 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -125,7 +125,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight())); } - if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD) + if (gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD) { //using offscreen render target, just use the bottom left corner mOrigin.set(0, 0); } @@ -212,7 +212,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } - bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; + bool use_fbo = gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; if (use_fbo) { diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index b76dc6a961..1300cf3658 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -2641,7 +2641,7 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F3 if (!water.isUndefined()) { - environment->injectWaterSettings(sky, experience_id, LLSettingsBase::Seconds(transition_time)); + environment->injectWaterSettings(water, experience_id, LLSettingsBase::Seconds(transition_time)); } if (updateenvironment) diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 1605e4133d..9bb3bac104 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -504,20 +504,6 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t is.close(); } - //get time domain - LLSD::Real cur_total_time = 0.0; - - for (U32 i = 0; i < cur_data.size(); ++i) - { - cur_total_time += cur_data[i]["Total"]["Time"].asReal(); - } - - LLSD::Real base_total_time = 0.0; - for (U32 i = 0; i < base_data.size(); ++i) - { - base_total_time += base_data[i]["Total"]["Time"].asReal(); - } - //allocate raw scratch space LLPointer<LLImageRaw> scratch = new LLImageRaw(1024, 512, 3); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index a02bb56489..70e8437190 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -471,7 +471,25 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, } // check if we are dragging an existing item from the favorites bar - if (item && mDragItemId == item->getUUID()) + bool existing_drop = false; + if (item && mDragItemId == item->getUUID()) + { + // There is a chance of mDragItemId being obsolete + // ex: can happen if something interrupts viewer, which + // results in viewer not geting a 'mouse up' signal + for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) + { + LLViewerInventoryItem* currItem = *i; + + if (currItem->getUUID() == mDragItemId) + { + existing_drop = true; + break; + } + } + } + + if (existing_drop) { *accept = ACCEPT_YES_SINGLE; @@ -500,6 +518,7 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (mItems.empty()) { setLandingTab(NULL); + mLastTab = NULL; } handleNewFavoriteDragAndDrop(item, favorites_id, x, y); } @@ -515,6 +534,12 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) { + if (mItems.empty()) + { + // Isn't supposed to be empty + return; + } + // Identify the button hovered and the side to drop LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab); bool insert_before = true; @@ -787,6 +812,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update) if(mItems.empty()) { mBarLabel->setVisible(TRUE); + mLastTab = NULL; } else { @@ -833,6 +859,10 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update) dynamic_cast<LLFavoriteLandmarkButton*> (*cur_it); if (button) { + if (mLastTab == button) + { + mLastTab = NULL; + } removeChild(button); delete button; } @@ -870,6 +900,17 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update) mLastTab = last_new_button; } + if (!mLastTab && mItems.size() > 0) + { + // mMoreTextBox was removed, so LLFavoriteLandmarkButtons + // should be the only ones in the list + LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (childs->back()); + if (button) + { + mLastTab = button; + } + } + mFirstDropDownItem = j; // Chevron button if (mFirstDropDownItem < mItems.size()) diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index ffbb0bbee9..c075f7e8bd 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -114,6 +114,11 @@ BOOL LLFloater360Capture::postBuild() // by default each time vs restoring the last value mQualityRadioGroup->setSelectedIndex(0); + return true; +} + +void LLFloater360Capture::onOpen(const LLSD& key) +{ // Construct a URL pointing to the first page to load. Although // we do not use this page for anything (after some significant // design changes), we retain the code to load the start page @@ -154,8 +159,6 @@ BOOL LLFloater360Capture::postBuild() // We do an initial capture when the floater is opened, albeit at a 'preview' // quality level (really low resolution, but really fast) onCapture360ImagesBtn(); - - return true; } // called when the user choose a quality level using diff --git a/indra/newview/llfloater360capture.h b/indra/newview/llfloater360capture.h index 6da7ee074a..8f765c0b1b 100644 --- a/indra/newview/llfloater360capture.h +++ b/indra/newview/llfloater360capture.h @@ -47,6 +47,7 @@ class LLFloater360Capture: ~LLFloater360Capture(); BOOL postBuild() override; + void onOpen(const LLSD& key) override; void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; void changeInterestListMode(bool send_everything); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index ab95bc06b8..0186c4aebe 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -105,6 +105,7 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) mNumResultsReturned(0), mNearMeListComplete(FALSE), mCloseOnSelect(FALSE), + mExcludeAgentFromSearchResults(FALSE), mContextConeOpacity (0.f), mContextConeInAlpha(0.f), mContextConeOutAlpha(0.f), @@ -295,7 +296,7 @@ void LLFloaterAvatarPicker::populateNearMe() for(U32 i=0; i<avatar_ids.size(); i++) { LLUUID& av = avatar_ids[i]; - if(av == gAgent.getID()) continue; + if(mExcludeAgentFromSearchResults && (av == gAgent.getID())) continue; LLSD element; element["id"] = av; // value LLAvatarName av_name; diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index a3037ed651..ed3dc37043 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -294,7 +294,7 @@ BOOL LLFloaterBvhPreview::postBuild() loaderp->serialize(dp); dp.reset(); LL_INFOS("BVH") << "Deserializing motionp" << LL_ENDL; - BOOL success = motionp && motionp->deserialize(dp, mMotionID); + BOOL success = motionp && motionp->deserialize(dp, mMotionID, false); LL_INFOS("BVH") << "Done" << LL_ENDL; delete []buffer; @@ -1047,7 +1047,12 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicT mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR); mDummyAvatar->mSpecialRenderMode = 1; mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); - mDummyAvatar->hideSkirt(); + + // on idle overall apperance update will set skirt to visible, so either + // call early or account for mSpecialRenderMode in updateMeshVisibility + mDummyAvatar->updateOverallAppearance(); + mDummyAvatar->hideHair(); + mDummyAvatar->hideSkirt(); // stop extraneous animations mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); @@ -1135,6 +1140,7 @@ BOOL LLPreviewAnimation::render() { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); avatarp->dirtyMesh(); + gPipeline.enableLightsPreview(); avatarPoolp->renderAvatars(avatarp); // renders only one avatar } } diff --git a/indra/newview/llfloaterchatvoicevolume.cpp b/indra/newview/llfloaterchatvoicevolume.cpp index 45aea00a49..67c412dfa6 100644 --- a/indra/newview/llfloaterchatvoicevolume.cpp +++ b/indra/newview/llfloaterchatvoicevolume.cpp @@ -35,7 +35,7 @@ LLFloaterChatVoiceVolume::LLFloaterChatVoiceVolume(const LLSD& key) void LLFloaterChatVoiceVolume::onOpen(const LLSD& key) { LLInspect::onOpen(key); - LLUI::getInstance()->positionViewNearMouse(this); + LLInspect::repositionInspector(key); } LLFloaterChatVoiceVolume::~LLFloaterChatVoiceVolume() diff --git a/indra/newview/llfloaterclassified.cpp b/indra/newview/llfloaterclassified.cpp new file mode 100644 index 0000000000..3520b0f67a --- /dev/null +++ b/indra/newview/llfloaterclassified.cpp @@ -0,0 +1,71 @@ +/** + * @file llfloaterclassified.cpp + * @brief LLFloaterClassified for displaying classifieds. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterclassified.h" + +LLFloaterClassified::LLFloaterClassified(const LLSD& key) + : LLFloater(key) +{ +} + +LLFloaterClassified::~LLFloaterClassified() +{ +} + +void LLFloaterClassified::onOpen(const LLSD& key) +{ + LLPanel* panel = findChild<LLPanel>("main_panel", true); + if (panel) + { + panel->onOpen(key); + } + if (key.has("classified_name")) + { + setTitle(key["classified_name"].asString()); + } + LLFloater::onOpen(key); +} + +BOOL LLFloaterClassified::postBuild() +{ + return TRUE; +} + + +bool LLFloaterClassified::matchesKey(const LLSD& key) +{ + bool is_mkey_valid = mKey.has("classified_id"); + bool is_key_valid = key.has("classified_id"); + if (is_mkey_valid && is_key_valid) + { + return key["classified_id"].asUUID() == mKey["classified_id"].asUUID(); + } + return is_mkey_valid == is_key_valid; +} + +// eof diff --git a/indra/newview/llfloaterwebprofile.h b/indra/newview/llfloaterclassified.h index 4c355e401b..2c95d82b2c 100644 --- a/indra/newview/llfloaterwebprofile.h +++ b/indra/newview/llfloaterclassified.h @@ -1,59 +1,45 @@ -/** - * @file llfloaterwebprofile.h - * @brief Avatar profile floater. +/** + * @file llfloaterclassified.h + * @brief LLFloaterClassified for displaying classifieds. * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * + * Copyright (C) 2022, Linden Research, Inc. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLFLOATERWEBPROFILE_H -#define LL_LLFLOATERWEBPROFILE_H - -#include "llfloaterwebcontent.h" -#include "llviewermediaobserver.h" +#ifndef LL_LLFLOATERCLASSIFIED_H +#define LL_LLFLOATERCLASSIFIED_H -#include <string> +#include "llfloater.h" -class LLMediaCtrl; - -/** - * Displays avatar profile web page. - */ -class LLFloaterWebProfile -: public LLFloaterWebContent +class LLFloaterClassified : public LLFloater { - LOG_CLASS(LLFloaterWebProfile); + LOG_CLASS(LLFloaterClassified); public: - typedef LLFloaterWebContent::Params Params; + LLFloaterClassified(const LLSD& key); + virtual ~LLFloaterClassified(); - LLFloaterWebProfile(const Params& key); + void onOpen(const LLSD& key) override; + BOOL postBuild() override; - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); - - static LLFloater* create(const LLSD& key); - -private: - void applyPreferredRect(); + bool matchesKey(const LLSD& key) override; }; -#endif // LL_LLFLOATERWEBPROFILE_H - +#endif // LL_LLFLOATERCLASSIFIED_H diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 1a784223c2..ba91277c79 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -173,7 +173,6 @@ void LLFloaterColorPicker::showUI () openFloater(getKey()); setVisible ( TRUE ); setFocus ( TRUE ); - setRevertOnCancel(FALSE); // HACK: if system color picker is required - close the SL one we made and use default system dialog if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) ) @@ -185,15 +184,23 @@ void LLFloaterColorPicker::showUI () // code that will get switched in for default system color picker if ( swatch ) { + // Todo: this needs to be threaded for viewer not to timeout LLColor4 curCol = swatch->get (); send_agent_pause(); - getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); + bool commit = getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); send_agent_resume(); - setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] ); - setCurRgb( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] ); - - LLColorSwatchCtrl::onColorChanged ( swatch, LLColorSwatchCtrl::COLOR_CHANGE ); + if (commit) + { + setOrigRgb(curCol[0], curCol[1], curCol[2]); + setCurRgb(curCol[0], curCol[1], curCol[2]); + + LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_SELECT); + } + else + { + LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_CANCEL); + } } closeFloater(); @@ -391,10 +398,7 @@ void LLFloaterColorPicker::onClickCancel ( void* data ) if ( self ) { - if(self->getRevertOnCancel()) - { - self->cancelSelection (); - } + self->cancelSelection(); self->closeFloater(); } } diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index 16974a872e..39dbc5b763 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -104,9 +104,6 @@ class LLFloaterColorPicker void setMouseDownInSwatch (BOOL mouse_down_in_swatch); BOOL getMouseDownInSwatch () { return mMouseDownInSwatch; } - void setRevertOnCancel (BOOL revertOnCancel) { mRevertOnCancel = revertOnCancel; }; - BOOL getRevertOnCancel () { return mRevertOnCancel; } - BOOL isColorChanged (); // called when text entries (RGB/HSL etc.) are changed by user @@ -149,8 +146,6 @@ class LLFloaterColorPicker BOOL mMouseDownInHueRegion; BOOL mMouseDownInSwatch; - BOOL mRevertOnCancel; - const S32 mRGBViewerImageLeft; const S32 mRGBViewerImageTop; const S32 mRGBViewerImageWidth; diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 6b1d9306fb..7def855d83 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -46,19 +46,60 @@ typedef std::pair<LLUUID, std::string> folder_pair_t; -class LLLandmarksInventoryObserver : public LLInventoryAddedObserver +class LLLandmarksInventoryObserver : public LLInventoryObserver { public: LLLandmarksInventoryObserver(LLFloaterCreateLandmark* create_landmark_floater) : mFloater(create_landmark_floater) {} + void changed(U32 mask) override + { + if (mFloater->getItem()) + { + checkChanged(mask); + } + else + { + checkCreated(mask); + } + } + protected: - /*virtual*/ void done() + void checkCreated(U32 mask) { + if (gInventory.getAddedIDs().empty()) + { + return; + } + + if (!(mask & LLInventoryObserver::ADD) || + !(mask & LLInventoryObserver::CREATE) || + !(mask & LLInventoryObserver::UPDATE_CREATE)) + { + return; + } + mFloater->setItem(gInventory.getAddedIDs()); } + void checkChanged(U32 mask) + { + if (gInventory.getChangedIDs().empty()) + { + return; + } + + if ((mask & LLInventoryObserver::LABEL) || + (mask & LLInventoryObserver::INTERNAL) || + (mask & LLInventoryObserver::REMOVE) || + (mask & LLInventoryObserver::STRUCTURE) || + (mask & LLInventoryObserver::REBUILD)) + { + mFloater->updateItem(gInventory.getChangedIDs(), mask); + } + } + private: LLFloaterCreateLandmark* mFloater; }; @@ -85,6 +126,9 @@ BOOL LLFloaterCreateLandmark::postBuild() getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onSaveClicked, this)); getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCancelClicked, this)); + mLandmarkTitleEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTextChanges(); }); + mNotesEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTextChanges(); }); + mLandmarksID = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); return TRUE; @@ -204,6 +248,33 @@ void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id) } } +void LLFloaterCreateLandmark::onCommitTextChanges() +{ + if (mItem.isNull()) + { + return; + } + std::string current_title_value = mLandmarkTitleEditor->getText(); + std::string item_title_value = mItem->getName(); + std::string current_notes_value = mNotesEditor->getText(); + std::string item_notes_value = mItem->getDescription(); + + LLStringUtil::trim(current_title_value); + LLStringUtil::trim(current_notes_value); + + if (!current_title_value.empty() && + (item_title_value != current_title_value || item_notes_value != current_notes_value)) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem); + new_item->rename(current_title_value); + new_item->setDescription(current_notes_value); + LLPointer<LLInventoryCallback> cb; + LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0); + gInventory.accountForUpdate(up); + update_inventory_item(new_item, cb); + } +} + void LLFloaterCreateLandmark::onCreateFolderClicked() { LLNotificationsUtil::add("CreateLandmarkFolder", LLSD(), LLSD(), @@ -278,6 +349,8 @@ void LLFloaterCreateLandmark::onSaveClicked() new_item->updateParentOnServer(FALSE); } + removeObserver(); + gInventory.updateItem(new_item); gInventory.notifyObservers(); @@ -286,6 +359,7 @@ void LLFloaterCreateLandmark::onSaveClicked() void LLFloaterCreateLandmark::onCancelClicked() { + removeObserver(); if (!mItem.isNull()) { LLUUID item_id = mItem->getUUID(); @@ -314,10 +388,59 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items) { if(!getItem()) { - removeObserver(); mItem = item; + mAssetID = mItem->getAssetUUID(); + setVisibleAndFrontmost(true); break; } } } } + +void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask) +{ + if (!getItem()) + { + return; + } + + LLUUID landmark_id = getItem()->getUUID(); + + for (uuid_set_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLUUID& item_id = (*item_iter); + if (landmark_id == item_id) + { + if (getItem() != gInventory.getItem(item_id)) + { + // item is obsolete or removed + closeFloater(); + } + + LLUUID folder_id = mFolderCombo->getValue().asUUID(); + if (folder_id != mItem->getParentUUID()) + { + // user moved landmark in inventory, + // assume that we are done all other changes should already be commited + closeFloater(); + } + + if ((mask & LLInventoryObserver::INTERNAL) && mAssetID != mItem->getAssetUUID()) + { + closeFloater(); + } + + if (mask & LLInventoryObserver::LABEL) + { + mLandmarkTitleEditor->setText(mItem->getName()); + } + + if (mask & LLInventoryObserver::INTERNAL) + { + mNotesEditor->setText(mItem->getDescription()); + } + } + } +} diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h index 74ac5e651c..d84f5ae1fc 100644 --- a/indra/newview/llfloatercreatelandmark.h +++ b/indra/newview/llfloatercreatelandmark.h @@ -49,6 +49,7 @@ public: void onOpen(const LLSD& key); void setItem(const uuid_set_t& items); + void updateItem(const uuid_set_t& items, U32 mask); LLInventoryItem* getItem() { return mItem; } @@ -56,6 +57,7 @@ private: void setLandmarkInfo(const LLUUID &folder_id); void removeObserver(); void populateFoldersList(const LLUUID &folder_id = LLUUID::null); + void onCommitTextChanges(); void onCreateFolderClicked(); void onSaveClicked(); void onCancelClicked(); @@ -66,6 +68,7 @@ private: LLLineEditor* mLandmarkTitleEditor; LLTextEditor* mNotesEditor; LLUUID mLandmarksID; + LLUUID mAssetID; LLLandmarksInventoryObserver* mInventoryObserver; LLPointer<LLInventoryItem> mItem; diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp new file mode 100644 index 0000000000..3b0c67415a --- /dev/null +++ b/indra/newview/llfloaterdisplayname.cpp @@ -0,0 +1,200 @@ +/** + * @file llfloaterdisplayname.cpp + * @author Leyla Farazha + * @brief Implementation of the LLFloaterDisplayName class. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" +#include "llfloaterreg.h" +#include "llfloater.h" + +#include "llnotificationsutil.h" +#include "llviewerdisplayname.h" + +#include "llnotifications.h" +#include "llfloaterdisplayname.h" +#include "llavatarnamecache.h" + +#include "llagent.h" + + +class LLFloaterDisplayName : public LLFloater +{ +public: + LLFloaterDisplayName(const LLSD& key); + virtual ~LLFloaterDisplayName() { } + /*virtual*/ BOOL postBuild(); + void onSave(); + void onCancel(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + + void onCacheSetName(bool success, + const std::string& reason, + const LLSD& content); +}; + +LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) : + LLFloater(key) +{ +} + +void LLFloaterDisplayName::onOpen(const LLSD& key) +{ + getChild<LLUICtrl>("display_name_editor")->clear(); + getChild<LLUICtrl>("display_name_confirm")->clear(); + + LLAvatarName av_name; + LLAvatarNameCache::get(gAgent.getID(), &av_name); + + F64 now_secs = LLDate::now().secondsSinceEpoch(); + + if (now_secs < av_name.mNextUpdate) + { + // ...can't update until some time in the future + F64 next_update_local_secs = + av_name.mNextUpdate - LLStringOps::getLocalTimeOffset(); + LLDate next_update_local(next_update_local_secs); + // display as "July 18 12:17 PM" + std::string next_update_string = + next_update_local.toHTTPDateString("%B %d %I:%M %p"); + getChild<LLUICtrl>("lockout_text")->setTextArg("[TIME]", next_update_string); + getChild<LLUICtrl>("lockout_text")->setVisible(true); + getChild<LLUICtrl>("save_btn")->setEnabled(false); + getChild<LLUICtrl>("display_name_editor")->setEnabled(false); + getChild<LLUICtrl>("display_name_confirm")->setEnabled(false); + getChild<LLUICtrl>("cancel_btn")->setFocus(TRUE); + + } + else + { + getChild<LLUICtrl>("lockout_text")->setVisible(false); + getChild<LLUICtrl>("save_btn")->setEnabled(true); + getChild<LLUICtrl>("display_name_editor")->setEnabled(true); + getChild<LLUICtrl>("display_name_confirm")->setEnabled(true); + + } +} + +BOOL LLFloaterDisplayName::postBuild() +{ + getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onCancel, this)); + getChild<LLUICtrl>("save_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onSave, this)); + + center(); + + return TRUE; +} + +void LLFloaterDisplayName::onCacheSetName(bool success, + const std::string& reason, + const LLSD& content) +{ + if (success) + { + // Inform the user that the change took place, but will take a while + // to percolate. + LLSD args; + args["DISPLAY_NAME"] = content["display_name"]; + LLNotificationsUtil::add("SetDisplayNameSuccess", args); + return; + } + + // Request failed, notify the user + std::string error_tag = content["error_tag"].asString(); + LL_INFOS() << "set name failure error_tag " << error_tag << LL_ENDL; + + // We might have a localized string for this message + // error_args will usually be empty from the server. + if (!error_tag.empty() + && LLNotifications::getInstance()->templateExists(error_tag)) + { + LLNotificationsUtil::add(error_tag); + return; + } + + // The server error might have a localized message for us + std::string lang_code = LLUI::getLanguage(); + LLSD error_desc = content["error_description"]; + if (error_desc.has( lang_code )) + { + LLSD args; + args["MESSAGE"] = error_desc[lang_code].asString(); + LLNotificationsUtil::add("GenericAlert", args); + return; + } + + // No specific error, throw a generic one + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +} + +void LLFloaterDisplayName::onCancel() +{ + setVisible(false); +} + +void LLFloaterDisplayName::onSave() +{ + std::string display_name_utf8 = getChild<LLUICtrl>("display_name_editor")->getValue().asString(); + std::string display_name_confirm = getChild<LLUICtrl>("display_name_confirm")->getValue().asString(); + + if (display_name_utf8.compare(display_name_confirm)) + { + LLNotificationsUtil::add("SetDisplayNameMismatch"); + return; + } + + const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes + LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8); + if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH) + { + LLSD args; + args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH); + LLNotificationsUtil::add("SetDisplayNameFailedLength", args); + return; + } + + if (LLAvatarNameCache::getInstance()->hasNameLookupURL()) + { + LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); + } + else + { + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); + } + + setVisible(false); +} + + +////////////////////////////////////////////////////////////////////////////// +// LLInspectObjectUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterDisplayNameUtil::registerFloater() +{ + LLFloaterReg::add("display_name", "floater_display_name.xml", + &LLFloaterReg::build<LLFloaterDisplayName>); +} diff --git a/indra/newview/llpanelme.h b/indra/newview/llfloaterdisplayname.h index 60e9d4317d..a00bf56712 100644 --- a/indra/newview/llpanelme.h +++ b/indra/newview/llfloaterdisplayname.h @@ -1,6 +1,5 @@ /** - * @file llpanelme.h - * @brief Side tray "Me" (My Profile) panel + * @file llfloaterdisplayname.h * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,27 +23,16 @@ * $/LicenseInfo$ */ -#ifndef LL_LLPANELMEPROFILE_H -#define LL_LLPANELMEPROFILE_H +#ifndef LLFLOATERDISPLAYNAME_H +#define LLFLOATERDISPLAYNAME_H -#include "llpanel.h" -#include "llpanelprofile.h" -/** -* Panel for displaying Agent's Picks and Classifieds panel. -* LLPanelMe allows user to edit his picks and classifieds. -*/ -class LLPanelMe : public LLPanelProfile +namespace LLFloaterDisplayNameUtil { - LOG_CLASS(LLPanelMe); + // Register with LLFloaterReg + void registerFloater(); +} -public: - LLPanelMe(); - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ BOOL postBuild(); -}; - -#endif // LL_LLPANELMEPROFILE_H +#endif diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 24673d5a7c..297ad24359 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -665,6 +665,7 @@ void LLFloaterEditExtDayCycle::onButtonApply(LLUICtrl *ctrl, const LLSD &data) if (ctrl_action == ACTION_SAVE) { doApplyUpdateInventory(dayclone); + clearDirtyFlag(); } else if (ctrl_action == ACTION_SAVEAS) { diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index fec218ca3b..aa9a2c164a 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -296,6 +296,7 @@ void LLFloaterFixedEnvironment::onButtonApply(LLUICtrl *ctrl, const LLSD &data) if (ctrl_action == ACTION_SAVE) { doApplyUpdateInventory(setting_clone); + clearDirtyFlag(); } else if (ctrl_action == ACTION_SAVEAS) { diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 6e326ff3cf..d17889bed1 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -122,7 +122,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key) mObserver = new LLFloaterGestureObserver(this); LLGestureMgr::instance().addObserver(mObserver); - mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); + mCommitCallbackRegistrar.add("Gesture.Action.ToggleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this)); mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2)); mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this)); diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp index 42c5e40761..a00fc4aa84 100644 --- a/indra/newview/llfloaterhoverheight.cpp +++ b/indra/newview/llfloaterhoverheight.cpp @@ -100,11 +100,14 @@ void LLFloaterHoverHeight::onClose(bool app_quitting) // static void LLFloaterHoverHeight::onSliderMoved(LLUICtrl* ctrl, void* userData) { - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - F32 value = sldrCtrl->getValueF32(); - LLVector3 offset(0.0, 0.0, llclamp(value,MIN_HOVER_Z,MAX_HOVER_Z)); - LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL; - gAgentAvatarp->setHoverOffset(offset, false); + if (isAgentAvatarValid()) + { + LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); + F32 value = sldrCtrl->getValueF32(); + LLVector3 offset(0.0, 0.0, llclamp(value, MIN_HOVER_Z, MAX_HOVER_Z)); + LL_INFOS("Avatar") << "setting hover from slider moved" << offset[2] << LL_ENDL; + gAgentAvatarp->setHoverOffset(offset, false); + } } // Do send-to-the-server work when slider drag completes, or new diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 1525bb9952..703b5d0011 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -45,6 +45,7 @@ #include "llflashtimer.h" #include "llfloateravatarpicker.h" #include "llfloaterpreference.h" +#include "llfloaterreporter.h" #include "llimview.h" #include "llnotificationsutil.h" #include "lltoolbarview.h" @@ -1242,6 +1243,18 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec { LLAvatarActions::pay(userID); } + else if ("report_abuse" == command) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(userID, &av_name)) + { + LLFloaterReporter::showFromAvatar(userID, av_name.getCompleteName()); + } + else + { + LLFloaterReporter::showFromAvatar(userID, "not avaliable"); + } + } else if ("block_unblock" == command) { LLAvatarActions::toggleMute(userID, LLMute::flagVoiceChat); @@ -1507,7 +1520,11 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } // Handle all other options - if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) + if (("can_invite" == item) + || ("can_chat_history" == item) + || ("can_share" == item) + || ("can_pay" == item) + || ("report_abuse" == item)) { // Those menu items are enable only if a single avatar is selected return is_single_select; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 3a850d4b68..4cceddeefb 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -698,7 +698,6 @@ void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, ECha void LLFloaterIMNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) { - LLUIUsage::instance().logCommand("Chat.Send"); // pseuo-command // Look for "/20 foo" channel chats. S32 channel = 0; LLWString out_text = stripChannelNumber(wtext, &channel); @@ -858,6 +857,12 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) { + LL_DEBUGS("UIUsage") << "Nearby chat, text " << utf8_out_text << " type " << type << " channel " << channel << LL_ENDL; + if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) // prune back some redundant logging + { + LLUIUsage::instance().logCommand("Chat.SendNearby"); // pseuo-command + } + LLMessageSystem* msg = gMessageSystem; if (channel >= 0) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 34499ac170..93a0b39e02 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -551,7 +551,7 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& participant_id) { LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); - if (widget) + if (widget && widget->getViewModelItem()) { widget->refresh(); } @@ -576,8 +576,11 @@ void LLFloaterIMSessionTab::refreshConversation() { participants_uuids.push_back(widget_it->first); } - widget_it->second->refresh(); - widget_it->second->setVisible(TRUE); + if (widget_it->second->getViewModelItem()) + { + widget_it->second->refresh(); + widget_it->second->setVisible(TRUE); + } ++widget_it; } if (is_ad_hoc || mIsP2PChat) @@ -1126,7 +1129,10 @@ void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) for (; it != it_end; ++it) { LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); - selected_uuids.push_back(conversation_item->getUUID()); + if (conversation_item) + { + selected_uuids.push_back(conversation_item->getUUID()); + } } } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index d78f80ad12..1a98ab9d76 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -3056,7 +3056,8 @@ BOOL LLPanelLandCovenant::postBuild() { mLastRegionID = LLUUID::null; mNextUpdateTime = 0; - + mTextEstateOwner = getChild<LLTextBox>("estate_owner_text"); + mTextEstateOwner->setIsFriendCallback(LLAvatarActions::isFriend); return TRUE; } @@ -3164,8 +3165,7 @@ void LLPanelLandCovenant::updateEstateOwnerName(const std::string& name) LLPanelLandCovenant* self = LLFloaterLand::getCurrentPanelLandCovenant(); if (self) { - LLTextBox* editor = self->getChild<LLTextBox>("estate_owner_text"); - if (editor) editor->setText(name); + self->mTextEstateOwner->setText(name); } } diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 5d9b411f04..684950d88b 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -413,6 +413,7 @@ protected: private: LLUUID mLastRegionID; F64 mNextUpdateTime; //seconds since client start + LLTextBox* mTextEstateOwner; }; #endif diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index fc2da772f3..fd1af7ccc0 100644..100755 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -51,7 +51,7 @@ // The minor cardinal direction labels are hidden if their height is more // than this proportion of the map. -const F32 MAP_MINOR_DIR_THRESHOLD = 0.07f; +const F32 MAP_MINOR_DIR_THRESHOLD = 0.035f; // // Member functions @@ -77,35 +77,44 @@ LLFloaterMap::~LLFloaterMap() BOOL LLFloaterMap::postBuild() { - mMap = getChild<LLNetMap>("Net Map"); - if (gSavedSettings.getBOOL("DoubleClickTeleport")) - { - mMap->setToolTipMsg(getString("AltToolTipMsg")); - } - else if (gSavedSettings.getBOOL("DoubleClickShowWorldMap")) - { - mMap->setToolTipMsg(getString("ToolTipMsg")); - } - sendChildToBack(mMap); - - mTextBoxNorth = getChild<LLTextBox> ("floater_map_north"); - mTextBoxEast = getChild<LLTextBox> ("floater_map_east"); - mTextBoxWest = getChild<LLTextBox> ("floater_map_west"); - mTextBoxSouth = getChild<LLTextBox> ("floater_map_south"); - mTextBoxSouthEast = getChild<LLTextBox> ("floater_map_southeast"); - mTextBoxNorthEast = getChild<LLTextBox> ("floater_map_northeast"); - mTextBoxSouthWest = getChild<LLTextBox> ("floater_map_southwest"); - mTextBoxNorthWest = getChild<LLTextBox> ("floater_map_northwest"); - - updateMinorDirections(); - - // Get the drag handle all the way in back - sendChildToBack(getDragHandle()); - - // keep onscreen - gFloaterView->adjustToFitScreen(this, FALSE); - - return TRUE; + mMap = getChild<LLNetMap>("Net Map"); + mMap->setToolTipMsg(getString("ToolTipMsg")); + mMap->setParcelNameMsg(getString("ParcelNameMsg")); + mMap->setParcelSalePriceMsg(getString("ParcelSalePriceMsg")); + mMap->setParcelSaleAreaMsg(getString("ParcelSaleAreaMsg")); + mMap->setParcelOwnerMsg(getString("ParcelOwnerMsg")); + mMap->setRegionNameMsg(getString("RegionNameMsg")); + mMap->setToolTipHintMsg(getString("ToolTipHintMsg")); + mMap->setAltToolTipHintMsg(getString("AltToolTipHintMsg")); + sendChildToBack(mMap); + + mTextBoxNorth = getChild<LLTextBox>("floater_map_north"); + mTextBoxEast = getChild<LLTextBox>("floater_map_east"); + mTextBoxWest = getChild<LLTextBox>("floater_map_west"); + mTextBoxSouth = getChild<LLTextBox>("floater_map_south"); + mTextBoxSouthEast = getChild<LLTextBox>("floater_map_southeast"); + mTextBoxNorthEast = getChild<LLTextBox>("floater_map_northeast"); + mTextBoxSouthWest = getChild<LLTextBox>("floater_map_southwest"); + mTextBoxNorthWest = getChild<LLTextBox>("floater_map_northwest"); + + mTextBoxNorth->reshapeToFitText(); + mTextBoxEast->reshapeToFitText(); + mTextBoxWest->reshapeToFitText(); + mTextBoxSouth->reshapeToFitText(); + mTextBoxSouthEast->reshapeToFitText(); + mTextBoxNorthEast->reshapeToFitText(); + mTextBoxSouthWest->reshapeToFitText(); + mTextBoxNorthWest->reshapeToFitText(); + + updateMinorDirections(); + + // Get the drag handle all the way in back + sendChildToBack(getDragHandle()); + + // keep onscreen + gFloaterView->adjustToFitScreen(this, false); + + return true; } BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -138,23 +147,44 @@ BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask) return TRUE; } -void LLFloaterMap::setDirectionPos( LLTextBox* text_box, F32 rotation ) +void LLFloaterMap::setDirectionPos(LLTextBox *text_box, F32 rotation) { - // Rotation is in radians. - // Rotation of 0 means x = 1, y = 0 on the unit circle. - - F32 map_half_height = (F32)(getRect().getHeight() / 2) - getHeaderHeight()/2; - F32 map_half_width = (F32)(getRect().getWidth() / 2) ; - F32 text_half_height = (F32)(text_box->getRect().getHeight() / 2); - F32 text_half_width = (F32)(text_box->getRect().getWidth() / 2); - F32 radius = llmin( map_half_height - text_half_height, map_half_width - text_half_width ); - - // Inset by a little to account for position display. - radius -= 8.f; - - text_box->setOrigin( - ll_round(map_half_width - text_half_width + radius * cos( rotation )), - ll_round(map_half_height - text_half_height + radius * sin( rotation )) ); + // Rotation is in radians. + // Rotation of 0 means x = 1, y = 0 on the unit circle. + + F32 map_half_height = (F32) (getRect().getHeight() / 2) - (getHeaderHeight() / 2); + F32 map_half_width = (F32) (getRect().getWidth() / 2); + F32 text_half_height = (F32) (text_box->getRect().getHeight() / 2); + F32 text_half_width = (F32) (text_box->getRect().getWidth() / 2); + F32 extra_padding = (F32) (mTextBoxNorth->getRect().getWidth() / 2); + F32 pos_half_height = map_half_height - text_half_height - extra_padding; + F32 pos_half_width = map_half_width - text_half_width - extra_padding; + + F32 corner_angle = atan2(pos_half_height, pos_half_width); + F32 rotation_mirrored_into_top = abs(fmodf(rotation, F_PI)); + if (rotation < 0) + { + rotation_mirrored_into_top = F_PI - rotation_mirrored_into_top; + } + F32 rotation_mirrored_into_top_right = (F_PI_BY_TWO - abs(rotation_mirrored_into_top - F_PI_BY_TWO)); + bool at_left_right_edge = rotation_mirrored_into_top_right < corner_angle; + + F32 part_x = cos(rotation); + F32 part_y = sin(rotation); + F32 y; + F32 x; + if (at_left_right_edge) + { + x = std::copysign(pos_half_width, part_x); + y = x * part_y / part_x; + } + else + { + y = std::copysign(pos_half_height, part_y); + x = y * part_x / part_y; + } + + text_box->setOrigin(ll_round(map_half_width + x - text_half_width), ll_round(map_half_height + y - text_half_height)); } void LLFloaterMap::updateMinorDirections() @@ -218,32 +248,6 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent) updateMinorDirections(); } -void LLFloaterMap::handleZoom(const LLSD& userdata) -{ - std::string level = userdata.asString(); - - F32 scale = 0.0f; - if (level == std::string("default")) - { - LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale"); - if(pvar) - { - pvar->resetToDefault(); - scale = gSavedSettings.getF32("MiniMapScale"); - } - } - else if (level == std::string("close")) - scale = LLNetMap::MAP_SCALE_MAX; - else if (level == std::string("medium")) - scale = LLNetMap::MAP_SCALE_MID; - else if (level == std::string("far")) - scale = LLNetMap::MAP_SCALE_MIN; - if (scale != 0.0f) - { - mMap->setScale(scale); - } -} - LLFloaterMap* LLFloaterMap::getInstance() { return LLFloaterReg::getTypedInstance<LLFloaterMap>("mini_map"); diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h index ff2fb20535..929b1795aa 100644 --- a/indra/newview/llfloatermap.h +++ b/indra/newview/llfloatermap.h @@ -48,7 +48,6 @@ public: /*virtual*/ void draw(); private: - void handleZoom(const LLSD& userdata); void setDirectionPos( LLTextBox* text_box, F32 rotation ); void updateMinorDirections(); diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index 524162ba51..e755e9924c 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -579,7 +579,25 @@ void LLFloaterMarketplaceListings::updateView() // Update the top message or flip to the tabs and folders view // *TODO : check those messages and create better appropriate ones in strings.xml - if (mRootFolderId.notNull()) + if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE) + { + std::string reason = LLMarketplaceData::instance().getSLMConnectionfailureReason(); + if (reason.empty()) + { + text = LLTrans::getString("InventoryMarketplaceConnectionError"); + } + else + { + LLSD args; + args["[REASON]"] = reason; + text = LLTrans::getString("InventoryMarketplaceConnectionErrorReason", args); + } + + title = LLTrans::getString("InventoryOutboxErrorTitle"); + tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + LL_WARNS() << "Marketplace status code: " << mkt_status << LL_ENDL; + } + else if (mRootFolderId.notNull()) { // "Marketplace listings is empty!" message strings text = LLTrans::getString("InventoryMarketplaceListingsNoItems", subs); diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index 2afd889609..b34961e8a2 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -157,6 +157,18 @@ void LLFloaterMediaSettings::apply() } //////////////////////////////////////////////////////////////////////////////// +void LLFloaterMediaSettings::onOpen(const LLSD& key) +{ + if (mPanelMediaSettingsGeneral) + { + // media is expensive, so only load it when nessesary. + // If we need to preload it, set volume to 0 and any pause + // if applicable, then unpause here + mPanelMediaSettingsGeneral->updateMediaPreview(); + } +} + +//////////////////////////////////////////////////////////////////////////////// void LLFloaterMediaSettings::onClose(bool app_quitting) { if(mPanelMediaSettingsGeneral) diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h index f93512eb3a..151e43e6b9 100644 --- a/indra/newview/llfloatermediasettings.h +++ b/indra/newview/llfloatermediasettings.h @@ -42,6 +42,7 @@ public: ~LLFloaterMediaSettings(); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); static LLFloaterMediaSettings* getInstance(); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index fe5120376c..66a245b779 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -467,22 +467,25 @@ void LLFloaterModelPreview::loadHighLodModel() loadModel(3); } -void LLFloaterModelPreview::loadModel(S32 lod) +void LLFloaterModelPreview::prepareToLoadModel(S32 lod) { mModelPreview->mLoading = true; if (lod == LLModel::LOD_PHYSICS) { // loading physics from file mModelPreview->mPhysicsSearchLOD = lod; + mModelPreview->mWarnOfUnmatchedPhyicsMeshes = false; } - +} +void LLFloaterModelPreview::loadModel(S32 lod) +{ + prepareToLoadModel(lod); (new LLMeshFilePicker(mModelPreview, lod))->getFile(); } void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name, bool force_disable_slm) { - mModelPreview->mLoading = true; - + prepareToLoadModel(lod); mModelPreview->loadModel(file_name, lod, force_disable_slm); } @@ -507,6 +510,15 @@ void LLFloaterModelPreview::onClickCalculateBtn() toggleCalculateButton(false); mUploadBtn->setEnabled(false); + + //disable "simplification" UI + LLPanel* simplification_panel = getChild<LLPanel>("physics simplification"); + LLView* child = simplification_panel->getFirstChild(); + while (child) + { + child->setEnabled(false); + child = simplification_panel->findNextSibling(child); + } } // Modified cell_params, make sure to clear values if you have to reuse cell_params outside of this function @@ -741,7 +753,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { case LLModelPreview::MESH_OPTIMIZER_AUTO: case LLModelPreview::MESH_OPTIMIZER_SLOPPY: - case LLModelPreview::MESH_OPTIMIZER_COMBINE: + case LLModelPreview::MESH_OPTIMIZER_PRECISE: mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, mode); break; default: @@ -1063,11 +1075,18 @@ void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata) } S32 file_mode = iface->getItemCount() - 1; - if (which_mode < file_mode) + S32 cube_mode = file_mode - 1; + if (which_mode < cube_mode) { S32 which_lod = num_lods - which_mode; sInstance->mModelPreview->setPhysicsFromLOD(which_lod); } + else if (which_mode == cube_mode) + { + std::string path = gDirUtilp->getAppRODataDir(); + gDirUtilp->append(path, "cube.dae"); + sInstance->loadModel(LLModel::LOD_PHYSICS, path); + } LLModelPreview *model_preview = sInstance->mModelPreview; if (model_preview) @@ -1662,15 +1681,15 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL void LLFloaterModelPreview::setCtrlLoadFromFile(S32 lod) { if (lod == LLModel::LOD_PHYSICS) - { + { LLComboBox* lod_combo = findChild<LLComboBox>("physics_lod_combo"); if (lod_combo) { - lod_combo->setCurrentByIndex(5); + lod_combo->setCurrentByIndex(lod_combo->getItemCount() - 1); } } else -{ + { LLComboBox* lod_combo = findChild<LLComboBox>("lod_source_" + lod_name[lod]); if (lod_combo) { @@ -1745,7 +1764,7 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod) S32 index = lod_source_combo->getCurrentIndex(); if (index == LLModelPreview::MESH_OPTIMIZER_AUTO || index == LLModelPreview::MESH_OPTIMIZER_SLOPPY - || index == LLModelPreview::MESH_OPTIMIZER_COMBINE) + || index == LLModelPreview::MESH_OPTIMIZER_PRECISE) { //rebuild LoD to update triangle counts onLODParamCommit(lod, true); } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 1e147cd555..bda042186b 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -221,6 +221,7 @@ private: void resetUploadOptions(); void clearLogTab(); + void prepareToLoadModel(S32 lod); void createSmoothComboBox(LLComboBox* combo_box, float min, float max); diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp index dccef88e41..ad5e97e067 100644 --- a/indra/newview/llfloateroutfitsnapshot.cpp +++ b/indra/newview/llfloateroutfitsnapshot.cpp @@ -42,7 +42,6 @@ #include "llviewercontrol.h" #include "lltoolfocus.h" #include "lltoolmgr.h" -#include "llwebprofile.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index 87973c2286..94261b2e4e 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -72,7 +72,7 @@ struct LLGiveMoneyInfo mFloater(floater), mAmount(amount){} }; -typedef boost::shared_ptr<LLGiveMoneyInfo> give_money_ptr; +typedef std::shared_ptr<LLGiveMoneyInfo> give_money_ptr; ///---------------------------------------------------------------------------- /// Class LLFloaterPay diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 8d19aa36bb..273810e8d4 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -333,60 +333,59 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData ); if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null)) { - storeAvatarProperties( pAvatarData ); - processProfileProperties( pAvatarData ); + mAllowPublish = (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH); + mAvatarDataInitialized = true; + getChild<LLUICtrl>("online_searchresults")->setValue(mAllowPublish); } } } -void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData ) +void LLFloaterPreference::saveAvatarProperties( void ) { - if (LLStartUp::getStartupState() == STATE_STARTED) - { - mAvatarProperties.avatar_id = pAvatarData->avatar_id; - mAvatarProperties.image_id = pAvatarData->image_id; - mAvatarProperties.fl_image_id = pAvatarData->fl_image_id; - mAvatarProperties.about_text = pAvatarData->about_text; - mAvatarProperties.fl_about_text = pAvatarData->fl_about_text; - mAvatarProperties.profile_url = pAvatarData->profile_url; - mAvatarProperties.flags = pAvatarData->flags; - mAvatarProperties.allow_publish = pAvatarData->flags & AVATAR_ALLOW_PUBLISH; + const bool allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue(); - mAvatarDataInitialized = true; - } -} + if ((LLStartUp::getStartupState() == STATE_STARTED) + && mAvatarDataInitialized + && (allowPublish != mAllowPublish)) + { + std::string cap_url = gAgent.getRegionCapability("AgentProfile"); + if (!cap_url.empty()) + { + mAllowPublish = allowPublish; -void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData ) -{ - getChild<LLUICtrl>("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) ); + LLCoros::instance().launch("requestAgentUserInfoCoro", + boost::bind(saveAvatarPropertiesCoro, cap_url, allowPublish)); + } + } } -void LLFloaterPreference::saveAvatarProperties( void ) +void LLFloaterPreference::saveAvatarPropertiesCoro(const std::string cap_url, bool allow_publish) { - const BOOL allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue(); + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; - if (allowPublish) - { - mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH; - } + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); - // - // NOTE: We really don't want to send the avatar properties unless we absolutely - // need to so we can avoid the accidental profile reset bug, so, if we're - // logged in, the avatar data has been initialized and we have a state change - // for the "allow publish" flag, then set the flag to its new value and send - // the properties update. - // - // NOTE: The only reason we can not remove this update altogether is because of the - // "allow publish" flag, the last remaining profile setting in the viewer - // that doesn't exist in the web profile. - // - if ((LLStartUp::getStartupState() == STATE_STARTED) && mAvatarDataInitialized && (allowPublish != mAvatarProperties.allow_publish)) - { - mAvatarProperties.allow_publish = allowPublish; + std::string finalUrl = cap_url + "/" + gAgentID.asString(); + LLSD data; + data["allow_publish"] = allow_publish; - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties ); - } + LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("Preferences") << "Failed to put agent information " << data << " for id " << gAgentID << LL_ENDL; + return; + } + + LL_DEBUGS("Preferences") << "Agent id: " << gAgentID << " Data: " << data << " Result: " << httpResults << LL_ENDL; } BOOL LLFloaterPreference::postBuild() @@ -938,7 +937,7 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata) else { // Show beep, pop up dialog, etc. - LL_INFOS() << "Can't close preferences!" << LL_ENDL; + LL_INFOS("Preferences") << "Can't close preferences!" << LL_ENDL; } LLPanelLogin::updateLocationSelectorsVisibility(); @@ -1200,7 +1199,6 @@ void LLFloaterPreference::refreshEnabledState() BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && bumpshiny && shaders && - gGLManager.mHasFramebufferObject && (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); @@ -1251,7 +1249,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && - gGLManager.mHasFramebufferObject && (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); @@ -1385,8 +1382,7 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings() } // disabled deferred - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") || - !gGLManager.mHasFramebufferObject) + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")) { ctrl_shadows->setEnabled(FALSE); ctrl_shadows->setValue(0); @@ -1793,13 +1789,13 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map if (!LLXMLNode::parseFile(filename, root, NULL)) { - LL_WARNS() << "Unable to parse file " << filename << LL_ENDL; + LL_WARNS("Preferences") << "Unable to parse file " << filename << LL_ENDL; return false; } if (!root->hasName("labels")) { - LL_WARNS() << filename << " is not a valid definition file" << LL_ENDL; + LL_WARNS("Preferences") << filename << " is not a valid definition file" << LL_ENDL; return false; } @@ -1819,7 +1815,7 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map } else { - LL_WARNS() << filename << " failed to load" << LL_ENDL; + LL_WARNS("Preferences") << filename << " failed to load" << LL_ENDL; return false; } @@ -2725,7 +2721,7 @@ bool LLPanelPreferenceControls::addControlTableColumns(const std::string &filena LLScrollListCtrl::Contents contents; if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode)) { - LL_WARNS() << "Failed to load " << filename << LL_ENDL; + LL_WARNS("Preferences") << "Failed to load " << filename << LL_ENDL; return false; } LLXUIParser parser; @@ -2752,7 +2748,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename) LLScrollListCtrl::Contents contents; if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode)) { - LL_WARNS() << "Failed to load " << filename << LL_ENDL; + LL_WARNS("Preferences") << "Failed to load " << filename << LL_ENDL; return false; } LLXUIParser parser; @@ -2858,7 +2854,7 @@ void LLPanelPreferenceControls::populateControlTable() { // Either unknown mode or MODE_SAVED_SETTINGS // It doesn't have UI or actual settings yet - LL_WARNS() << "Unimplemented mode" << LL_ENDL; + LL_WARNS("Preferences") << "Unimplemented mode" << LL_ENDL; // Searchable columns were removed, mark searchables for an update LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); @@ -2898,7 +2894,7 @@ void LLPanelPreferenceControls::populateControlTable() } else { - LL_WARNS() << "Unimplemented mode" << LL_ENDL; + LL_WARNS("Preferences") << "Unimplemented mode" << LL_ENDL; } // explicit update to make sure table is ready for llsearchableui @@ -2953,10 +2949,15 @@ void LLPanelPreferenceControls::cancel() if (mConflictHandler[i].hasUnsavedChanges()) { mConflictHandler[i].clear(); + if (mEditingMode == i) + { + // cancel() can be called either when preferences floater closes + // or when child floater closes (like advanced graphical settings) + // in which case we need to clear and repopulate table + regenerateControls(); + } } } - pControlsTable->clearRows(); - pControlsTable->clearColumns(); } void LLPanelPreferenceControls::saveSettings() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 5ef2ca68d3..542df18ddb 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -100,9 +100,8 @@ public: static void updateShowFavoritesCheckbox(bool val); void processProperties( void* pData, EAvatarProcessorType type ); - void processProfileProperties(const LLAvatarData* pAvatarData ); - void storeAvatarProperties( const LLAvatarData* pAvatarData ); void saveAvatarProperties( void ); + static void saveAvatarPropertiesCoro(const std::string url, bool allow_publish); void selectPrivacyPanel(); void selectChatPanel(); void getControlNames(std::vector<std::string>& names); @@ -213,7 +212,7 @@ private: bool mOriginalHideOnlineStatus; std::string mDirectoryVisibility; - LLAvatarData mAvatarProperties; + bool mAllowPublish; // Allow showing agent in search std::string mSavedCameraPreset; std::string mSavedGraphicsPreset; LOG_CLASS(LLFloaterPreference); diff --git a/indra/newview/llfloaterprofile.cpp b/indra/newview/llfloaterprofile.cpp new file mode 100644 index 0000000000..6ccdace6c5 --- /dev/null +++ b/indra/newview/llfloaterprofile.cpp @@ -0,0 +1,170 @@ +/** + * @file llfloaterprofile.cpp + * @brief Avatar profile floater. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterprofile.h" + +#include "llagent.h" //gAgent +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llpanelprofile.h" + +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +LLFloaterProfile::LLFloaterProfile(const LLSD& key) + : LLFloater(key), + mAvatarId(key["id"].asUUID()), + mNameCallbackConnection() +{ + mDefaultRectForGroup = false; +} + +LLFloaterProfile::~LLFloaterProfile() +{ + if (mNameCallbackConnection.connected()) + { + mNameCallbackConnection.disconnect(); + } +} + +void LLFloaterProfile::onOpen(const LLSD& key) +{ + mPanelProfile->onOpen(key); + + // Update the avatar name. + mNameCallbackConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLFloaterProfile::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLFloaterProfile::postBuild() +{ + mPanelProfile = findChild<LLPanelProfile>(PANEL_PROFILE_VIEW); + + return TRUE; +} + +void LLFloaterProfile::onClickCloseBtn(bool app_quitting) +{ + if (!app_quitting) + { + if (mPanelProfile->hasUnpublishedClassifieds()) + { + LLNotificationsUtil::add("ProfileUnpublishedClassified", LLSD(), LLSD(), + boost::bind(&LLFloaterProfile::onUnsavedChangesCallback, this, _1, _2, false)); + } + else if (mPanelProfile->hasUnsavedChanges()) + { + LLNotificationsUtil::add("ProfileUnsavedChanges", LLSD(), LLSD(), + boost::bind(&LLFloaterProfile::onUnsavedChangesCallback, this, _1, _2, true)); + } + else + { + closeFloater(); + } + } + else + { + closeFloater(); + } +} + +void LLFloaterProfile::onUnsavedChangesCallback(const LLSD& notification, const LLSD& response, bool can_save) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (can_save) + { + // savable content + + if (option == 0) // Save + { + mPanelProfile->commitUnsavedChanges(); + closeFloater(); + } + if (option == 1) // Discard + { + closeFloater(); + } + // else cancel + } + else + { + // classifieds + + if (option == 0) // Ok + { + closeFloater(); + } + // else cancel + } + +} + +void LLFloaterProfile::createPick(const LLPickData &data) +{ + mPanelProfile->createPick(data); +} + +void LLFloaterProfile::showPick(const LLUUID& pick_id) +{ + mPanelProfile->showPick(pick_id); +} + +bool LLFloaterProfile::isPickTabSelected() +{ + return mPanelProfile->isPickTabSelected(); +} + +void LLFloaterProfile::refreshName() +{ + if (!mNameCallbackConnection.connected()) + { + mNameCallbackConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLFloaterProfile::onAvatarNameCache, this, _1, _2)); + } + + LLPanelProfileSecondLife *panel = findChild<LLPanelProfileSecondLife>("panel_profile_secondlife"); + if (panel) + { + panel->refreshName(); + } +} + +void LLFloaterProfile::showClassified(const LLUUID& classified_id, bool edit) +{ + mPanelProfile->showClassified(classified_id, edit); +} + +void LLFloaterProfile::createClassified() +{ + mPanelProfile->createClassified(); +} + +void LLFloaterProfile::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mNameCallbackConnection.disconnect(); + setTitle(av_name.getCompleteName()); +} + +// eof diff --git a/indra/newview/llfloaterprofile.h b/indra/newview/llfloaterprofile.h new file mode 100644 index 0000000000..b3ed02fc2c --- /dev/null +++ b/indra/newview/llfloaterprofile.h @@ -0,0 +1,66 @@ +/** + * @file llfloaterprofile.h + * @brief Avatar profile floater. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERPROFILE_H +#define LL_LLFLOATERPROFILE_H + +#include "llavatarnamecache.h" +#include "llavatarpropertiesprocessor.h" +#include "llfloater.h" + +class LLPanelProfile; + +class LLFloaterProfile : public LLFloater +{ + LOG_CLASS(LLFloaterProfile); +public: + LLFloaterProfile(const LLSD& key); + virtual ~LLFloaterProfile(); + + BOOL postBuild() override; + + void onOpen(const LLSD& key) override; + void onClickCloseBtn(bool app_quitting = false) override; + void onUnsavedChangesCallback(const LLSD& notification, const LLSD& response, bool can_save); + + void createPick(const LLPickData &data); + void showPick(const LLUUID& pick_id = LLUUID::null); + bool isPickTabSelected(); + void refreshName(); + + void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); + void createClassified(); + +private: + LLAvatarNameCache::callback_connection_t mNameCallbackConnection; + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + + LLPanelProfile* mPanelProfile; + + LLUUID mAvatarId; +}; + +#endif // LL_LLFLOATERPROFILE_H diff --git a/indra/newview/llfloaterprofiletexture.cpp b/indra/newview/llfloaterprofiletexture.cpp new file mode 100644 index 0000000000..bf1f56a6d1 --- /dev/null +++ b/indra/newview/llfloaterprofiletexture.cpp @@ -0,0 +1,223 @@ +/** + * @file llfloaterprofiletexture.cpp + * @brief LLFloaterProfileTexture class implementation + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterprofiletexture.h" + +#include "llbutton.h" +#include "llfloaterreg.h" +#include "llpreview.h" // fors constants +#include "lltrans.h" +#include "llviewercontrol.h" +#include "lltextureview.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" + + + +LLFloaterProfileTexture::LLFloaterProfileTexture(LLView* owner) + : LLFloater(LLSD()) + , mUpdateDimensions(TRUE) + , mLastHeight(0) + , mLastWidth(0) + , mImage(NULL) + , mImageOldBoostLevel(LLGLTexture::BOOST_NONE) + , mOwnerHandle(owner->getHandle()) +{ + buildFromFile("floater_profile_texture.xml"); +} + +LLFloaterProfileTexture::~LLFloaterProfileTexture() +{ + if (mImage.notNull()) + { + mImage->setBoostLevel(mImageOldBoostLevel); + mImage = NULL; + } +} + +// virtual +BOOL LLFloaterProfileTexture::postBuild() +{ + mProfileIcon = getChild<LLIconCtrl>("profile_pic"); + + mCloseButton = getChild<LLButton>("close_btn"); + mCloseButton->setCommitCallback([this](LLUICtrl*, void*) { closeFloater(); }, nullptr); + + return TRUE; +} + +// virtual +void LLFloaterProfileTexture::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLFloater::reshape(width, height, called_from_parent); +} + +// It takes a while until we get height and width information. +// When we receive it, reshape the window accordingly. +void LLFloaterProfileTexture::updateDimensions() +{ + if (mImage.isNull()) + { + return; + } + if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) + { + return; + } + + S32 img_width = mImage->getFullWidth(); + S32 img_height = mImage->getFullHeight(); + + if (mAssetStatus != LLPreview::PREVIEW_ASSET_LOADED + || mLastWidth != img_width + || mLastHeight != img_height) + { + mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; + // Asset has been fully loaded + mUpdateDimensions = TRUE; + } + + mLastHeight = img_height; + mLastWidth = img_width; + + // Reshape the floater only when required + if (mUpdateDimensions) + { + mUpdateDimensions = FALSE; + + LLRect old_floater_rect = getRect(); + LLRect old_image_rect = mProfileIcon->getRect(); + S32 width = old_floater_rect.getWidth() - old_image_rect.getWidth() + mLastWidth; + S32 height = old_floater_rect.getHeight() - old_image_rect.getHeight() + mLastHeight; + + const F32 MAX_DIMENTIONS = 512; // most profiles are supposed to be 256x256 + + S32 biggest_dim = llmax(width, height); + if (biggest_dim > MAX_DIMENTIONS) + { + F32 scale_down = MAX_DIMENTIONS / (F32)biggest_dim; + width *= scale_down; + height *= scale_down; + } + + //reshape floater + reshape(width, height); + + gFloaterView->adjustToFitScreen(this, FALSE); + } +} + +void LLFloaterProfileTexture::draw() +{ + // drawFrustum + LLView *owner = mOwnerHandle.get(); + static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, owner); + + LLFloater::draw(); +} + +void LLFloaterProfileTexture::onOpen(const LLSD& key) +{ + mCloseButton->setFocus(true); +} + +void LLFloaterProfileTexture::resetAsset() +{ + mProfileIcon->setValue("Generic_Person_Large"); + mImageID = LLUUID::null; + if (mImage.notNull()) + { + mImage->setBoostLevel(mImageOldBoostLevel); + mImage = NULL; + } +} +void LLFloaterProfileTexture::loadAsset(const LLUUID &image_id) +{ + if (mImageID != image_id) + { + if (mImage.notNull()) + { + mImage->setBoostLevel(mImageOldBoostLevel); + mImage = NULL; + } + } + else + { + return; + } + + mProfileIcon->setValue(image_id); + mImageID = image_id; + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImageOldBoostLevel = mImage->getBoostLevel(); + + if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) + { + mImage->setLoadedCallback(LLFloaterProfileTexture::onTextureLoaded, + 0, TRUE, FALSE, new LLHandle<LLFloater>(getHandle()), &mCallbackTextureList); + + mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + mAssetStatus = LLPreview::PREVIEW_ASSET_LOADING; + } + else + { + mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; + } + + mUpdateDimensions = TRUE; + updateDimensions(); +} + +// static +void LLFloaterProfileTexture::onTextureLoaded( + BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata) +{ + LLHandle<LLFloater>* handle = (LLHandle<LLFloater>*)userdata; + + if (!handle->isDead()) + { + LLFloaterProfileTexture* floater = static_cast<LLFloaterProfileTexture*>(handle->get()); + if (floater && success) + { + floater->mUpdateDimensions = TRUE; + floater->updateDimensions(); + } + } + + if (final || !success) + { + delete handle; + } +} diff --git a/indra/newview/llfloaterprofiletexture.h b/indra/newview/llfloaterprofiletexture.h new file mode 100644 index 0000000000..66a61213dd --- /dev/null +++ b/indra/newview/llfloaterprofiletexture.h @@ -0,0 +1,81 @@ +/** + * @file llfloaterprofiletexture.h + * @brief LLFloaterProfileTexture class definition + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERPROFILETEXTURE_H +#define LL_LLFLOATERPROFILETEXTURE_H + +#include "llfloater.h" +#include "llviewertexture.h" + +class LLButton; +class LLImageRaw; +class LLIconCtrl; + +class LLFloaterProfileTexture : public LLFloater +{ +public: + LLFloaterProfileTexture(LLView* owner); + ~LLFloaterProfileTexture(); + + void draw() override; + void onOpen(const LLSD& key) override; + + void resetAsset(); + void loadAsset(const LLUUID &image_id); + + + static void onTextureLoaded( + BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata); + + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; +protected: + BOOL postBuild() override; + +private: + void updateDimensions(); + + LLUUID mImageID; + LLPointer<LLViewerFetchedTexture> mImage; + S32 mImageOldBoostLevel; + S32 mAssetStatus; + F32 mContextConeOpacity; + S32 mLastHeight; + S32 mLastWidth; + BOOL mUpdateDimensions; + + LLHandle<LLView> mOwnerHandle; + LLIconCtrl* mProfileIcon; + LLButton* mCloseButton; + + LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList; +}; +#endif // LL_LLFLOATERPROFILETEXTURE_H diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 296e155d28..07d4dcae38 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -47,6 +47,7 @@ #include "llagent.h" #include "llappviewer.h" +#include "llavataractions.h" #include "llavatarname.h" #include "llfloateravatarpicker.h" #include "llbutton.h" @@ -1322,6 +1323,7 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { + static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { std::string buffer; @@ -1343,17 +1345,19 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() LLSD args; args["TEXTURE_NUM"] = i+1; args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); + args["MAX_SIZE"] = MAX_TERRAIN_TEXTURE_SIZE; LLNotificationsUtil::add("InvalidTerrainBitDepth", args); return FALSE; } - if (width > 512 || height > 512) + if (width > MAX_TERRAIN_TEXTURE_SIZE || height > MAX_TERRAIN_TEXTURE_SIZE) { LLSD args; args["TEXTURE_NUM"] = i+1; args["TEXTURE_SIZE_X"] = width; args["TEXTURE_SIZE_Y"] = height; + args["MAX_SIZE"] = MAX_TERRAIN_TEXTURE_SIZE; LLNotificationsUtil::add("InvalidTerrainSize", args); return FALSE; @@ -1826,7 +1830,7 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region) setCtrlsEnabled(god || owner || manager); getChildView("apply_btn")->setEnabled(FALSE); - + getChildView("estate_owner")->setEnabled(TRUE); getChildView("message_estate_btn")->setEnabled(god || owner || manager); getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); @@ -1888,6 +1892,8 @@ BOOL LLPanelEstateInfo::postBuild() getChild<LLUICtrl>("externally_visible_radio")->setFocus(TRUE); + getChild<LLTextBox>("estate_owner")->setIsFriendCallback(LLAvatarActions::isFriend); + return LLPanelRegionInfo::postBuild(); } @@ -2134,6 +2140,7 @@ BOOL LLPanelEstateCovenant::postBuild() { mEstateNameText = getChild<LLTextBox>("estate_name_text"); mEstateOwnerText = getChild<LLTextBox>("estate_owner_text"); + mEstateOwnerText->setIsFriendCallback(LLAvatarActions::isFriend); mLastModifiedText = getChild<LLTextBox>("covenant_timestamp_text"); mEditor = getChild<LLViewerTextEditor>("covenant_editor"); LLButton* reset_button = getChild<LLButton>("reset_covenant"); @@ -3683,7 +3690,7 @@ void LLPanelEstateAccess::searchAgent(LLNameListCtrl* listCtrl, const std::strin if (!search_string.empty()) { listCtrl->setSearchColumn(0); // name column - listCtrl->selectItemByPrefix(search_string, FALSE); + listCtrl->searchItems(search_string, false, true); } else { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index b73755cf4e..2df4ca973d 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -54,6 +54,7 @@ #include "llbutton.h" #include "llfloaterreg.h" #include "lltexturectrl.h" +#include "lltexteditor.h" #include "llscrolllistctrl.h" #include "lldispatcher.h" #include "llviewerobject.h" @@ -250,9 +251,6 @@ LLFloaterReporter::~LLFloaterReporter() mPosition.setVec(0.0f, 0.0f, 0.0f); - std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() ); - mMCDList.clear(); - delete mResourceDatap; } @@ -661,6 +659,23 @@ void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::strin show(avatar_id, avatar_name); } +// static +void LLFloaterReporter::showFromChat(const LLUUID& avatar_id, const std::string& avatar_name, const std::string& time, const std::string& description) +{ + show(avatar_id, avatar_name); + + LLStringUtil::format_map_t args; + args["[MSG_TIME]"] = time; + args["[MSG_DESCRIPTION]"] = description; + + LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); + if (self) + { + std::string description = self->getString("chat_report_format", args); + self->getChild<LLUICtrl>("details_edit")->setValue(description); + } +} + void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id) { getChild<LLUICtrl>("object_name")->setValue(object_name); @@ -1028,37 +1043,3 @@ void LLFloaterReporter::onClose(bool app_quitting) mSnapshotTimer.stop(); gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting); } - - -// void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd) -// { -// LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); -// if (self) -// { -// self->getChild<LLUICtrl>("details_edit")->setValue(description); - -// for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer()); -// self->mMCDList.clear(); -// if (mcd) -// { -// self->mMCDList.push_back(new LLMeanCollisionData(mcd)); -// } -// } -// } - -// void LLFloaterReporter::addDescription(const std::string& description, LLMeanCollisionData *mcd) -// { -// LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter"); -// if (self) -// { -// LLTextEditor* text = self->getChild<LLTextEditor>("details_edit"); -// if (text) -// { -// text->insertText(description); -// } -// if (mcd) -// { -// self->mMCDList.push_back(new LLMeanCollisionData(mcd)); -// } -// } -// } diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index c678df7155..b6c70e866d 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -93,6 +93,7 @@ public: static void showFromObject(const LLUUID& object_id, const LLUUID& experience_id = LLUUID::null); static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name); + static void showFromChat(const LLUUID& avatar_id, const std::string& avatar_name, const std::string& time, const std::string& description); static void showFromExperience(const LLUUID& experience_id); static void onClickSend (void *userdata); @@ -101,8 +102,6 @@ public: void onClickSelectAbuser (); static void closePickTool (void *userdata); static void uploadDoneCallback(const LLUUID &uuid, void* user_data, S32 result, LLExtStat ext_status); - static void addDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); - static void setDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id); @@ -114,10 +113,8 @@ private: static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null, const LLUUID& experience_id = LLUUID::null); void takeScreenshot(bool use_prev_screenshot = false); - void sendReportViaCaps(std::string url); void uploadImage(); bool validateReport(); - void setReporterID(); LLSD gatherReport(); void sendReportViaLegacy(const LLSD & report); void sendReportViaCaps(std::string url, std::string sshot_url, const LLSD & report); @@ -144,7 +141,6 @@ private: BOOL mPicking; LLVector3 mPosition; BOOL mCopyrightWarningSeen; - std::list<LLMeanCollisionData*> mMCDList; std::string mDefaultSummary; LLResourceData* mResourceDatap; boost::signals2::connection mAvatarNameCacheConnection; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 2e1fbb09e0..bb3ed77772 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -57,10 +57,10 @@ public: const size_t parts = tokens.size(); // get the (optional) category for the search - std::string category; + std::string collection; if (parts > 0) { - category = tokens[0].asString(); + collection = tokens[0].asString(); } // get the (optional) search string @@ -72,7 +72,7 @@ public: // create the LLSD arguments for the search floater LLFloaterSearch::Params p; - p.search.category = category; + p.search.collection = collection; p.search.query = LLURI::unescape(search_text); // open the search floater and perform the requested search @@ -83,8 +83,9 @@ public: LLSearchHandler gSearchHandler; LLFloaterSearch::SearchQuery::SearchQuery() -: category("category", ""), - query("query") +: category("category", ""), + collection("collection", ""), + query("query") {} LLFloaterSearch::LLFloaterSearch(const Params& key) : @@ -93,16 +94,16 @@ LLFloaterSearch::LLFloaterSearch(const Params& key) : { // declare a map that transforms a category name into // the URL suffix that is used to search that category - mCategoryPaths = LLSD::emptyMap(); - mCategoryPaths["all"] = "search"; - mCategoryPaths["people"] = "search/people"; - mCategoryPaths["places"] = "search/places"; - mCategoryPaths["events"] = "search/events"; - mCategoryPaths["groups"] = "search/groups"; - mCategoryPaths["wiki"] = "search/wiki"; - mCategoryPaths["land"] = "land"; - mCategoryPaths["destinations"] = "destinations"; - mCategoryPaths["classifieds"] = "classifieds"; + + mSearchType.insert("standard"); + mSearchType.insert("land"); + mSearchType.insert("classified"); + + mCollectionType.insert("events"); + mCollectionType.insert("destinations"); + mCollectionType.insert("places"); + mCollectionType.insert("groups"); + mCollectionType.insert("people"); } BOOL LLFloaterSearch::postBuild() @@ -157,31 +158,49 @@ void LLFloaterSearch::search(const SearchQuery &p) // work out the subdir to use based on the requested category LLSD subs; - if (mCategoryPaths.has(p.category)) + if (mSearchType.find(p.category) != mSearchType.end()) { - subs["CATEGORY"] = mCategoryPaths[p.category].asString(); + subs["TYPE"] = p.category; } else { - subs["CATEGORY"] = mCategoryPaths["all"].asString(); + subs["TYPE"] = "standard"; } // add the search query string subs["QUERY"] = LLURI::escape(p.query); + subs["COLLECTION"] = ""; + if (subs["TYPE"] == "standard") + { + if (mCollectionType.find(p.collection) != mCollectionType.end()) + { + subs["COLLECTION"] = "&collection_chosen=" + std::string(p.collection); + } + else + { + std::string collection_args(""); + for (std::set<std::string>::iterator it = mCollectionType.begin(); it != mCollectionType.end(); ++it) + { + collection_args += "&collection_chosen=" + std::string(*it); + } + subs["COLLECTION"] = collection_args; + } + } + // add the user's preferred maturity (can be changed via prefs) std::string maturity; if (gAgent.prefersAdult()) { - maturity = "42"; // PG,Mature,Adult + maturity = "gma"; // PG,Mature,Adult } else if (gAgent.prefersMature()) { - maturity = "21"; // PG,Mature + maturity = "gm"; // PG,Mature } else { - maturity = "13"; // PG + maturity = "g"; // PG } subs["MATURITY"] = maturity; diff --git a/indra/newview/llfloatersearch.h b/indra/newview/llfloatersearch.h index 35b268e1b2..cc77ce696f 100644 --- a/indra/newview/llfloatersearch.h +++ b/indra/newview/llfloatersearch.h @@ -49,6 +49,7 @@ public: struct SearchQuery : public LLInitParam::Block<SearchQuery> { Optional<std::string> category; + Optional<std::string> collection; Optional<std::string> query; SearchQuery(); @@ -84,7 +85,8 @@ public: private: /*virtual*/ BOOL postBuild(); - LLSD mCategoryPaths; + std::set<std::string> mSearchType; + std::set<std::string> mCollectionType; U8 mSearchGodLevel; }; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 0429749e11..b6acba6558 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -46,7 +46,6 @@ #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llmediaentry.h" -#include "llmediactrl.h" #include "llmenugl.h" #include "llnotificationsutil.h" #include "llpanelcontents.h" @@ -240,7 +239,6 @@ BOOL LLFloaterTools::postBuild() mRadioGroupMove = getChild<LLRadioGroup>("move_radio_group"); mRadioGroupEdit = getChild<LLRadioGroup>("edit_radio_group"); mBtnGridOptions = getChild<LLButton>("Options..."); - mTitleMedia = getChild<LLMediaCtrl>("title_media"); mBtnLink = getChild<LLButton>("link_btn"); mBtnUnlink = getChild<LLButton>("unlink_btn"); @@ -329,7 +327,6 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mCheckSnapToGrid(NULL), mBtnGridOptions(NULL), - mTitleMedia(NULL), mComboGridMode(NULL), mCheckStretchUniform(NULL), mCheckStretchTexture(NULL), @@ -369,8 +366,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mLandImpactsObserver(NULL), mDirty(TRUE), - mHasSelection(TRUE), - mNeedMediaTitle(TRUE) + mHasSelection(TRUE) { gFloaterTools = this; @@ -394,9 +390,6 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this)); mCommitCallbackRegistrar.add("BuildTool.commitRadioLand", boost::bind(&commit_radio_group_land,_1)); mCommitCallbackRegistrar.add("BuildTool.LandBrushForce", boost::bind(&commit_slider_dozer_force,_1)); - mCommitCallbackRegistrar.add("BuildTool.AddMedia", boost::bind(&LLFloaterTools::onClickBtnAddMedia,this)); - mCommitCallbackRegistrar.add("BuildTool.DeleteMedia", boost::bind(&LLFloaterTools::onClickBtnDeleteMedia,this)); - mCommitCallbackRegistrar.add("BuildTool.EditMedia", boost::bind(&LLFloaterTools::onClickBtnEditMedia,this)); mCommitCallbackRegistrar.add("BuildTool.LinkObjects", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance())); mCommitCallbackRegistrar.add("BuildTool.UnlinkObjects", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance())); @@ -480,30 +473,61 @@ void LLFloaterTools::refresh() else #endif { - F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); - S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + F32 link_cost = selection->getSelectedLinksetCost(); + S32 link_count = selection->getRootObjectCount(); + S32 object_count = selection->getObjectCount(); - LLCrossParcelFunctor func; - if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) - { - // Selection crosses parcel bounds. - // We don't display remaining land capacity in this case. - const LLStringExplicit empty_str(""); - childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", empty_str); - } - else - { - LLViewerObject* selected_object = mObjectSelection->getFirstObject(); - if (selected_object) - { - // Select a parcel at the currently selected object's position. - LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); - } - else - { - LL_WARNS() << "Failed to get selected object" << LL_ENDL; - } - } + LLCrossParcelFunctor func; + if (!LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) + { + // Unless multiple parcels selected, higlight parcel object is at. + LLViewerObject* selected_object = mObjectSelection->getFirstObject(); + if (selected_object) + { + // Select a parcel at the currently selected object's position. + LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); + } + else + { + LL_WARNS() << "Failed to get selected object" << LL_ENDL; + } + } + + if (object_count == 1) + { + // "selection_faces" shouldn't be visible if not LLToolFace::getInstance() + // But still need to be populated in case user switches + + std::string faces_str = ""; + + for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end();) + { + LLObjectSelection::iterator nextiter = iter++; // not strictly needed, we have only one object + LLSelectNode* node = *nextiter; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + if (!faces_str.empty()) + { + faces_str += ", "; + } + faces_str += llformat("%d", te); + } + } + } + + childSetTextArg("selection_faces", "[FACES_STRING]", faces_str); + } + + bool show_faces = (object_count == 1) + && LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + getChildView("selection_faces")->setVisible(show_faces); LLStringUtil::format_map_t selection_args; selection_args["OBJ_COUNT"] = llformat("%.1d", link_count); @@ -522,7 +546,7 @@ void LLFloaterTools::refresh() mPanelObject->refresh(); mPanelVolume->refresh(); mPanelFace->refresh(); - refreshMedia(); + mPanelFace->refreshMedia(); mPanelContents->refresh(); mPanelLandInfo->refresh(); @@ -549,9 +573,6 @@ void LLFloaterTools::draw() mDirty = FALSE; } - // grab media name/title and update the UI widget - updateMediaTitle(); - // mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts")); LLFloater::draw(); } @@ -824,7 +845,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty(); getChildView("selection_count")->setVisible(!land_visible && have_selection); - getChildView("remaining_capacity")->setVisible(!land_visible && have_selection); + getChildView("selection_faces")->setVisible(LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool() + && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1); getChildView("selection_empty")->setVisible(!land_visible && !have_selection); mTab->setVisible(!land_visible); @@ -874,8 +896,7 @@ void LLFloaterTools::onClose(bool app_quitting) LLViewerJoystick::getInstance()->moveAvatar(false); // destroy media source used to grab media title - if( mTitleMedia ) - mTitleMedia->unloadMediaSource(); + mPanelFace->unloadMedia(); // Different from handle_reset_view in that it doesn't actually // move the camera if EditCameraMovement is not set. @@ -1095,7 +1116,7 @@ void LLFloaterTools::onClickGridOptions() { LLFloater* floaterp = LLFloaterReg::showInstance("build_options"); // position floater next to build tools, not over - floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp)); + floaterp->setShape(gFloaterView->findNeighboringPosition(this, floaterp), true); } // static @@ -1128,51 +1149,6 @@ void LLFloaterTools::onFocusReceived() LLFloater::onFocusReceived(); } -// Media stuff -void LLFloaterTools::refreshMedia() -{ - getMediaState(); -} - -bool LLFloaterTools::selectedMediaEditable() -{ - U32 owner_mask_on; - U32 owner_mask_off; - U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_OWNER, - &owner_mask_on, &owner_mask_off ); - U32 group_mask_on; - U32 group_mask_off; - U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_GROUP, - &group_mask_on, &group_mask_off ); - U32 everyone_mask_on; - U32 everyone_mask_off; - S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_EVERYONE, - &everyone_mask_on, &everyone_mask_off ); - - bool selected_Media_editable = false; - - // if perms we got back are valid - if ( valid_owner_perms && - valid_group_perms && - valid_everyone_perms ) - { - - if ( ( owner_mask_on & PERM_MODIFY ) || - ( group_mask_on & PERM_MODIFY ) || - ( group_mask_on & PERM_MODIFY ) ) - { - selected_Media_editable = true; - } - else - // user is NOT allowed to press the RESET button - { - selected_Media_editable = false; - }; - }; - - return selected_Media_editable; -} - void LLFloaterTools::updateLandImpacts() { LLParcel *parcel = mParcelSelection->getParcel(); @@ -1181,26 +1157,6 @@ void LLFloaterTools::updateLandImpacts() return; } - S32 rezzed_prims = parcel->getSimWidePrimCount(); - S32 total_capacity = parcel->getSimWideMaxPrimCapacity(); - LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (region) - { - S32 max_tasks_per_region = (S32)region->getMaxTasks(); - total_capacity = llmin(total_capacity, max_tasks_per_region); - } - std::string remaining_capacity_str = ""; - - bool show_mesh_cost = gMeshRepo.meshRezEnabled(); - if (show_mesh_cost) - { - LLStringUtil::format_map_t remaining_capacity_args; - remaining_capacity_args["LAND_CAPACITY"] = llformat("%d", total_capacity - rezzed_prims); - remaining_capacity_str = getString("status_remaining_capacity", remaining_capacity_args); - } - - childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str); - // Update land impacts info in the weights floater LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights"); if(object_weights_floater) @@ -1209,784 +1165,3 @@ void LLFloaterTools::updateLandImpacts() } } -void LLFloaterTools::getMediaState() -{ - LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); - LLViewerObject* first_object = selected_objects->getFirstObject(); - LLTextBox* media_info = getChild<LLTextBox>("media_info"); - - if( !(first_object - && first_object->getPCode() == LL_PCODE_VOLUME - &&first_object->permModify() - )) - { - getChildView("add_media")->setEnabled(FALSE); - media_info->clear(); - clearMediaSettings(); - return; - } - - std::string url = first_object->getRegion()->getCapability("ObjectMedia"); - bool has_media_capability = (!url.empty()); - - if(!has_media_capability) - { - getChildView("add_media")->setEnabled(FALSE); - LL_WARNS("LLFloaterToolsMedia") << "Media not enabled (no capability) in this region!" << LL_ENDL; - clearMediaSettings(); - return; - } - - BOOL is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() - && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) - || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced(); - bool editable = is_nonpermanent_enforced && (first_object->permModify() || selectedMediaEditable()); - - // Check modify permissions and whether any selected objects are in - // the process of being fetched. If they are, then we're not editable - if (editable) - { - LLObjectSelection::iterator iter = selected_objects->begin(); - LLObjectSelection::iterator end = selected_objects->end(); - for ( ; iter != end; ++iter) - { - LLSelectNode* node = *iter; - LLVOVolume* object = dynamic_cast<LLVOVolume*>(node->getObject()); - if (NULL != object) - { - if (!object->permModify()) - { - LL_INFOS("LLFloaterToolsMedia") - << "Selection not editable due to lack of modify permissions on object id " - << object->getID() << LL_ENDL; - - editable = false; - break; - } - // XXX DISABLE this for now, because when the fetch finally - // does come in, the state of this floater doesn't properly - // update. Re-selecting fixes the problem, but there is - // contention as to whether this is a sufficient solution. -// if (object->isMediaDataBeingFetched()) -// { -// LL_INFOS("LLFloaterToolsMedia") -// << "Selection not editable due to media data being fetched for object id " -// << object->getID() << LL_ENDL; -// -// editable = false; -// break; -// } - } - } - } - - // Media settings - bool bool_has_media = false; - struct media_functor : public LLSelectedTEGetFunctor<bool> - { - bool get(LLViewerObject* object, S32 face) - { - LLTextureEntry *te = object->getTE(face); - if (te) - { - return te->hasMedia(); - } - return false; - } - } func; - - - // check if all faces have media(or, all dont have media) - LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, bool_has_media ); - - const LLMediaEntry default_media_data; - - struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry> - { - functor_getter_media_data(const LLMediaEntry& entry): mMediaEntry(entry) {} - - LLMediaEntry get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return *(object->getTE(face)->getMediaData()); - return mMediaEntry; - }; - - const LLMediaEntry& mMediaEntry; - - } func_media_data(default_media_data); - - LLMediaEntry media_data_get; - LLFloaterMediaSettings::getInstance()->mMultipleMedia = !(selected_objects->getSelectedTEValue( &func_media_data, media_data_get )); - - std::string multi_media_info_str = LLTrans::getString("Multiple Media"); - std::string media_title = ""; - // update UI depending on whether "object" (prim or face) has media - // and whether or not you are allowed to edit it. - - getChildView("add_media")->setEnabled(editable); - // IF all the faces have media (or all dont have media) - if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) - { - // TODO: get media title and set it. - media_info->clear(); - // if identical is set, all faces are same (whether all empty or has the same media) - if(!(LLFloaterMediaSettings::getInstance()->mMultipleMedia) ) - { - // Media data is valid - if(media_data_get!=default_media_data) - { - // initial media title is the media URL (until we get the name) - media_title = media_data_get.getHomeURL(); - } - // else all faces might be empty. - } - else // there' re Different Medias' been set on on the faces. - { - media_title = multi_media_info_str; - } - - getChildView("delete_media")->setEnabled(bool_has_media && editable ); - // TODO: display a list of all media on the face - use 'identical' flag - } - else // not all face has media but at least one does. - { - // seleted faces have not identical value - LLFloaterMediaSettings::getInstance()->mMultipleValidMedia = selected_objects->isMultipleTEValue(&func_media_data, default_media_data ); - - if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) - { - media_title = multi_media_info_str; - } - else - { - // Media data is valid - if(media_data_get!=default_media_data) - { - // initial media title is the media URL (until we get the name) - media_title = media_data_get.getHomeURL(); - } - } - - getChildView("delete_media")->setEnabled(TRUE); - } - - navigateToTitleMedia(media_title); - media_info->setText(media_title); - - // load values for media settings - updateMediaSettings(); - - LLFloaterMediaSettings::initValues(mMediaSettings, editable ); -} - - -////////////////////////////////////////////////////////////////////////////// -// called when a user wants to add media to a prim or prim face -void LLFloaterTools::onClickBtnAddMedia() -{ - // check if multiple faces are selected - if(LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) - { - LLNotificationsUtil::add("MultipleFacesSelected", LLSD(), LLSD(), multipleFacesSelectedConfirm); - } - else - { - onClickBtnEditMedia(); - } -} - -// static -bool LLFloaterTools::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch( option ) - { - case 0: // "Yes" - gFloaterTools->onClickBtnEditMedia(); - break; - case 1: // "No" - default: - break; - } - return false; -} - -////////////////////////////////////////////////////////////////////////////// -// called when a user wants to edit existing media settings on a prim or prim face -// TODO: test if there is media on the item and only allow editing if present -void LLFloaterTools::onClickBtnEditMedia() -{ - refreshMedia(); - LLFloaterReg::showInstance("media_settings"); -} - -////////////////////////////////////////////////////////////////////////////// -// called when a user wants to delete media from a prim or prim face -void LLFloaterTools::onClickBtnDeleteMedia() -{ - LLNotificationsUtil::add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm); -} - - -// static -bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch( option ) - { - case 0: // "Yes" - LLSelectMgr::getInstance()->selectionSetMedia( 0, LLSD() ); - if(LLFloaterReg::instanceVisible("media_settings")) - { - LLFloaterReg::hideInstance("media_settings"); - } - break; - - case 1: // "No" - default: - break; - } - return false; -} - -////////////////////////////////////////////////////////////////////////////// -// -void LLFloaterTools::clearMediaSettings() -{ - LLFloaterMediaSettings::clearValues(false); -} - -////////////////////////////////////////////////////////////////////////////// -// -void LLFloaterTools::navigateToTitleMedia( const std::string url ) -{ - std::string multi_media_info_str = LLTrans::getString("Multiple Media"); - if (url.empty() || multi_media_info_str == url) - { - // nothing to show - mNeedMediaTitle = false; - } - else if (mTitleMedia) - { - LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); - - if ( media_plugin ) // Shouldn't this be after navigateTo creates plugin? - { - // if it's a movie, we don't want to hear it - media_plugin->setVolume( 0 ); - }; - - // check if url changed or if we need a new media source - if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL) - { - mTitleMedia->navigateTo( url ); - } - - // flag that we need to update the title (even if no request were made) - mNeedMediaTitle = true; - } -} - -////////////////////////////////////////////////////////////////////////////// -// -void LLFloaterTools::updateMediaTitle() -{ - // only get the media name if we need it - if ( ! mNeedMediaTitle ) - return; - - // get plugin impl - LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); - if ( media_plugin ) - { - // get the media name (asynchronous - must call repeatedly) - std::string media_title = media_plugin->getMediaName(); - - // only replace the title if what we get contains something - if ( ! media_title.empty() ) - { - // update the UI widget - LLTextBox* media_title_field = getChild<LLTextBox>("media_info"); - if ( media_title_field ) - { - media_title_field->setText( media_title ); - - // stop looking for a title when we get one - // FIXME: check this is the right approach - mNeedMediaTitle = false; - }; - }; - }; -} - -////////////////////////////////////////////////////////////////////////////// -// -void LLFloaterTools::updateMediaSettings() -{ - bool identical( false ); - std::string base_key( "" ); - std::string value_str( "" ); - int value_int = 0; - bool value_bool = false; - LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); - // TODO: (CP) refactor this using something clever or boost or both !! - - const LLMediaEntry default_media_data; - - // controls - U8 value_u8 = default_media_data.getControls(); - struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 > - { - functor_getter_controls(const LLMediaEntry &entry) : mMediaEntry(entry) {} - - U8 get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getControls(); - return mMediaEntry.getControls(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_controls(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_controls, value_u8 ); - base_key = std::string( LLMediaEntry::CONTROLS_KEY ); - mMediaSettings[ base_key ] = value_u8; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // First click (formerly left click) - value_bool = default_media_data.getFirstClickInteract(); - struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool > - { - functor_getter_first_click(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getFirstClickInteract(); - return mMediaEntry.getFirstClickInteract(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_first_click(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_first_click, value_bool ); - base_key = std::string( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Home URL - value_str = default_media_data.getHomeURL(); - struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string > - { - functor_getter_home_url(const LLMediaEntry& entry): mMediaEntry(entry) {} - - std::string get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getHomeURL(); - return mMediaEntry.getHomeURL(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_home_url(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_home_url, value_str ); - base_key = std::string( LLMediaEntry::HOME_URL_KEY ); - mMediaSettings[ base_key ] = value_str; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Current URL - value_str = default_media_data.getCurrentURL(); - struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string > - { - functor_getter_current_url(const LLMediaEntry& entry): mMediaEntry(entry) {} - - std::string get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getCurrentURL(); - return mMediaEntry.getCurrentURL(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_current_url(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_current_url, value_str ); - base_key = std::string( LLMediaEntry::CURRENT_URL_KEY ); - mMediaSettings[ base_key ] = value_str; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Auto zoom - value_bool = default_media_data.getAutoZoom(); - struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool > - { - - functor_getter_auto_zoom(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getAutoZoom(); - return mMediaEntry.getAutoZoom(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_auto_zoom(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_auto_zoom, value_bool ); - base_key = std::string( LLMediaEntry::AUTO_ZOOM_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Auto play - //value_bool = default_media_data.getAutoPlay(); - // set default to auto play TRUE -- angela EXT-5172 - value_bool = true; - struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool > - { - functor_getter_auto_play(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getAutoPlay(); - //return mMediaEntry.getAutoPlay(); set default to auto play TRUE -- angela EXT-5172 - return true; - }; - - const LLMediaEntry &mMediaEntry; - - } func_auto_play(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_auto_play, value_bool ); - base_key = std::string( LLMediaEntry::AUTO_PLAY_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - - // Auto scale - // set default to auto scale TRUE -- angela EXT-5172 - //value_bool = default_media_data.getAutoScale(); - value_bool = true; - struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool > - { - functor_getter_auto_scale(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getAutoScale(); - // return mMediaEntry.getAutoScale(); set default to auto scale TRUE -- angela EXT-5172 - return true; - }; - - const LLMediaEntry &mMediaEntry; - - } func_auto_scale(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_auto_scale, value_bool ); - base_key = std::string( LLMediaEntry::AUTO_SCALE_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Auto loop - value_bool = default_media_data.getAutoLoop(); - struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool > - { - functor_getter_auto_loop(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getAutoLoop(); - return mMediaEntry.getAutoLoop(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_auto_loop(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_auto_loop, value_bool ); - base_key = std::string( LLMediaEntry::AUTO_LOOP_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // width pixels (if not auto scaled) - value_int = default_media_data.getWidthPixels(); - struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int > - { - functor_getter_width_pixels(const LLMediaEntry& entry): mMediaEntry(entry) {} - - int get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getWidthPixels(); - return mMediaEntry.getWidthPixels(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_width_pixels(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_width_pixels, value_int ); - base_key = std::string( LLMediaEntry::WIDTH_PIXELS_KEY ); - mMediaSettings[ base_key ] = value_int; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // height pixels (if not auto scaled) - value_int = default_media_data.getHeightPixels(); - struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int > - { - functor_getter_height_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - int get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getHeightPixels(); - return mMediaEntry.getHeightPixels(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_height_pixels(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_height_pixels, value_int ); - base_key = std::string( LLMediaEntry::HEIGHT_PIXELS_KEY ); - mMediaSettings[ base_key ] = value_int; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Enable Alt image - value_bool = default_media_data.getAltImageEnable(); - struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool > - { - functor_getter_enable_alt_image(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getAltImageEnable(); - return mMediaEntry.getAltImageEnable(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_enable_alt_image(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_enable_alt_image, value_bool ); - base_key = std::string( LLMediaEntry::ALT_IMAGE_ENABLE_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - owner interact - value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER ); - struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_owner_interact(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER)); - return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_owner_interact(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_perms_owner_interact, value_bool ); - base_key = std::string( LLPanelContents::PERMS_OWNER_INTERACT_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - owner control - value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER ); - struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_owner_control(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER)); - return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_owner_control(default_media_data); - identical = selected_objects ->getSelectedTEValue( &func_perms_owner_control, value_bool ); - base_key = std::string( LLPanelContents::PERMS_OWNER_CONTROL_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - group interact - value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP ); - struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_group_interact(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP)); - return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_group_interact(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_perms_group_interact, value_bool ); - base_key = std::string( LLPanelContents::PERMS_GROUP_INTERACT_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - group control - value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP ); - struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_group_control(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP)); - return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_group_control(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_perms_group_control, value_bool ); - base_key = std::string( LLPanelContents::PERMS_GROUP_CONTROL_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - anyone interact - value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE ); - struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_anyone_interact(const LLMediaEntry& entry): mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE)); - return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_anyone_interact(default_media_data); - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_perms_anyone_interact, value_bool ); - base_key = std::string( LLPanelContents::PERMS_ANYONE_INTERACT_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // Perms - anyone control - value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE ); - struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool > - { - functor_getter_perms_anyone_control(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE)); - return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE ); - }; - - const LLMediaEntry &mMediaEntry; - - } func_perms_anyone_control(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_perms_anyone_control, value_bool ); - base_key = std::string( LLPanelContents::PERMS_ANYONE_CONTROL_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // security - whitelist enable - value_bool = default_media_data.getWhiteListEnable(); - struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool > - { - functor_getter_whitelist_enable(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getWhiteListEnable(); - return mMediaEntry.getWhiteListEnable(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_whitelist_enable(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_whitelist_enable, value_bool ); - base_key = std::string( LLMediaEntry::WHITELIST_ENABLE_KEY ); - mMediaSettings[ base_key ] = value_bool; - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; - - // security - whitelist URLs - std::vector<std::string> value_vector_str = default_media_data.getWhiteList(); - struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector<std::string> > - { - functor_getter_whitelist_urls(const LLMediaEntry& entry): mMediaEntry(entry) {} - - std::vector<std::string> get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - return object->getTE(face)->getMediaData()->getWhiteList(); - return mMediaEntry.getWhiteList(); - }; - - const LLMediaEntry &mMediaEntry; - - } func_whitelist_urls(default_media_data); - identical = selected_objects->getSelectedTEValue( &func_whitelist_urls, value_vector_str ); - base_key = std::string( LLMediaEntry::WHITELIST_KEY ); - mMediaSettings[ base_key ].clear(); - std::vector< std::string >::iterator iter = value_vector_str.begin(); - while( iter != value_vector_str.end() ) - { - std::string white_list_url = *iter; - mMediaSettings[ base_key ].append( white_list_url ); - ++iter; - }; - - mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; -} - diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index ffff564ad4..3bb6492a6e 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -44,7 +44,6 @@ class LLRadioGroup; class LLSlider; class LLTabContainer; class LLTextBox; -class LLMediaCtrl; class LLTool; class LLParcelSelection; class LLObjectSelection; @@ -98,11 +97,6 @@ public: static void setEditTool(void* data); void setTool(const LLSD& user_data); void saveLastTool(); - void onClickBtnDeleteMedia(); - void onClickBtnAddMedia(); - void onClickBtnEditMedia(); - void clearMediaSettings(); - bool selectedMediaEditable(); void updateLandImpacts(); static void setGridMode(S32 mode); @@ -111,13 +105,6 @@ public: private: void refresh(); - void refreshMedia(); - void getMediaState(); - void updateMediaSettings(); - void navigateToTitleMedia( const std::string url ); // navigate if changed - void updateMediaTitle(); - static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response); - static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response); static void setObjectType( LLPCode pcode ); void onClickGridOptions(); @@ -193,19 +180,12 @@ public: LLParcelSelectionHandle mParcelSelection; LLObjectSelectionHandle mObjectSelection; - LLMediaCtrl *mTitleMedia; - bool mNeedMediaTitle; - private: BOOL mDirty; BOOL mHasSelection; std::map<std::string, std::string> mStatusText; - -protected: - LLSD mMediaSettings; - public: static bool sShowObjectCost; static bool sPreviousFocusOnAvatar; diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index d5c2ad5f81..917d6dfcd0 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -112,16 +112,6 @@ void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_ panel_media->setMediaType(mime_type); panel_media->setMediaURL(mMediaURLEdit->getValue().asString()); } - else - { - LLPanelFace* panel_face = dynamic_cast<LLPanelFace*>(mPanelLandMediaHandle.get()); - if(panel_face) - { - panel_face->setMediaType(mime_type); - panel_face->setMediaURL(mMediaURLEdit->getValue().asString()); - } - - } getChildView("loading_label")->setVisible( false); closeFloater(); diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index 59e1f49f81..23f19dd5aa 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -127,7 +127,7 @@ void LLFloaterVoiceVolume::onOpen(const LLSD& data) // Extract appropriate avatar id mAvatarID = data["avatar_id"]; - LLUI::getInstance()->positionViewNearMouse(this); + LLInspect::repositionInspector(data); getChild<LLUICtrl>("avatar_name")->setValue(""); updateVolumeControls(); diff --git a/indra/newview/llfloaterwebprofile.cpp b/indra/newview/llfloaterwebprofile.cpp deleted file mode 100644 index 891bb90c0e..0000000000 --- a/indra/newview/llfloaterwebprofile.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file llfloaterwebprofile.cpp - * @brief Avatar profile floater. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterwebprofile.h" - -#include "llviewercontrol.h" - -LLFloaterWebProfile::LLFloaterWebProfile(const Params& key) : - LLFloaterWebContent(key) -{ -} - -void LLFloaterWebProfile::onOpen(const LLSD& key) -{ - Params p(key); - p.show_chrome(true); - p.window_class("profile"); - p.allow_address_entry(false); - p.trusted_content(true); - LLFloaterWebContent::onOpen(p); - applyPreferredRect(); -} - -// virtual -void LLFloaterWebProfile::handleReshape(const LLRect& new_rect, bool by_user) -{ - LL_DEBUGS() << "handleReshape: " << new_rect << LL_ENDL; - - if (by_user && !isMinimized()) - { - LL_DEBUGS() << "Storing new rect" << LL_ENDL; - gSavedSettings.setRect("WebProfileFloaterRect", new_rect); - } - - LLFloaterWebContent::handleReshape(new_rect, by_user); -} - -LLFloater* LLFloaterWebProfile::create(const LLSD& key) -{ - LLFloaterWebContent::Params p(key); - preCreate(p); - return new LLFloaterWebProfile(p); -} - -void LLFloaterWebProfile::applyPreferredRect() -{ - const LLRect preferred_rect = gSavedSettings.getRect("WebProfileFloaterRect"); - LL_DEBUGS() << "Applying preferred rect: " << preferred_rect << LL_ENDL; - - // Don't override position that may have been set by floater stacking code. - LLRect new_rect = getRect(); - new_rect.setLeftTopAndSize( - new_rect.mLeft, new_rect.mTop, - preferred_rect.getWidth(), preferred_rect.getHeight()); - setShape(new_rect); -} diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 2c84cd1f93..01bfae8934 100644..100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -45,6 +45,7 @@ //#include "llfirstuse.h" #include "llfloaterreg.h" // getTypedInstance() #include "llfocusmgr.h" +#include "lliconctrl.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" @@ -81,7 +82,6 @@ //--------------------------------------------------------------------------- // Constants //--------------------------------------------------------------------------- -static const F32 MAP_ZOOM_TIME = 0.2f; // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across @@ -284,7 +284,7 @@ void* LLFloaterWorldMap::createWorldMapView(void* data) BOOL LLFloaterWorldMap::postBuild() { - mPanel = getChild<LLPanel>("objects_mapview"); + mMapView = dynamic_cast<LLWorldMapView*>(getChild<LLPanel>("objects_mapview")); LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); avatar_combo->selectFirstItem(); @@ -305,13 +305,13 @@ BOOL LLFloaterWorldMap::postBuild() landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo); - mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f); - getChild<LLUICtrl>("zoom slider")->setValue(mCurZoomVal); + F32 slider_zoom = mMapView->getZoom(); + getChild<LLUICtrl>("zoom slider")->setValue(slider_zoom); + + getChild<LLPanel>("expand_btn_panel")->setMouseDownCallback(boost::bind(&LLFloaterWorldMap::onExpandCollapseBtn, this)); setDefaultBtn(NULL); - mZoomTimer.stop(); - onChangeMaturity(); return TRUE; @@ -321,7 +321,7 @@ BOOL LLFloaterWorldMap::postBuild() LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor - mPanel = NULL; + mMapView = NULL; // Inventory deletes all observers on shutdown mInventory = NULL; @@ -359,17 +359,15 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) mIsClosing = FALSE; - LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; - map_panel->clearLastClick(); + mMapView->clearLastClick(); { // reset pan on show, so it centers on you again if (!center_on_target) { - LLWorldMapView::setPan(0, 0, TRUE); + mMapView->setPan(0, 0, true); } - map_panel->updateVisibleBlocks(); + mMapView->updateVisibleBlocks(); // Reload items as they may have changed LLWorldMap::getInstance()->reloadItems(); @@ -417,18 +415,21 @@ BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask) BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if (!isMinimized() && isFrontmost()) - { - if(mPanel->pointInView(x, y)) - { - F32 slider_value = (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(); - slider_value += ((F32)clicks * -0.3333f); - getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_value)); - return TRUE; - } - } - - return LLFloater::handleScrollWheel(x, y, clicks); + if (!isMinimized() && isFrontmost()) + { + S32 map_x = x - mMapView->getRect().mLeft; + S32 map_y = y - mMapView->getRect().mBottom; + if (mMapView->pointInView(map_x, map_y)) + { + F32 old_slider_zoom = (F32) getChild<LLUICtrl>("zoom slider")->getValue().asReal(); + F32 slider_zoom = old_slider_zoom + ((F32) clicks * -0.3333f); + getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_zoom)); + mMapView->zoomWithPivot(slider_zoom, map_x, map_y); + return true; + } + } + + return LLFloater::handleScrollWheel(x, y, clicks); } @@ -507,26 +508,13 @@ void LLFloaterWorldMap::draw() setMouseOpaque(TRUE); getDragHandle()->setMouseOpaque(TRUE); - - //RN: snaps to zoom value because interpolation caused jitter in the text rendering - if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal()) - { - mZoomTimer.start(); - } - F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; - if (interp > 1.f) - { - interp = 1.f; - mZoomTimer.stop(); - } - mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp); - F32 map_scale = 256.f*pow(2.f, mCurZoomVal); - LLWorldMapView::setScale( map_scale ); + + mMapView->zoom((F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal()); // Enable/disable checkboxes depending on the zoom level // If above threshold level (i.e. low res) -> Disable all checkboxes // If under threshold level (i.e. high res) -> Enable all checkboxes - bool enable = LLWorldMapView::showRegionInfo(); + bool enable = mMapView->showRegionInfo(); getChildView("people_chk")->setEnabled(enable); getChildView("infohub_chk")->setEnabled(enable); getChildView("telehub_chk")->setEnabled(enable); @@ -1005,7 +993,7 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) { mTrackedStatus = LLTracker::TRACKING_NOTHING; LLCtrlListInterface *list = mListFriendCombo; - if (list) + if (list && list->getSelectedValue().asString() != "None") { list->selectByValue( "None" ); } @@ -1025,9 +1013,7 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() S32 world_height_regions = MAX_VISIBLE_REGIONS; // Find how much space we have to display the world - LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)mPanel; - LLRect view_rect = map_panel->getRect(); + LLRect view_rect = mMapView->getRect(); // View size in pixels S32 view_width = view_rect.getWidth(); @@ -1295,9 +1281,9 @@ void LLFloaterWorldMap::onShowTargetBtn() void LLFloaterWorldMap::onShowAgentBtn() { - LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate - // Set flag so user's location will be displayed if not tracking anything else - mSetToUserPosition = TRUE; + mMapView->setPanWithInterpTime(0, 0, false, 0.1f); // false == animate + // Set flag so user's location will be displayed if not tracking anything else + mSetToUserPosition = true; } void LLFloaterWorldMap::onClickTeleportBtn() @@ -1315,6 +1301,22 @@ void LLFloaterWorldMap::onCopySLURL() LLNotificationsUtil::add("CopySLURL", args); } +void LLFloaterWorldMap::onExpandCollapseBtn() +{ + LLLayoutStack* floater_stack = getChild<LLLayoutStack>("floater_map_stack"); + LLLayoutPanel* controls_panel = getChild<LLLayoutPanel>("controls_lp"); + + bool toggle_collapse = !controls_panel->isCollapsed(); + floater_stack->collapsePanel(controls_panel, toggle_collapse); + floater_stack->updateLayout(); + + std::string image_name = getString(toggle_collapse ? "expand_icon" : "collapse_icon"); + std::string tooltip = getString(toggle_collapse ? "expand_tooltip" : "collapse_tooltip"); + getChild<LLIconCtrl>("expand_collapse_icon")->setImage(LLUI::getUIImage(image_name)); + getChild<LLIconCtrl>("expand_collapse_icon")->setToolTip(tooltip); + getChild<LLPanel>("expand_btn_panel")->setToolTip(tooltip); +} + // protected void LLFloaterWorldMap::centerOnTarget(BOOL animate) { @@ -1349,9 +1351,10 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global.clearVec(); } - LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), - -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), - !animate); + F64 map_scale = (F64)mMapView->getScale(); + mMapView->setPanWithInterpTime(-llfloor((F32)(pos_global.mdV[VX] * map_scale / REGION_WIDTH_METERS)), + -llfloor((F32)(pos_global.mdV[VY] * map_scale / REGION_WIDTH_METERS)), + !animate, 0.1f); mWaitingForTracker = FALSE; } @@ -1581,7 +1584,7 @@ void LLFloaterWorldMap::onTeleportFinished() { if(isInVisibleChain()) { - LLWorldMapView::setPan(0, 0, TRUE); + mMapView->setPan(0, 0, TRUE); } } @@ -1656,9 +1659,8 @@ void LLFloaterWorldMap::onChangeMaturity() void LLFloaterWorldMap::onFocusLost() { - gViewerWindow->showCursor(); - LLWorldMapView* map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; - map_panel->mPanning = FALSE; + gViewerWindow->showCursor(); + mMapView->mPanning = false; } LLPanelHideBeacon::LLPanelHideBeacon() : diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 14a9c26fb9..3702226d23 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -44,6 +44,7 @@ class LLInventoryObserver; class LLItemInfo; class LLLineEditor; class LLTabContainer; +class LLWorldMapView; class LLFloaterWorldMap : public LLFloater { @@ -130,6 +131,8 @@ protected: void onShowAgentBtn(); void onCopySLURL(); + void onExpandCollapseBtn(); + void centerOnTarget(BOOL animate); void updateLocation(); @@ -154,11 +157,7 @@ protected: void onTeleportFinished(); private: - LLPanel* mPanel; // Panel displaying the map - - // Ties to LLWorldMapView::sMapScale, in pixels per region - F32 mCurZoomVal; - LLFrameTimer mZoomTimer; + LLWorldMapView* mMapView; // Panel displaying the map // update display of teleport destination coordinates - pos is in global coordinates void updateTeleportCoordsDisplay( const LLVector3d& pos ); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 0be748ace9..e395da7f1e 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -327,22 +327,63 @@ void LLFriendCardsManager::syncFriendCardsFolders() /************************************************************************/ /* Private Methods */ /************************************************************************/ -const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const +const LLUUID& LLFriendCardsManager::findFirstCallingCardSubfolder(const LLUUID &parent_id) const { - const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + if (parent_id.isNull()) + { + return LLUUID::null; + } - std::string friendFolderName = get_friend_folder_name(); + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(parent_id, cats, items); - return findChildFolderUUID(callingCardsFolderID, friendFolderName); + if (!cats || !items || cats->size() == 0) + { + // call failed + return LLUUID::null; + } + + if (cats->size() > 1) + { + const LLViewerInventoryCategory* friendFolder = gInventory.getCategory(parent_id); + if (friendFolder) + { + LL_WARNS_ONCE() << friendFolder->getName() << " folder contains more than one folder" << LL_ENDL; + } + } + + for (LLInventoryModel::cat_array_t::const_iterator iter = cats->begin(); + iter != cats->end(); + ++iter) + { + const LLInventoryCategory* category = (*iter); + if (category->getPreferredType() == LLFolderType::FT_CALLINGCARD) + { + return category->getUUID(); + } + } + + return LLUUID::null; } -const LLUUID& LLFriendCardsManager::findFriendAllSubfolderUUIDImpl() const +// Inventorry -> +// Calling Cards - > +// Friends - > (the only expected folder) +// All (the only expected folder) + +const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const { - LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); + const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + + return findFirstCallingCardSubfolder(callingCardsFolderID); +} - std::string friendAllSubfolderName = get_friend_all_subfolder_name(); +const LLUUID& LLFriendCardsManager::findFriendAllSubfolderUUIDImpl() const +{ + LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); - return findChildFolderUUID(friendFolderUUID, friendAllSubfolderName); + return findFirstCallingCardSubfolder(friendFolderUUID); } const LLUUID& LLFriendCardsManager::findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& nonLocalizedName) const diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index 2fb912a930..f5679d7d85 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -116,6 +116,7 @@ private: } const LLUUID& findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& nonLocalizedName) const; + const LLUUID& findFirstCallingCardSubfolder(const LLUUID &parent_id) const; const LLUUID& findFriendFolderUUIDImpl() const; const LLUUID& findFriendAllSubfolderUUIDImpl() const; const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID); diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 91ab445273..7c8e8279c2 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -185,7 +185,7 @@ private: std::set<LLUUID> mLoadingAssets; // LLEventHost interface - boost::shared_ptr<LLGestureListener> mListener; + std::shared_ptr<LLGestureListener> mListener; }; #endif diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index e7bc2a9268..84a1278767 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -196,7 +196,7 @@ LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; // static void LLGroupActions::search() { - LLFloaterReg::showInstance("search"); + LLFloaterReg::showInstance("search", LLSD().with("collection", "groups")); } // static diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 62414d3bbb..32af2592d3 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -45,7 +45,6 @@ #include "llvoiceclient.h" static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); -S32 LLGroupListItem::sIconWidth = 0; class LLGroupComparator : public LLFlatListView::ItemComparator { @@ -65,21 +64,81 @@ public: } }; -static const LLGroupComparator GROUP_COMPARATOR; +class LLSharedGroupComparator : public LLFlatListView::ItemComparator +{ +public: + LLSharedGroupComparator() {}; + + /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const + { + const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1); + std::string name1 = group_item1->getGroupName(); + bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true); + + const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2); + std::string name2 = group_item2->getGroupName(); + bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true); + if (item2_shared != item1_shared) + { + return item1_shared; + } + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; + } +}; + +static LLGroupComparator GROUP_COMPARATOR; +static LLSharedGroupComparator SHARED_GROUP_COMPARATOR; + +LLGroupList::Params::Params() +: for_agent("for_agent", true) +{ +} LLGroupList::LLGroupList(const Params& p) : LLFlatListViewEx(p) + , mForAgent(p.for_agent) , mDirty(true) // to force initial update + , mShowIcons(false) + , mShowNone(true) { - // Listen for agent group changes. - gAgent.addListener(this, "new group"); - - mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons"); setCommitOnSelectionChange(true); // Set default sort order. - setComparator(&GROUP_COMPARATOR); + if (mForAgent) + { + setComparator(&GROUP_COMPARATOR); + } + else + { + // shared groups first + setComparator(&SHARED_GROUP_COMPARATOR); + } + + if (mForAgent) + { + enableForAgent(true); + } +} + +LLGroupList::~LLGroupList() +{ + if (mForAgent) gAgent.removeListener(this); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); +} + +void LLGroupList::enableForAgent(bool show_icons) +{ + mForAgent = true; + + mShowIcons = mForAgent && gSavedSettings.getBOOL("GroupListShowIcons") && show_icons; + + // Listen for agent group changes. + gAgent.addListener(this, "new group"); // Set up context menu. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -94,12 +153,6 @@ LLGroupList::LLGroupList(const Params& p) mContextMenuHandle = context_menu->getHandle(); } -LLGroupList::~LLGroupList() -{ - gAgent.removeListener(this); - if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); -} - // virtual void LLGroupList::draw() { @@ -114,12 +167,15 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); - LLToggleableMenu* context_menu = mContextMenuHandle.get(); - if (context_menu && size() > 0) - { - context_menu->buildDrawLabels(); - context_menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, context_menu, x, y); + if (mForAgent) + { + LLToggleableMenu* context_menu = mContextMenuHandle.get(); + if (context_menu && size() > 0) + { + context_menu->buildDrawLabels(); + context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, context_menu, x, y); + } } return handled; @@ -132,7 +188,7 @@ BOOL LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask) // Handle double click only for the selected item in the list, skip clicks on empty space. if (handled) { - if (mDoubleClickSignal) + if (mDoubleClickSignal && getItemsRect().pointInRect(x, y)) { (*mDoubleClickSignal)(this, x, y, mask); } @@ -164,34 +220,49 @@ static bool findInsensitive(std::string haystack, const std::string& needle_uppe void LLGroupList::refresh() { - const LLUUID& highlight_id = gAgent.getGroupID(); - S32 count = gAgent.mGroups.size(); - LLUUID id; - bool have_filter = !mNameFilter.empty(); - - clear(); - - for(S32 i = 0; i < count; ++i) - { - id = gAgent.mGroups.at(i).mID; - const LLGroupData& group_data = gAgent.mGroups.at(i); - if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) - continue; - addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM); - } - - // Sort the list. - sort(); - - // Add "none" to list at top if filter not set (what's the point of filtering "none"?). - // but only if some real groups exists. EXT-4838 - if (!have_filter && count > 0) - { - std::string loc_none = LLTrans::getString("GroupsNone"); - addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); - } - - selectItemByUUID(highlight_id); + if (mForAgent) + { + const LLUUID& highlight_id = gAgent.getGroupID(); + S32 count = gAgent.mGroups.size(); + LLUUID id; + bool have_filter = !mNameFilter.empty(); + + clear(); + + for(S32 i = 0; i < count; ++i) + { + id = gAgent.mGroups.at(i).mID; + const LLGroupData& group_data = gAgent.mGroups.at(i); + if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) + continue; + addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile); + } + + // Sort the list. + sort(); + + // Add "none" to list at top if filter not set (what's the point of filtering "none"?). + // but only if some real groups exists. EXT-4838 + if (!have_filter && count > 0 && mShowNone) + { + std::string loc_none = LLTrans::getString("GroupsNone"); + addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); + } + + selectItemByUUID(highlight_id); + } + else + { + clear(); + + for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) + { + addNewItem(it->second, it->first, LLUUID::null, ADD_BOTTOM); + } + + // Sort the list. + sort(); + } setDirty(false); onCommit(); @@ -212,13 +283,19 @@ void LLGroupList::toggleIcons() } } +void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list) +{ + mGroups = group_list; + setDirty(true); +} + ////////////////////////////////////////////////////////////////////////// // PRIVATE Section ////////////////////////////////////////////////////////////////////////// -void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos) +void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile) { - LLGroupListItem* item = new LLGroupListItem(); + LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons); item->setGroupID(id); item->setName(name, mNameFilter); @@ -227,7 +304,10 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL item->getChildView("info_btn")->setVisible( false); item->getChildView("profile_btn")->setVisible( false); item->setGroupIconVisible(mShowIcons); - + if (!mShowIcons) + { + item->setVisibleInProfile(visible_in_profile); + } addItem(item, id, pos); // setCommentVisible(false); @@ -243,6 +323,29 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& return true; } + if (event->desc() == "value_changed") + { + LLSD data = event->getValue(); + if (data.has("group_id") && data.has("visible")) + { + LLUUID group_id = data["group_id"].asUUID(); + bool visible = data["visible"].asBoolean(); + + std::vector<LLPanel*> items; + getItems(items); + for (std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) + { + LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(*it); + if (item && item->getGroupID() == group_id) + { + item->setVisibleInProfile(visible); + break; + } + } + } + return true; + } + return false; } @@ -294,21 +397,25 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) /* LLGroupListItem implementation */ /************************************************************************/ -LLGroupListItem::LLGroupListItem() +LLGroupListItem::LLGroupListItem(bool for_agent, bool show_icons) : LLPanel(), mGroupIcon(NULL), mGroupNameBox(NULL), mInfoBtn(NULL), -mGroupID(LLUUID::null) +mProfileBtn(NULL), +mVisibilityHideBtn(NULL), +mVisibilityShowBtn(NULL), +mGroupID(LLUUID::null), +mForAgent(for_agent) { - buildFromFile( "panel_group_list_item.xml"); - - // Remember group icon width including its padding from the name text box, - // so that we can hide and show the icon again later. - if (!sIconWidth) - { - sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft; - } + if (show_icons) + { + buildFromFile( "panel_group_list_item.xml"); + } + else + { + buildFromFile( "panel_group_list_item_short.xml"); + } } LLGroupListItem::~LLGroupListItem() @@ -325,7 +432,25 @@ BOOL LLGroupListItem::postBuild() mInfoBtn = getChild<LLButton>("info_btn"); mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this)); - childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this)); + mProfileBtn = getChild<LLButton>("profile_btn"); + mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); }); + + mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn"); + if (mVisibilityHideBtn) + { + mVisibilityHideBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(false); }); + } + mVisibilityShowBtn = findChild<LLButton>("visibility_show_btn"); + if (mVisibilityShowBtn) + { + mVisibilityShowBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(true); }); + } + + // Remember group icon width including its padding from the name text box, + // so that we can hide and show the icon again later. + // Also note that panel_group_list_item and panel_group_list_item_short + // have icons of different sizes so we need to figure it per file. + mIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft; return TRUE; } @@ -344,7 +469,16 @@ void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask) if (mGroupID.notNull()) // don't show the info button for the "none" group { mInfoBtn->setVisible(true); - getChildView("profile_btn")->setVisible( true); + mProfileBtn->setVisible(true); + if (mForAgent && mVisibilityHideBtn) + { + LLGroupData agent_gdatap; + if (gAgent.getGroupData(mGroupID, agent_gdatap)) + { + mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile); + mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile); + } + } } LLPanel::onMouseEnter(x, y, mask); @@ -354,7 +488,12 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask) { getChildView("hovered_icon")->setVisible( false); mInfoBtn->setVisible(false); - getChildView("profile_btn")->setVisible( false); + mProfileBtn->setVisible(false); + if (mVisibilityHideBtn) + { + mVisibilityHideBtn->setVisible(false); + mVisibilityShowBtn->setVisible(false); + } LLPanel::onMouseLeave(x, y, mask); } @@ -372,7 +511,17 @@ void LLGroupListItem::setGroupID(const LLUUID& group_id) mID = group_id; mGroupID = group_id; - setActive(group_id == gAgent.getGroupID()); + + if (mForAgent) + { + // Active group should be bold. + setBold(group_id == gAgent.getGroupID()); + } + else + { + // Groups shared with the agent should be bold + setBold(gAgent.isInGroup(group_id, true)); + } LLGroupMgr::getInstance()->addObserver(this); } @@ -393,24 +542,28 @@ void LLGroupListItem::setGroupIconVisible(bool visible) // Move the group name horizontally by icon size + its distance from the group name. LLRect name_rect = mGroupNameBox->getRect(); - name_rect.mLeft += visible ? sIconWidth : -sIconWidth; + name_rect.mLeft += visible ? mIconWidth : -mIconWidth; mGroupNameBox->setRect(name_rect); } +void LLGroupListItem::setVisibleInProfile(bool visible) +{ + mGroupNameBox->setColor(LLUIColorTable::instance().getColor((visible ? "GroupVisibleInProfile" : "GroupHiddenInProfile"), LLColor4::red).get()); +} + ////////////////////////////////////////////////////////////////////////// // Private Section ////////////////////////////////////////////////////////////////////////// -void LLGroupListItem::setActive(bool active) +void LLGroupListItem::setBold(bool bold) { // *BUG: setName() overrides the style params. - // Active group should be bold. LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc()); // *NOTE dzaporozhan // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font // is predefined as bold (SansSerifSmallBold, for example) - new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL); + new_desc.setStyle(bold ? LLFontGL::BOLD : LLFontGL::NORMAL); LLFontGL* new_font = LLFontGL::getFont(new_desc); mGroupNameStyle.font = new_font; @@ -430,11 +583,25 @@ void LLGroupListItem::onProfileBtnClick() LLGroupActions::show(mGroupID); } +void LLGroupListItem::onVisibilityBtnClick(bool new_visibility) +{ + LLGroupData agent_gdatap; + if (gAgent.getGroupData(mGroupID, agent_gdatap)) + { + gAgent.setUserGroupFlags(mGroupID, agent_gdatap.mAcceptNotices, new_visibility); + setVisibleInProfile(new_visibility); + mVisibilityHideBtn->setVisible(new_visibility); + mVisibilityShowBtn->setVisible(!new_visibility); + } +} + void LLGroupListItem::changed(LLGroupChange gc) { LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); - if(group_data) - setGroupIconID(group_data->mInsigniaID); + if ((gc == GC_ALL || gc == GC_PROPERTIES) && group_data) + { + setGroupIconID(group_data->mInsigniaID); + } } //EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 171b77fb00..5cbabb712f 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -50,12 +50,15 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener public: struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> { - Params(){}; + Optional<bool> for_agent; + Params(); }; LLGroupList(const Params& p); virtual ~LLGroupList(); + void enableForAgent(bool show_icons); + virtual void draw(); // from LLView /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView @@ -63,13 +66,16 @@ public: void setNameFilter(const std::string& filter); void toggleIcons(); bool getIconsVisible() const { return mShowIcons; } + void setIconsVisible(bool show_icons) { mShowIcons = show_icons; } + void setShowNone(bool show_none) { mShowNone = show_none; } + void setGroups(const std::map< std::string,LLUUID> group_list); LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); } private: void setDirty(bool val = true) { mDirty = val; } void refresh(); - void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM); + void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true); bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes bool onContextMenuItemClick(const LLSD& userdata); @@ -80,6 +86,11 @@ private: bool mShowIcons; bool mDirty; std::string mNameFilter; + + bool mForAgent; + bool mShowNone; + typedef std::map< std::string,LLUUID> group_map_t; + group_map_t mGroups; }; class LLButton; @@ -90,7 +101,7 @@ class LLGroupListItem : public LLPanel , public LLGroupMgrObserver { public: - LLGroupListItem(); + LLGroupListItem(bool for_agent, bool show_icons); ~LLGroupListItem(); /*virtual*/ BOOL postBuild(); /*virtual*/ void setValue(const LLSD& value); @@ -106,19 +117,26 @@ public: void setGroupIconVisible(bool visible); virtual void changed(LLGroupChange gc); + + void setVisibleInProfile(bool visible); private: - void setActive(bool active); + void setBold(bool bold); void onInfoBtnClick(); void onProfileBtnClick(); + void onVisibilityBtnClick(bool new_visibility); LLTextBox* mGroupNameBox; LLUUID mGroupID; LLGroupIconCtrl* mGroupIcon; - LLButton* mInfoBtn; + LLButton* mInfoBtn; + LLButton* mProfileBtn; + LLButton* mVisibilityHideBtn; + LLButton* mVisibilityShowBtn; std::string mGroupName; + bool mForAgent; LLStyle::Params mGroupNameStyle; - static S32 sIconWidth; // icon width + padding + S32 mIconWidth; }; #endif // LL_LLGROUPLIST_H diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 7f65153879..a9e5e55451 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -53,6 +53,7 @@ #include "llviewerregion.h" #include <boost/regex.hpp> #include "llcorehttputil.h" +#include "lluiusage.h" #if LL_MSVC @@ -1859,6 +1860,9 @@ void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id) //static void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id) { + + LLUIUsage::instance().logCommand("Group.Join"); + LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_JoinGroupRequest); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 7be35ac260..5952edfc44 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -330,7 +330,7 @@ void LLHUDText::updateVisibility() if (!mSourceObject) { - LL_WARNS() << "HUD text: mSourceObject is NULL, mOnHUDAttachment: " << mOnHUDAttachment << LL_ENDL; + // Beacons mVisible = TRUE; if (mOnHUDAttachment) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b7e0a6a794..4d6ebf9cbb 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -69,7 +69,7 @@ #include "message.h" #include "llviewerregion.h" #include "llcorehttputil.h" - +#include "lluiusage.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -532,7 +532,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mSessionInitialized(false), mCallBackEnabled(true), mTextIMPossible(true), - mOtherParticipantIsAvatar(true), mStartCallOnInitialize(false), mStartedAsIMCall(voice), mIsDNDsend(false), @@ -544,13 +543,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType) { mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id); - mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID); - - // check if it was AVALINE call - if (!mOtherParticipantIsAvatar) - { - mSessionType = AVALINE_SESSION; - } } else { @@ -651,9 +643,6 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(mSessionType) { - case AVALINE_SESSION: - // no text notifications - break; case P2P_SESSION: LLAvatarNameCache::get(mOtherParticipantID, &av_name); other_avatar_name = av_name.getUserName(); @@ -781,6 +770,23 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f message["index"] = (LLSD::Integer)mMsgs.size(); message["is_history"] = is_history; + LL_DEBUGS("UIUsage") << "addMessage " << " from " << from << " from_id " << from_id << " utf8_text " << utf8_text << " time " << time << " is_history " << is_history << " session mType " << mType << LL_ENDL; + if (from_id == gAgent.getID()) + { + if (mType == IM_SESSION_GROUP_START) + { + LLUIUsage::instance().logCommand("Chat.SendGroup"); + } + else if (mType == IM_NOTHING_SPECIAL) + { + LLUIUsage::instance().logCommand("Chat.SendIM"); + } + else + { + LLUIUsage::instance().logCommand("Chat.SendOther"); + } + } + mMsgs.push_front(message); if (mSpeakers && from_id.notNull()) @@ -913,11 +919,6 @@ bool LLIMModel::LLIMSession::isGroupChat() return IM_SESSION_GROUP_START == mType || (IM_SESSION_INVITE == mType && gAgent.isInGroup(mSessionID, TRUE)); } -bool LLIMModel::LLIMSession::isOtherParticipantAvaline() -{ - return !mOtherParticipantIsAvatar; -} - LLUUID LLIMModel::LLIMSession::generateOutgoingAdHocHash() const { LLUUID hash = LLUUID::null; @@ -1795,7 +1796,6 @@ LLIMMgr::onConfirmForceCloseError( LLCallDialogManager::LLCallDialogManager(): mPreviousSessionlName(""), -mPreviousSessionType(LLIMModel::LLIMSession::P2P_SESSION), mCurrentSessionlName(""), mSession(NULL), mOldState(LLVoiceChannel::STATE_READY) @@ -1826,12 +1826,6 @@ void LLCallDialogManager::onVoiceChannelChangedInt(const LLUUID &session_id) mCurrentSessionlName = ""; // Empty string results in "Nearby Voice Chat" after substitution return; } - - if (mSession) - { - // store previous session type to process Avaline calls in dialogs - mPreviousSessionType = mSession->mSessionType; - } mSession = session; @@ -1857,7 +1851,6 @@ void LLCallDialogManager::onVoiceChannelChangedInt(const LLUUID &session_id) mCallDialogPayload["session_name"] = mSession->mName; mCallDialogPayload["other_user_id"] = mSession->mOtherParticipantID; mCallDialogPayload["old_channel_name"] = mPreviousSessionlName; - mCallDialogPayload["old_session_type"] = mPreviousSessionType; mCallDialogPayload["state"] = LLVoiceChannel::STATE_CALL_STARTED; mCallDialogPayload["disconnected_channel_name"] = mSession->mName; mCallDialogPayload["session_type"] = mSession->mSessionType; @@ -1893,7 +1886,6 @@ void LLCallDialogManager::onVoiceChannelStateChangedInt(const LLVoiceChannel::ES mCallDialogPayload["session_name"] = mSession->mName; mCallDialogPayload["other_user_id"] = mSession->mOtherParticipantID; mCallDialogPayload["old_channel_name"] = mPreviousSessionlName; - mCallDialogPayload["old_session_type"] = mPreviousSessionType; mCallDialogPayload["state"] = new_state; mCallDialogPayload["disconnected_channel_name"] = mSession->mName; mCallDialogPayload["session_type"] = mSession->mSessionType; @@ -1910,8 +1902,7 @@ void LLCallDialogManager::onVoiceChannelStateChangedInt(const LLVoiceChannel::ES break; case LLVoiceChannel::STATE_HUNG_UP: - // this state is coming before session is changed, so, put it into payload map - mCallDialogPayload["old_session_type"] = mSession->mSessionType; + // this state is coming before session is changed break; case LLVoiceChannel::STATE_CONNECTED : @@ -2031,7 +2022,6 @@ void LLCallDialog::onOpen(const LLSD& key) void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id) { - // *NOTE: 12/28/2009: check avaline calls: LLVoiceClient::isParticipantAvatar returns false for them bool participant_is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); bool is_group = participant_is_avatar && gAgent.isInGroup(session_id, TRUE); @@ -2052,8 +2042,8 @@ void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id) } else { - avatar_icon->setValue("Avaline_Icon"); - avatar_icon->setToolTip(std::string("")); + LL_WARNS() << "Participant neither avatar nor group" << LL_ENDL; + group_icon->setValue(session_id); } } @@ -2097,13 +2087,7 @@ void LLOutgoingCallDialog::show(const LLSD& key) // tell the user which voice channel they are leaving if (!mPayload["old_channel_name"].asString().empty()) { - bool was_avaline_call = LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["old_session_type"].asInteger(); - std::string old_caller_name = mPayload["old_channel_name"].asString(); - if (was_avaline_call) - { - old_caller_name = LLTextUtil::formatPhoneNumber(old_caller_name); - } getChild<LLUICtrl>("leaving")->setTextArg("[CURRENT_CHAT]", old_caller_name); show_oldchannel = true; @@ -2116,10 +2100,6 @@ void LLOutgoingCallDialog::show(const LLSD& key) if (!mPayload["disconnected_channel_name"].asString().empty()) { std::string channel_name = mPayload["disconnected_channel_name"].asString(); - if (LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["session_type"].asInteger()) - { - channel_name = LLTextUtil::formatPhoneNumber(channel_name); - } getChild<LLUICtrl>("nearby")->setTextArg("[VOICE_CHANNEL_NAME]", channel_name); // skipping "You will now be reconnected to nearby" in notification when call is ended by disabling voice, @@ -2135,16 +2115,11 @@ void LLOutgoingCallDialog::show(const LLSD& key) std::string callee_name = mPayload["session_name"].asString(); LLUUID session_id = mPayload["session_id"].asUUID(); - bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); - if (callee_name == "anonymous") + if (callee_name == "anonymous") // obsolete? Likely was part of avaline support { callee_name = getString("anonymous"); } - else if (!is_avatar) - { - callee_name = LLTextUtil::formatPhoneNumber(callee_name); - } LLSD callee_id = mPayload["other_user_id"]; // Beautification: Since you know who you called, just show display name @@ -2344,18 +2319,11 @@ BOOL LLIncomingCallDialog::postBuild() call_type = getString(notify_box_type); } - // check to see if this is an Avaline call - bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); - if (caller_name == "anonymous") + if (caller_name == "anonymous") // obsolete? Likely was part of avaline support { caller_name = getString("anonymous"); setCallerName(caller_name, caller_name, call_type); } - else if (!is_avatar) - { - caller_name = LLTextUtil::formatPhoneNumber(caller_name); - setCallerName(caller_name, caller_name, call_type); - } else { // Get the full name information @@ -2375,7 +2343,7 @@ BOOL LLIncomingCallDialog::postBuild() if(notify_box_type != "VoiceInviteGroup" && notify_box_type != "VoiceInviteAdHoc") { - // starting notification's timer for P2P and AVALINE invitations + // starting notification's timer for P2P invitations mLifetimeTimer.start(); } else @@ -2384,7 +2352,7 @@ BOOL LLIncomingCallDialog::postBuild() } //it's not possible to connect to existing Ad-Hoc/Group chat through incoming ad-hoc call - //and no IM for avaline + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); getChildView("Start IM")->setVisible( is_avatar && notify_box_type != "VoiceInviteAdHoc" && notify_box_type != "VoiceInviteGroup"); setCanDrag(FALSE); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 79c831ebb6..fdf9806e2e 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -72,7 +72,6 @@ public: P2P_SESSION, GROUP_SESSION, ADHOC_SESSION, - AVALINE_SESSION, NONE_SESSION, } SType; @@ -92,12 +91,10 @@ public: bool isAdHoc(); bool isP2P(); bool isGroupChat(); - bool isOtherParticipantAvaline(); bool isP2PSessionType() const { return mSessionType == P2P_SESSION;} bool isAdHocSessionType() const { return mSessionType == ADHOC_SESSION;} bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;} - bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;} LLUUID generateOutgoingAdHocHash() const; @@ -136,7 +133,6 @@ public: bool mCallBackEnabled; bool mTextIMPossible; - bool mOtherParticipantIsAvatar; bool mStartCallOnInitialize; //if IM session is created for a voice call @@ -516,7 +512,6 @@ private: protected: std::string mPreviousSessionlName; - LLIMModel::LLIMSession::SType mPreviousSessionType; std::string mCurrentSessionlName; LLIMModel::LLIMSession* mSession; LLVoiceChannel::EState mOldState; diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp index 479e8f9abf..f382b5985f 100644 --- a/indra/newview/llinspect.cpp +++ b/indra/newview/llinspect.cpp @@ -147,3 +147,19 @@ bool LLInspect::childHasVisiblePopupMenu() } return false; } + +void LLInspect::repositionInspector(const LLSD& data) +{ + // Position the inspector relative to the mouse cursor + // Similar to how tooltips are positioned + // See LLToolTipMgr::createToolTip + if (data.has("pos")) + { + LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); + } + else + { + LLUI::getInstance()->positionViewNearMouse(this); + } + applyRectControl(); +} diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h index 1f6aafc7bd..6909aa3f16 100644 --- a/indra/newview/llinspect.h +++ b/indra/newview/llinspect.h @@ -49,6 +49,8 @@ public: /// Inspectors close themselves when they lose focus /*virtual*/ void onFocusLost(); + + void repositionInspector(const LLSD& data); protected: diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 10814ac076..b11c440015 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -45,7 +45,6 @@ #include "llfloater.h" #include "llfloaterreg.h" #include "lltextbox.h" -#include "lltooltip.h" // positionViewNearMouse() #include "lltrans.h" class LLFetchAvatarData; @@ -202,17 +201,7 @@ void LLInspectAvatar::onOpen(const LLSD& data) // Extract appropriate avatar id mAvatarID = data["avatar_id"]; - // Position the inspector relative to the mouse cursor - // Similar to how tooltips are positioned - // See LLToolTipMgr::createToolTip - if (data.has("pos")) - { - LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); - } - else - { - LLUI::getInstance()->positionViewNearMouse(this); - } + LLInspect::repositionInspector(data); // Generate link to avatar profile. LLTextBase* avatar_profile_link = getChild<LLTextBase>("avatar_profile_link"); @@ -348,7 +337,7 @@ void LLInspectAvatar::onClickMuteVolume() LLMuteList* mute_list = LLMuteList::getInstance(); bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - LLMute mute(mAvatarID, mAvatarName.getDisplayName(), LLMute::AGENT); + LLMute mute(mAvatarID, mAvatarName.getUserName(), LLMute::AGENT); if (!is_muted) { mute_list->add(mute, LLMute::flagVoiceChat); diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp index fa8a53c546..0a30ab9217 100644 --- a/indra/newview/llinspectgroup.cpp +++ b/indra/newview/llinspectgroup.cpp @@ -38,7 +38,6 @@ #include "llfloater.h" #include "llfloaterreg.h" #include "llresmgr.h" // getMonetaryString() -#include "lltooltip.h" // positionViewNearMouse() #include "lltrans.h" #include "lluictrl.h" #include "llgroupiconctrl.h" @@ -124,17 +123,7 @@ void LLInspectGroup::onOpen(const LLSD& data) setGroupID(data["group_id"]); - // Position the inspector relative to the mouse cursor - // Similar to how tooltips are positioned - // See LLToolTipMgr::createToolTip - if (data.has("pos")) - { - LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); - } - else - { - LLUI::getInstance()->positionViewNearMouse(this); - } + LLInspect::repositionInspector(data); // can't call from constructor as widgets are not built yet requestUpdate(); diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index cb7031971b..5329f10612 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -50,7 +50,6 @@ #include "lltextbox.h" // for description truncation #include "lltoggleablemenu.h" #include "lltrans.h" -#include "llui.h" // positionViewNearMouse() #include "lluictrl.h" class LLViewerObject; @@ -198,17 +197,8 @@ void LLInspectObject::onOpen(const LLSD& data) { mObjectFace = data["object_face"]; } - // Position the inspector relative to the mouse cursor - // Similar to how tooltips are positioned - // See LLToolTipMgr::createToolTip - if (data.has("pos")) - { - LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); - } - else - { - LLUI::getInstance()->positionViewNearMouse(this); - } + + LLInspect::repositionInspector(data); // Promote hovered object to a complete selection, which will also force // a request for selected object data off the network diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index 272c8acbd5..77320510a6 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -111,17 +111,7 @@ void LLInspectRemoteObject::onOpen(const LLSD& data) // update the inspector with the current object state update(); - // Position the inspector relative to the mouse cursor - // Similar to how tooltips are positioned - // See LLToolTipMgr::createToolTip - if (data.has("pos")) - { - LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); - } - else - { - LLUI::getInstance()->positionViewNearMouse(this); - } + LLInspect::repositionInspector(data); } void LLInspectRemoteObject::onClickMap() diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index d0034eff13..68801b0895 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -110,7 +110,7 @@ void LLInspectToast::onOpen(const LLSD& notification_id) panel_rect = panel->getRect(); reshape(panel_rect.getWidth(), panel_rect.getHeight()); - LLUI::getInstance()->positionViewNearMouse(this); + LLInspect::repositionInspector(notification_id); } // virtual diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a0de3a2af1..a0bc1035bf 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -792,6 +792,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } + if (isAgentInventory()) + { + items.push_back(std::string("New folder from selected")); + items.push_back(std::string("Subfolder Separator")); + std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs(); + uuid_vec_t ids; + std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); + if (!is_only_items_selected(ids) && !is_only_cats_selected(ids)) + { + disabled_items.push_back(std::string("New folder from selected")); + } + } + if (obj->getIsLinkType()) { items.push_back(std::string("Find Original")); @@ -1102,7 +1115,10 @@ void LLInvFVBridge::addMarketplaceContextMenuOptions(U32 flags, LLInventoryModel::cat_array_t categories; LLInventoryModel::item_array_t items; gInventory.collectDescendents(local_version_folder_id, categories, items, FALSE); - if (categories.size() >= gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + LLCachedControl<U32> max_depth(gSavedSettings, "InventoryOutboxMaxFolderDepth", 4); + LLCachedControl<U32> max_count(gSavedSettings, "InventoryOutboxMaxFolderCount", 20); + if (categories.size() >= max_count + || depth > (max_depth + 1)) { disabled_items.push_back(std::string("New Folder")); } @@ -3798,7 +3814,20 @@ void LLFolderBridge::perform_pasteFromClipboard() { if (item && can_move_to_landmarks(item)) { - dropToFavorites(item); + if (LLClipboard::instance().isCutMode()) + { + LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); + llassert(viitem); + if (viitem) + { + //changeItemParent() implicity calls dirtyFilter + changeItemParent(model, viitem, parent_id, FALSE); + } + } + else + { + dropToFavorites(item); + } } } else if (LLClipboard::instance().isCutMode()) @@ -4266,7 +4295,16 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items.push_back(std::string("Conference Chat Folder")); items.push_back(std::string("IM All Contacts In Folder")); } + + if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren()) + { + items.push_back(std::string("Ungroup folder items")); + } } + else + { + disabled_items.push_back(std::string("New folder from selected")); + } #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index d239b23e83..27edc8148e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1868,6 +1868,86 @@ void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id) } } +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLInventoryItem* inv_item = gInventory.getItem(*it); + if (inv_item) + { + change_item_parent(*it, new_cat_uuid); + } + else + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (inv_cat && !LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { + gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false); + } + } + } + + LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory"); + if (!floater_inventory) + { + LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; + return; + } + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); + if (sidepanel_inventory) + { + if (sidepanel_inventory->getActivePanel()) + { + sidepanel_inventory->getActivePanel()->setSelection(new_cat_uuid, TAKE_FOCUS_YES); + LLFolderViewItem* fv_folder = sidepanel_inventory->getActivePanel()->getItemByID(new_cat_uuid); + if (fv_folder) + { + fv_folder->setOpen(TRUE); + } + } + } +} + +bool is_only_cats_selected(const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (!inv_cat) + { + return false; + } + } + return true; +} + +bool is_only_items_selected(const uuid_vec_t& selected_uuids) +{ + for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) + { + LLViewerInventoryItem* inv_item = gInventory.getItem(*it); + if (!inv_item) + { + return false; + } + } + return true; +} + + +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name) +{ + LLInventoryObject* first_item = gInventory.getObject(*selected_uuids.begin()); + if (!first_item) + { + return; + } + + inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids); + gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); + +} + ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- @@ -2522,6 +2602,81 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile(); } + else if ("new_folder_from_selected" == action) + { + + LLInventoryObject* first_item = gInventory.getObject(*ids.begin()); + if (!first_item) + { + return; + } + const LLUUID& parent_uuid = first_item->getParentUUID(); + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLInventoryObject *item = gInventory.getObject(*it); + if (!item || item->getParentUUID() != parent_uuid) + { + LLNotificationsUtil::add("SameFolderRequired"); + return; + } + } + + LLSD args; + args["DESC"] = LLTrans::getString("New Folder"); + + LLNotificationsUtil::add("CreateSubfolder", args, LLSD(), + [ids](const LLSD& notification, const LLSD& response) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notification, response); + if (opt == 0) + { + std::string settings_name = response["message"].asString(); + + LLInventoryObject::correctInventoryName(settings_name); + if (settings_name.empty()) + { + settings_name = LLTrans::getString("New Folder"); + } + move_items_to_new_subfolder(ids, settings_name); + } + }); + } + else if ("ungroup_folder_items" == action) + { + if (selected_uuid_set.size() == 1) + { + LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin()); + if (!inv_cat || LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { + return; + } + const LLUUID &new_cat_uuid = inv_cat->getParentUUID(); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array); + LLInventoryModel::cat_array_t cats = *cat_array; + LLInventoryModel::item_array_t items = *item_array; + + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) + { + LLViewerInventoryCategory* cat = *cat_iter; + if (cat) + { + gInventory.changeCategoryParent(cat, new_cat_uuid, false); + } + } + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) + { + LLViewerInventoryItem* item = *item_iter; + if(item) + { + gInventory.changeItemParent(item, new_cat_uuid, false); + } + } + gInventory.removeCategory(inv_cat->getUUID()); + gInventory.notifyObservers(); + } + } else { std::set<LLFolderViewItem*>::iterator set_iter; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 8915bfa1e0..ba9f157e47 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -93,6 +93,10 @@ LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id); +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name); +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); +bool is_only_cats_selected(const uuid_vec_t& selected_uuids); +bool is_only_items_selected(const uuid_vec_t& selected_uuids); /** Miscellaneous global functions ** ** diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index 12bb609df8..de6a850b57 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -298,31 +298,41 @@ LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem applyXUILayout(icon_params, this); mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); - if (mIconCtrl) - { - addChild(mIconCtrl); - } - else + if (!mIconCtrl) { LLIconCtrl::Params icon_params; icon_params.name = "item_icon"; mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); } + if (mIconCtrl) + { + addChild(mIconCtrl); + } + else + { + LL_ERRS() << "Failed to create mIconCtrl" << LL_ENDL; + } + LLTextBox::Params text_params(params.item_name); applyXUILayout(text_params, this); mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params); - if (mTitleCtrl) + if (!mTitleCtrl) { - addChild(mTitleCtrl); - } - else - { - LLTextBox::Params text_aprams; + LLTextBox::Params text_params; text_params.name = "item_title"; mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params); } + + if (mTitleCtrl) + { + addChild(mTitleCtrl); + } + else + { + LL_ERRS() << "Failed to create mTitleCtrl" << LL_ENDL; + } } class WidgetVisibilityChanger diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 37500176ea..fab7ae8f1a 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -135,15 +135,7 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) ///---------------------------------------------------------------------------- /// Class LLInventoryValidationInfo ///---------------------------------------------------------------------------- -LLInventoryValidationInfo::LLInventoryValidationInfo(): - mFatalErrorCount(0), - mWarningCount(0), - mLoopCount(0), - mOrphanedCount(0), - mInitialized(false), - mFatalNoRootFolder(false), - mFatalNoLibraryRootFolder(false), - mFatalQADebugMode(false) +LLInventoryValidationInfo::LLInventoryValidationInfo() { } @@ -165,7 +157,6 @@ std::ostream& operator<<(std::ostream& os, const LLInventoryValidationInfo& v) void LLInventoryValidationInfo::asLLSD(LLSD& sd) const { sd["fatal_error_count"] = mFatalErrorCount; - sd["warning_count"] = mWarningCount; sd["loop_count"] = mLoopCount; sd["orphaned_count"] = mOrphanedCount; sd["initialized"] = mInitialized; @@ -173,6 +164,20 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const sd["fatal_no_root_folder"] = mFatalNoRootFolder; sd["fatal_no_library_root_folder"] = mFatalNoLibraryRootFolder; sd["fatal_qa_debug_mode"] = mFatalQADebugMode; + + sd["warning_count"] = mWarningCount; + if (mWarningCount>0) + { + sd["warnings"] = LLSD::emptyArray(); + for (auto const& it : mWarnings) + { + S32 val =LLSD::Integer(it.second); + if (val>0) + { + sd["warnings"][it.first] = val; + } + } + } if (mMissingRequiredSystemFolders.size()>0) { sd["missing_system_folders"] = LLSD::emptyArray(); @@ -344,13 +349,13 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL return NULL; } -LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const +LLInventoryModel::EAncestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const { LLInventoryObject *object = getObject(object_id); if (!object) { LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL; - return ANSCESTOR_MISSING; + return ANCESTOR_MISSING; } std::set<LLUUID> object_ids{ object_id }; // loop protection @@ -360,19 +365,19 @@ LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(co if (object_ids.find(parent_id) != object_ids.end()) { LL_WARNS(LOG_INV) << "Detected a loop on an object " << parent_id << " when searching for ancestor of " << object_id << LL_ENDL; - return ANSCESTOR_LOOP; + return ANCESTOR_LOOP; } object_ids.insert(parent_id); LLInventoryObject *parent_object = getObject(parent_id); if (!parent_object) { LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL; - return ANSCESTOR_MISSING; + return ANCESTOR_MISSING; } object = parent_object; } result = object->getUUID(); - return ANSCESTOR_OK; + return ANCESTOR_OK; } // Get the object by id. Returns NULL if not found. @@ -541,9 +546,18 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E LLViewerInventoryCategory* cat = getCategory(*it); changeCategoryParent(cat, main_id, TRUE); } - + // Purge the emptied folder - removeCategory(folder_id); + // Note that this might be a system folder, don't validate removability + LLViewerInventoryCategory* cat = getCategory(folder_id); + if (cat) + { + const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id.notNull()) + { + changeCategoryParent(cat, trash_id, TRUE); + } + } remove_inventory_category(folder_id, NULL); } } @@ -3132,7 +3146,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 gInventory.accountForUpdate(update); } - U32 changes = 0x0; if (account) { mask |= LLInventoryObserver::CREATE; @@ -3140,7 +3153,7 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 //as above, this loop never seems to loop more than once per call for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) { - changes |= gInventory.updateItem(*it, mask); + gInventory.updateItem(*it, mask); } gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); @@ -3899,9 +3912,9 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo; S32 fatal_errs = 0; - S32 warnings = 0; - S32 loops = 0; - S32 orphaned = 0; + S32 warning_count= 0; + S32 loop_count = 0; + S32 orphaned_count = 0; if (getRootFolderID().isNull()) { @@ -3922,7 +3935,9 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const // ParentChild should be one larger because of the special entry for null uuid. LL_INFOS("Inventory") << "unexpected sizes: cat map size " << mCategoryMap.size() << " parent/child " << mParentChildCategoryTree.size() << LL_ENDL; - warnings++; + + validation_info->mWarnings["category_map_size"]++; + warning_count++; } S32 cat_lock = 0; S32 item_lock = 0; @@ -3941,32 +3956,35 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (!cat) { LL_WARNS("Inventory") << "null cat" << LL_ENDL; - warnings++; + validation_info->mWarnings["null_cat"]++; + warning_count++; continue; } LLUUID topmost_ancestor_id; // Will leave as null uuid on failure - EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id); + EAncestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id); switch (res) { - case ANSCESTOR_MISSING: - orphaned++; + case ANCESTOR_MISSING: + orphaned_count++; break; - case ANSCESTOR_LOOP: - loops++; + case ANCESTOR_LOOP: + loop_count++; break; - case ANSCESTOR_OK: + case ANCESTOR_OK: break; default: LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL; - warnings++; + validation_info->mWarnings["unknown_ancestor_status"]++; + warning_count++; break; } if (cat_id != cat->getUUID()) { LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL; - warnings++; + validation_info->mWarnings["cat_id_index_mismatch"]++; + warning_count++; } if (cat->getParentUUID().isNull()) @@ -3976,7 +3994,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LL_WARNS("Inventory") << "cat " << cat_id << " has no parent, but is not root (" << getRootFolderID() << ") or library root (" << getLibraryRootFolderID() << ")" << LL_ENDL; - warnings++; + validation_info->mWarnings["null_parent"]++; + warning_count++; } } cat_array_t* cats; @@ -3985,7 +4004,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (!cats || !items) { LL_WARNS("Inventory") << "invalid direct descendents for " << cat_id << LL_ENDL; - warnings++; + validation_info->mWarnings["direct_descendents"]++; + warning_count++; continue; } if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) @@ -4003,7 +4023,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const << " cached " << cat->getDescendentCount() << " expected " << cats->size() << "+" << items->size() << "=" << cats->size() +items->size() << LL_ENDL; - warnings++; + validation_info->mWarnings["invalid_descendent_count"]++; + warning_count++; } } if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) @@ -4027,7 +4048,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (!item) { LL_WARNS("Inventory") << "null item at index " << i << " for cat " << cat_id << LL_ENDL; - warnings++; + validation_info->mWarnings["null_item_at_index"]++; + warning_count++; continue; } @@ -4038,7 +4060,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LL_WARNS("Inventory") << "wrong parent for " << item_id << " found " << item->getParentUUID() << " expected " << cat_id << LL_ENDL; - warnings++; + validation_info->mWarnings["wrong_parent_for_item"]++; + warning_count++; } @@ -4048,7 +4071,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "item " << item_id << " found as child of " << cat_id << " but not in top level mItemMap" << LL_ENDL; - warnings++; + validation_info->mWarnings["item_not_in_top_map"]++; + warning_count++; } else { @@ -4062,11 +4086,12 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const // Topmost ancestor should be root or library. LLUUID topmost_ancestor_id; - EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); - if (found != ANSCESTOR_OK) + EAncestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); + if (found != ANCESTOR_OK) { LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL; - warnings++; + validation_info->mWarnings["topmost_ancestor_not_found"]++; + warning_count++; } else { @@ -4077,7 +4102,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const << " got " << topmost_ancestor_id << " expected " << getRootFolderID() << " or " << getLibraryRootFolderID() << LL_ENDL; - warnings++; + validation_info->mWarnings["topmost_ancestor_not_recognized"]++; + warning_count++; } } } @@ -4093,7 +4119,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL; - orphaned++; + orphaned_count++; } else { @@ -4111,7 +4137,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL; - orphaned++; + orphaned_count++; } } } @@ -4120,7 +4146,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LLFolderType::EType folder_type = cat->getPreferredType(); bool cat_is_in_library = false; LLUUID topmost_id; - if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID()) + if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANCESTOR_OK && topmost_id == getLibraryRootFolderID()) { cat_is_in_library = true; } @@ -4153,14 +4179,15 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (item->getUUID() != item_id) { LL_WARNS("Inventory") << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL; - warnings++; + validation_info->mWarnings["item_id_mismatch"]++; + warning_count++; } const LLUUID& parent_id = item->getParentUUID(); if (parent_id.isNull()) { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL; - orphaned++; + orphaned_count++; } else { @@ -4171,7 +4198,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL; - orphaned++; + orphaned_count++; } else { @@ -4188,7 +4215,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL; - orphaned++; + orphaned_count++; } } @@ -4206,18 +4233,18 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType() << " missing backlink info at target_id " << target_id << LL_ENDL; - orphaned++; + orphaned_count++; } // Links should have referents. if (item->getActualType() == LLAssetType::AT_LINK && !target_item) { LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL; - orphaned++; + orphaned_count++; } else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) { LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL; - orphaned++; + orphaned_count++; } if (target_item && target_item->getIsLinkType()) { @@ -4289,13 +4316,15 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (is_automatic) { LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL; - fatal_errs++; validation_info->mMissingRequiredSystemFolders.insert(folder_type); + fatal_errs++; } else { // Can create, and will when needed. - warnings++; + // (Not sure this is really a warning, but worth logging) + validation_info->mWarnings["missing_system_folder_can_create"]++; + warning_count++; } } else if (count_under_root > 1) @@ -4306,6 +4335,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { // It is a fatal problem or can lead to fatal problems for COF, // outfits, trash and other non-automatic folders. + validation_info->mFatalSystemDuplicate++; fatal_errs++; } else @@ -4313,13 +4343,15 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const // For automatic folders it's not a fatal issue and shouldn't // break inventory or other functionality further // Exception: FT_SETTINGS is not automatic, but only deserves a warning. - warnings++; + validation_info->mWarnings["non_fatal_system_duplicate_under_root"]++; + warning_count++; } } if (count_elsewhere > 0) { LL_WARNS("Inventory") << "Found " << count_elsewhere << " extra folders of type " << ft << " outside of root" << LL_ENDL; - warnings++; + validation_info->mWarnings["non_fatal_system_duplicate_elsewhere"]++; + warning_count++; } } } @@ -4341,12 +4373,12 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const // FIXME need to fail login and tell user to retry, contact support if problem persists. bool valid = (fatal_errs == 0); - LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL; + LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warning_count << ", valid: " << valid << LL_ENDL; validation_info->mFatalErrorCount = fatal_errs; - validation_info->mWarningCount = warnings; - validation_info->mLoopCount = loops; - validation_info->mOrphanedCount = orphaned; + validation_info->mWarningCount = warning_count; + validation_info->mLoopCount = loop_count; + validation_info->mOrphanedCount = orphaned_count; return validation_info; } @@ -4551,12 +4583,10 @@ void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore: } // as above, this loop never seems to loop more than once per call - U32 changes(0U); for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) { - changes |= gInventory.updateItem(*it); + gInventory.updateItem(*it); } - // *HUH: Have computed 'changes', nothing uses it. gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index eeec89bfb0..c4133ff9bb 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -65,15 +65,19 @@ public: void toOstream(std::ostream& os) const; void asLLSD(LLSD& sd) const; + bool mInitialized{false}; + S32 mWarningCount{0}; + std::map<std::string,U32> mWarnings; + + S32 mLoopCount{0}; // Presence of folders whose ancestors loop onto themselves + S32 mOrphanedCount{0}; // Missing or orphaned items, links and folders + + S32 mFatalErrorCount{0}; + bool mFatalNoRootFolder{false}; + S32 mFatalSystemDuplicate{0}; + bool mFatalNoLibraryRootFolder{false}; + bool mFatalQADebugMode{false}; - S32 mFatalErrorCount; - S32 mWarningCount; - S32 mLoopCount; // Presence of folders whose ansestors loop onto themselves - S32 mOrphanedCount; // Missing or orphaned items, links and folders - bool mInitialized; - bool mFatalNoRootFolder; - bool mFatalNoLibraryRootFolder; - bool mFatalQADebugMode; std::set<LLFolderType::EType> mMissingRequiredSystemFolders; std::set<LLFolderType::EType> mDuplicateRequiredSystemFolders; }; @@ -286,13 +290,13 @@ public: // Check if one object has a parent chain up to the category specified by UUID. BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const; - enum EAnscestorResult{ - ANSCESTOR_OK = 0, - ANSCESTOR_MISSING = 1, - ANSCESTOR_LOOP = 2, + enum EAncestorResult{ + ANCESTOR_OK = 0, + ANCESTOR_MISSING = 1, + ANCESTOR_LOOP = 2, }; // Follow parent chain to the top. - EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const; + EAncestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const; //-------------------------------------------------------------------- // Find diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp index 1364067949..ce4ec668f1 100644 --- a/indra/newview/lllegacyatmospherics.cpp +++ b/indra/newview/lllegacyatmospherics.cpp @@ -386,7 +386,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) return; } - const BOOL hide_clip_plane = TRUE; LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f); const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f; @@ -472,33 +471,17 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) render_fog_color = sky_fog_color; - F32 fog_density = 0.f; fog_distance = mFogRatio * distance; if (camera_height > water_height) { LLColor4 fog(render_fog_color); mGLFogCol = fog; - - if (hide_clip_plane) - { - // For now, set the density to extend to the cull distance. - const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f))) - fog_density = f_log/fog_distance; - } - else - { - const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f)) - fog_density = (f_log)/fog_distance; - } } else { LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); F32 depth = water_height - camera_height; - - // get the water param manager variables - float water_fog_density = pwater->getModifiedWaterFogDensity(depth <= 0.0f); LLColor4 water_fog_color(pwater->getWaterFogColor()); @@ -512,9 +495,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) // set the gl fog color mGLFogCol = fogCol; - - // set the density based on what the shaders use - fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale"); } mFogColor = sky_fog_color; diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 5a17332fde..de8db69e19 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -919,6 +919,36 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr() mBitmapList.clear(); } +LLUUID LLLocalBitmapMgr::addUnit(const std::string &filename) +{ + if (!checkTextureDimensions(filename)) + { + return LLUUID::null; + } + + LLLocalBitmap* unit = new LLLocalBitmap(filename); + + if (unit->getValid()) + { + mBitmapList.push_back(unit); + return unit->getTrackingID(); + } + else + { + LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" + << "Filename: " << filename << LL_ENDL; + + LLSD notif_args; + notif_args["FNAME"] = filename; + LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); + + delete unit; + unit = NULL; + } + + return LLUUID::null; +} + bool LLLocalBitmapMgr::addUnit() { bool add_successful = false; @@ -931,32 +961,10 @@ bool LLLocalBitmapMgr::addUnit() std::string filename = picker.getFirstFile(); while(!filename.empty()) { - if(!checkTextureDimensions(filename)) - { - filename = picker.getNextFile(); - continue; - } - - LLLocalBitmap* unit = new LLLocalBitmap(filename); - - if (unit->getValid()) - { - mBitmapList.push_back(unit); - add_successful = true; - } - else - { - LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" - << "Filename: " << filename << LL_ENDL; - - LLSD notif_args; - notif_args["FNAME"] = filename; - LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); - - delete unit; - unit = NULL; - } - + if (addUnit(filename).notNull()) + { + add_successful = true; + } filename = picker.getNextFile(); } diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index d5ee7efdc6..02b8834c16 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -116,13 +116,14 @@ class LLLocalBitmapMgr : public LLSingleton<LLLocalBitmapMgr> ~LLLocalBitmapMgr(); public: bool addUnit(); + LLUUID addUnit(const std::string &filename); void delUnit(LLUUID tracking_id); bool checkTextureDimensions(std::string filename); LLUUID getWorldID(LLUUID tracking_id); bool isLocal(LLUUID world_id); std::string getFilename(LLUUID tracking_id); - + void feedScrollList(LLScrollListCtrl* ctrl); void doUpdates(); void setNeedsRebake(); diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 79dbe17982..af2a9f6afd 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -109,6 +109,8 @@ public: LLLineEditor* getTextEntry() const { return mTextEntry; } void handleLoginComplete(); + bool isNavMeshDirty() { return mIsNavMeshDirty; } + private: enum EParcelIcon diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 82ecfbd4dc..dd8c9b2dde 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -451,26 +451,8 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) LLSD args(llsd::map( "MESSAGE", LLTrans::getString(response["message_id"]) )); LLSD payload; - LLNotificationsUtil::add("PromptMFAToken", args, payload, [=](LLSD const & notif, LLSD const & response) { - bool continue_clicked = response["continue"].asBoolean(); - std::string token = response["token"].asString(); - LL_DEBUGS("LLLogin") << "PromptMFAToken: response: " << response << " continue_clicked" << continue_clicked << LL_ENDL; - - // strip out whitespace - SL-17034/BUG-231938 - token = boost::regex_replace(token, boost::regex("\\s"), ""); - - if (continue_clicked && !token.empty()) - { - LL_INFOS("LLLogin") << "PromptMFAToken: token submitted" << LL_ENDL; - - // Set the request data to true and retry login. - mRequestData["params"]["token"] = token; - reconnect(); - } else { - LL_INFOS("LLLogin") << "PromptMFAToken: no token, attemptComplete" << LL_ENDL; - attemptComplete(); - } - }); + LLNotificationsUtil::add("PromptMFAToken", args, payload, + boost::bind(&LLLoginInstance::handleMFAChallenge, this, _1, _2)); } else if( reason_response == "key" || reason_response == "presence" @@ -547,23 +529,59 @@ void LLLoginInstance::handleIndeterminate(const LLSD& event) bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { - if(accepted) - { - LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: accepted" << LL_ENDL; + if(accepted) + { + LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: accepted " << LL_ENDL; - // Set the request data to true and retry login. - mRequestData["params"][key] = true; - reconnect(); - } - else - { - LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: attemptComplete" << LL_ENDL; + // Set the request data to true and retry login. + mRequestData["params"][key] = true; - attemptComplete(); - } + if (!mRequestData["params"]["token"].asString().empty()) + { + // SL-18511 this TOS failure happened while we are in the middle of an MFA challenge/response. + // the previously entered token is very likely expired, so prompt again + LLSD args(llsd::map( "MESSAGE", LLTrans::getString("LoginFailedAuthenticationMFARequired") )); + LLSD payload; + LLNotificationsUtil::add("PromptMFAToken", args, payload, + boost::bind(&LLLoginInstance::handleMFAChallenge, this, _1, _2)); + } + else + { + reconnect(); + } + } + else + { + LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: attemptComplete" << LL_ENDL; + + attemptComplete(); + } + + LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); + return true; +} - LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); - return true; +bool LLLoginInstance::handleMFAChallenge(LLSD const & notif, LLSD const & response) +{ + bool continue_clicked = response["continue"].asBoolean(); + std::string token = response["token"].asString(); + LL_DEBUGS("LLLogin") << "PromptMFAToken: response: " << response << " continue_clicked" << continue_clicked << LL_ENDL; + + // strip out whitespace - SL-17034/BUG-231938 + token = boost::regex_replace(token, boost::regex("\\s"), ""); + + if (continue_clicked && !token.empty()) + { + LL_INFOS("LLLogin") << "PromptMFAToken: token submitted" << LL_ENDL; + + // Set the request data to true and retry login. + mRequestData["params"]["token"] = token; + reconnect(); + } else { + LL_INFOS("LLLogin") << "PromptMFAToken: no token, attemptComplete" << LL_ENDL; + attemptComplete(); + } + return true; } std::string construct_start_string() diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index b759b43474..ee3ef0e4b1 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -84,6 +84,7 @@ private: void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response); bool handleTOSResponse(bool v, const std::string& key); + bool handleMFAChallenge(LLSD const & notif, LLSD const & response); void attemptComplete() { mAttemptComplete = true; } // In the future an event? diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 044c76ce2c..dd4ae4d201 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -758,7 +758,14 @@ void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& if (mMarketPlaceStatus != MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) { // If already initialized, just confirm the status so the callback gets called - setSLMStatus(mMarketPlaceStatus); + if (mMarketPlaceFailureReason.empty()) + { + setSLMStatus(mMarketPlaceStatus); + } + else + { + setSLMConnectionFailure(mMarketPlaceFailureReason); + } } else { @@ -799,28 +806,27 @@ void LLMarketplaceData::getMerchantStatusCoro() if (httpCode == HTTP_NOT_FOUND) { log_SLM_infos("Get /merchant", httpCode, std::string("User is not a merchant")); - setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT); } else if (httpCode == HTTP_SERVICE_UNAVAILABLE) { log_SLM_infos("Get /merchant", httpCode, std::string("Merchant is not migrated")); - setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT); + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT); } - else if (httpCode == HTTP_INTERNAL_ERROR) + else { - // 499 includes timeout and ssl error - marketplace is down or having issues, we do not show it in this request according to MAINT-5938 LL_WARNS("SLM") << "SLM Merchant Request failed with status: " << httpCode << ", reason : " << status.toString() << ", code : " << result["error_code"].asString() << ", description : " << result["error_description"].asString() << LL_ENDL; - LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); - } - else - { - std::string err_code = result["error_code"].asString(); - //std::string err_description = result["error_description"].asString(); - log_SLM_warning("Get /merchant", httpCode, status.toString(), err_code, result["error_description"]); - setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + std::string reason = status.toString(); + if (reason.empty()) + { + reason = result["error_code"].asString(); + } + // Since user might not even have a marketplace, there is no reason to report the error + // to the user, instead write it down into listings' floater + LLMarketplaceData::instance().setSLMConnectionFailure(reason); } return; } @@ -1298,6 +1304,17 @@ std::string LLMarketplaceData::getSLMConnectURL(const std::string& route) void LLMarketplaceData::setSLMStatus(U32 status) { mMarketPlaceStatus = status; + mMarketPlaceFailureReason.clear(); + if (mStatusUpdatedSignal) + { + (*mStatusUpdatedSignal)(); + } +} + +void LLMarketplaceData::setSLMConnectionFailure(const std::string& reason) +{ + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; + mMarketPlaceFailureReason = reason; if (mStatusUpdatedSignal) { (*mStatusUpdatedSignal)(); diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index fee9225f77..088507d850 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -198,7 +198,9 @@ public: typedef boost::signals2::signal<void ()> status_updated_signal_t; void initializeSLM(const status_updated_signal_t::slot_type& cb); U32 getSLMStatus() const { return mMarketPlaceStatus; } + std::string getSLMConnectionfailureReason() { return mMarketPlaceFailureReason; } void setSLMStatus(U32 status); + void setSLMConnectionFailure(const std::string& reason); void getSLMListings(); bool isEmpty() { return (mMarketplaceItems.size() == 0); } void setDataFetchedSignal(const status_updated_signal_t::slot_type& cb); @@ -272,6 +274,7 @@ private: // Handling Marketplace connection and inventory connection U32 mMarketPlaceStatus; + std::string mMarketPlaceFailureReason; status_updated_signal_t* mStatusUpdatedSignal; LLInventoryObserver* mInventoryObserver; bool mDirtyCount; // If true, stock count value need to be updated at the next check diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index bc45eb6d3a..9d0f62a30d 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -154,8 +154,7 @@ void mark_dead_and_remove_if(T &c, const PredicateMatchRequest &matchPred) if (matchPred(*it)) { (*it)->markDead(); - // *TDOO: When C++11 is in change the following line to: it = c.erase(it); - c.erase(it++); + it = c.erase(it); } else { diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d28e929b48..a15a61429b 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -383,6 +383,9 @@ U32 LLMeshRepository::sLODPending = 0; U32 LLMeshRepository::sCacheBytesRead = 0; U32 LLMeshRepository::sCacheBytesWritten = 0; +U32 LLMeshRepository::sCacheBytesHeaders = 0; +U32 LLMeshRepository::sCacheBytesSkins = 0; +U32 LLMeshRepository::sCacheBytesDecomps = 0; U32 LLMeshRepository::sCacheReads = 0; U32 LLMeshRepository::sCacheWrites = 0; U32 LLMeshRepository::sMaxLockHoldoffs = 0; @@ -1877,6 +1880,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes LLMutexLock lock(mHeaderMutex); mMeshHeaderSize[mesh_id] = header_size; mMeshHeader[mesh_id] = header; + LLMeshRepository::sCacheBytesHeaders += header_size; } @@ -2054,17 +2058,6 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_ if (volume->unpackVolumeFaces(stream, data_size)) { - //load volume faces into decomposition buffer - S32 vertex_count = 0; - S32 index_count = 0; - - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - vertex_count += face.mNumVertices; - index_count += face.mNumIndices; - } - d->mPhysicsShapeMesh.clear(); std::vector<LLVector3>& pos = d->mPhysicsShapeMesh.mPositions; @@ -3019,27 +3012,6 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod) return -1; } -void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) -{ - mThread->mMeshHeader[data.mUUID] = header; - - // we cache the mesh for default parameters - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - volume_params.setSculptID(data.mUUID, LL_SCULPT_TYPE_MESH); - - for (U32 i = 0; i < 4; i++) - { - if (data.mModel[i].notNull()) - { - LLPointer<LLVolume> volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i)); - volume->copyVolumeFaces(data.mModel[i]); - volume->setMeshAssetLoaded(TRUE); - } - } - -} - // Handle failed or successful requests for mesh assets. // // Support for 200 responses was added for several reasons. One, @@ -3957,6 +3929,8 @@ void LLMeshRepository::notifyLoadedMeshes() void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) { mSkinMap[info.mMeshID] = info; + // Alternative: We can get skin size from header + sCacheBytesSkins += info.sizeBytes(); skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); if (iter != mLoadingSkins.end()) @@ -3980,10 +3954,14 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom { //just insert decomp into map mDecompositionMap[decomp->mMeshID] = decomp; mLoadingDecompositions.erase(decomp->mMeshID); + sCacheBytesDecomps += decomp->sizeBytes(); } else { //merge decomp with existing entry + sCacheBytesDecomps -= iter->second->sizeBytes(); iter->second->merge(decomp); + sCacheBytesDecomps += iter->second->sizeBytes(); + mLoadingDecompositions.erase(decomp->mMeshID); delete decomp; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 1989350303..f61da3e571 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -554,6 +554,9 @@ public: static U32 sLODProcessing; static U32 sCacheBytesRead; static U32 sCacheBytesWritten; + static U32 sCacheBytesHeaders; + static U32 sCacheBytesSkins; + static U32 sCacheBytesDecomps; static U32 sCacheReads; static U32 sCacheWrites; static U32 sMaxLockHoldoffs; // Maximum sequential locking failures @@ -643,8 +646,6 @@ public: std::queue<LLUUID> mPendingPhysicsShapeRequests; U32 mMeshThreadCount; - - void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header); LLMeshRepoThread* mThread; std::vector<LLMeshUploadThread*> mUploads; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 859d987fc3..642df7f931 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -86,6 +86,7 @@ static const LLColor4 PREVIEW_DEG_FILL_COL(1.f, 0.f, 0.f, 0.5f); static const F32 PREVIEW_DEG_EDGE_WIDTH(3.f); static const F32 PREVIEW_DEG_POINT_SIZE(8.f); static const F32 PREVIEW_ZOOM_LIMIT(10.f); +static const std::string DEFAULT_PHYSICS_MESH_NAME = "default_physics_shape"; const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f; @@ -432,6 +433,20 @@ void LLModelPreview::rebuildUploadData() LLFloaterModelPreview::addStringToLog(out, false); } } + if (mWarnOfUnmatchedPhyicsMeshes && !lod_model && (i == LLModel::LOD_PHYSICS)) + { + // Despite the various strategies above, if we don't now have a physics model, we're going to end up with decomposition. + // That's ok, but might not what they wanted. Use default_physics_shape if found. + std::ostringstream out; + out << "No physics model specified for " << instance.mLabel; + if (mDefaultPhysicsShapeP) + { + out << " - using: " << DEFAULT_PHYSICS_MESH_NAME; + lod_model = mDefaultPhysicsShapeP; + } + LL_WARNS() << out.str() << LL_ENDL; + LLFloaterModelPreview::addStringToLog(out, !mDefaultPhysicsShapeP); // Flash log tab if no default. + } if (lod_model) { @@ -816,8 +831,10 @@ void LLModelPreview::clearIncompatible(S32 lod) // at this point we don't care about sub-models, // different amount of sub-models means face count mismatch, not incompatibility U32 lod_size = countRootModels(mModel[lod]); + bool replaced_base_model = (lod == LLModel::LOD_HIGH); for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) - { //clear out any entries that aren't compatible with this model + { + // Clear out any entries that aren't compatible with this model if (i != lod) { if (countRootModels(mModel[i]) != lod_size) @@ -831,9 +848,47 @@ void LLModelPreview::clearIncompatible(S32 lod) mBaseModel = mModel[lod]; mBaseScene = mScene[lod]; mVertexBuffer[5].clear(); + replaced_base_model = true; + } + } + } + } + + if (replaced_base_model && !mGenLOD) + { + // In case base was replaced, we might need to restart generation + + // Check if already started + bool subscribe_for_generation = mLodsQuery.empty(); + + // Remove previously scheduled work + mLodsQuery.clear(); + + LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; + if (!fmp) return; + + // Schedule new work + for (S32 i = LLModel::LOD_HIGH; i >= 0; --i) + { + if (mModel[i].empty()) + { + // Base model was replaced, regenerate this lod if applicable + LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[i]); + if (!lod_combo) return; + + S32 lod_mode = lod_combo->getCurrentIndex(); + if (lod_mode != LOD_FROM_FILE) + { + mLodsQuery.push_back(i); } } } + + // Subscribe if we have pending work and not subscribed yet + if (!mLodsQuery.empty() && subscribe_for_generation) + { + doOnIdleRepeating(lodQueryCallback); + } } } @@ -994,6 +1049,13 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) } else { + if (loaded_lod == LLModel::LOD_PHYSICS) + { // Explicitly loading physics. See if there is a default mesh. + LLMatrix4 ignored_transform; // Each mesh that uses this will supply their own. + mDefaultPhysicsShapeP = nullptr; + FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), mDefaultPhysicsShapeP, ignored_transform); + mWarnOfUnmatchedPhyicsMeshes = true; + } BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); if (!legacyMatching) { @@ -1064,7 +1126,6 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) LL_WARNS() << out.str() << LL_ENDL; LLFloaterModelPreview::addStringToLog(out, false); } - mModel[loaded_lod][idx]->mLabel = name; } } @@ -1221,8 +1282,9 @@ void LLModelPreview::restoreNormals() // Runs per object, but likely it is a better way to run per model+submodels // returns a ratio of base model indices to resulting indices // returns -1 in case of failure -F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode) { + // I. Weld faces together // Figure out buffer size S32 size_indices = 0; S32 size_vertices = 0; @@ -1257,20 +1319,21 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe { const LLVolumeFace &face = base_model->getVolumeFace(face_idx); - // vertices + // Vertices S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a); LLVector4a::memcpyNonAliased16((F32*)(combined_positions + combined_positions_shift), (F32*)face.mPositions, copy_bytes); - // normals + // Normals LLVector4a::memcpyNonAliased16((F32*)(combined_normals + combined_positions_shift), (F32*)face.mNormals, copy_bytes); - // tex coords + // Tex coords copy_bytes = face.mNumVertices * sizeof(LLVector2); memcpy((void*)(combined_tex_coords + combined_positions_shift), (void*)face.mTexCoords, copy_bytes); combined_positions_shift += face.mNumVertices; - // indices, sadly can't do dumb memcpy for indices, need to adjust each value + // Indices + // Sadly can't do dumb memcpy for indices, need to adjust each value for (S32 i = 0; i < face.mNumIndices; ++i) { U16 idx = face.mIndices[i]; @@ -1281,10 +1344,42 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe indices_idx_shift += face.mNumVertices; } - // Now that we have buffers, optimize + // II. Generate a shadow buffer if nessesary. + // Welds together vertices if possible + + U32* shadow_indices = NULL; + // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 + // won't do anything new, model was remaped on a per face basis. + // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + // since 'simplifySloppy' ignores all topology, including normals and uvs. + // Note: simplifySloppy can affect UVs significantly. + if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) + { + // strip normals, reflections should restore relatively correctly + shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, combined_tex_coords, size_vertices); + } + if (simplification_mode == MESH_OPTIMIZER_NO_UVS) + { + // strip uvs, can heavily affect textures + shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); + LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, NULL, size_vertices); + } + + U32* source_indices = NULL; + if (shadow_indices) + { + source_indices = shadow_indices; + } + else + { + source_indices = combined_indices; + } + + // III. Simplify S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% - S32 new_indices = 0; + S32 size_new_indices = 0; if (indices_decimator > 0) { @@ -1294,38 +1389,43 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe { target_indices = 3; } - new_indices = LLMeshOptimizer::simplifyU32( + + size_new_indices = LLMeshOptimizer::simplifyU32( output_indices, - combined_indices, + source_indices, size_indices, combined_positions, size_vertices, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], target_indices, error_threshold, - sloppy, + simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY, &result_error); - if (result_error < 0) { LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << LL_ENDL; } - if (new_indices < 3) + // free unused buffers + ll_aligned_free_32(combined_indices); + ll_aligned_free_32(shadow_indices); + combined_indices = NULL; + shadow_indices = NULL; + + if (size_new_indices < 3) { // Model should have at least one visible triangle ll_aligned_free<64>(combined_positions); ll_aligned_free_32(output_indices); - ll_aligned_free_32(combined_indices); return -1; } - // repack back into individual faces + // IV. Repack back into individual faces LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size); LLVector4a* buffer_normals = buffer_positions + size_vertices; @@ -1356,7 +1456,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } // Copy relevant indices and vertices - for (S32 i = 0; i < new_indices; ++i) + for (S32 i = 0; i < size_new_indices; ++i) { U32 idx = output_indices[i]; @@ -1379,19 +1479,19 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe LL_WARNS() << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for" << " model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << " error treshold: " << error_threshold << LL_ENDL; // U16 vertices overflow shouldn't happen, but just in case - new_indices = 0; + size_new_indices = 0; valid_faces = 0; for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx) { - genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false); + genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, simplification_mode); const LLVolumeFace &face = target_model->getVolumeFace(face_idx); - new_indices += face.mNumIndices; + size_new_indices += face.mNumIndices; if (face.mNumIndices >= 3) { valid_faces++; @@ -1399,7 +1499,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe } if (valid_faces) { - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } else { @@ -1469,18 +1569,17 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe ll_aligned_free<64>(buffer_positions); ll_aligned_free_32(output_indices); ll_aligned_free_16(buffer_indices); - ll_aligned_free_32(combined_indices); - if (new_indices < 3 || valid_faces == 0) + if (size_new_indices < 3 || valid_faces == 0) { // Model should have at least one visible triangle return -1; } - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } -F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode) { const LLVolumeFace &face = base_model->getVolumeFace(face_idx); S32 size_indices = face.mNumIndices; @@ -1488,14 +1587,40 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target { return -1; } - // todo: do not allocate per each face, add one large buffer somewhere - // faces have limited amount of indices + S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF; - U16* output = (U16*)ll_aligned_malloc_16(size); + U16* output_indices = (U16*)ll_aligned_malloc_16(size); + + U16* shadow_indices = NULL; + // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 + // won't do anything new, model was remaped on a per face basis. + // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + // since 'simplifySloppy' ignores all topology, including normals and uvs. + if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) + { + U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); + LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, face.mTexCoords, face.mNumVertices); + } + if (simplification_mode == MESH_OPTIMIZER_NO_UVS) + { + U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); + LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, NULL, face.mNumVertices); + } + // Don't run ShadowIndexBuffer for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + + U16* source_indices = NULL; + if (shadow_indices) + { + source_indices = shadow_indices; + } + else + { + source_indices = face.mIndices; + } S32 target_indices = 0; F32 result_error = 0; // how far from original the model is, 1 == 100% - S32 new_indices = 0; + S32 size_new_indices = 0; if (indices_decimator > 0) { @@ -1505,25 +1630,25 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target { target_indices = 3; } - new_indices = LLMeshOptimizer::simplify( - output, - face.mIndices, + + size_new_indices = LLMeshOptimizer::simplify( + output_indices, + source_indices, size_indices, face.mPositions, face.mNumVertices, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], target_indices, error_threshold, - sloppy, + simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY, &result_error); - if (result_error < 0) { LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx << " of model " << target_model->mLabel << " target Indices: " << target_indices - << " new Indices: " << new_indices + << " new Indices: " << size_new_indices << " original count: " << size_indices << " error treshold: " << error_threshold << LL_ENDL; @@ -1534,10 +1659,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target // Copy old values new_face = face; - - if (new_indices < 3) + if (size_new_indices < 3) { - if (!sloppy) + if (simplification_mode != MESH_OPTIMIZER_NO_TOPOLOGY) { // meshopt_optimizeSloppy() can optimize triangles away even if target_indices is > 2, // but optimize() isn't supposed to @@ -1561,23 +1685,24 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target else { // Assign new values - new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output - S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF; - LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output, idx_size); + new_face.resizeIndices(size_new_indices); // will wipe out mIndices, so new_face can't substitute output + S32 idx_size = (size_new_indices * sizeof(U16) + 0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output_indices, idx_size); - // clear unused values + // Clear unused values new_face.optimize(); } - ll_aligned_free_16(output); + ll_aligned_free_16(output_indices); + ll_aligned_free_16(shadow_indices); - if (new_indices < 3) + if (size_new_indices < 3) { // At least one triangle is needed return -1; } - return (F32)size_indices / (F32)new_indices; + return (F32)size_indices / (F32)size_new_indices; } void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation, bool enforce_tri_limit) @@ -1711,16 +1836,19 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Ideally this should run not per model, // but combine all submodels with origin model as well - if (model_meshopt_mode == MESH_OPTIMIZER_COMBINE) + if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE) { - // Run meshoptimizer for each model/object, up to 8 faces in one model. - - // Ideally this should run not per model, - // but combine all submodels with origin model as well - F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); - if (res < 0) + // Run meshoptimizer for each face + for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) { - target_model->copyVolumeFaces(base); + F32 res = genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); + if (res < 0) + { + // Mesh optimizer failed and returned an invalid model + const LLVolumeFace &face = base->getVolumeFace(face_idx); + LLVolumeFace &new_face = target_model->getVolumeFace(face_idx); + new_face = face; + } } } @@ -1729,19 +1857,29 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Run meshoptimizer for each face for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) { - if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0) + if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY) < 0) { // Sloppy failed and returned an invalid model - genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); + genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); } } } if (model_meshopt_mode == MESH_OPTIMIZER_AUTO) { - // Switches between 'combine' method and 'sloppy' based on combine's result. - F32 allowed_ratio_drift = 2.f; - F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + // Remove progressively more data if we can't reach the target. + F32 allowed_ratio_drift = 1.8f; + F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); + + if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) + { + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_NORMALS); + } + + if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) + { + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS); + } if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) { @@ -1749,10 +1887,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // Sloppy variant can fail entirely and has issues with precision, // so code needs to do multiple attempts with different decimators. // Todo: this is a bit of a mess, needs to be refined and improved + F32 last_working_decimator = 0.f; F32 last_working_ratio = F32_MAX; - F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); if (sloppy_ratio > 0) { @@ -1775,13 +1914,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // side due to overal lack of precision, and we don't need an ideal result, which // likely does not exist, just a better one, so a partial correction is enough. F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2; - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); } if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio) { // Compensation didn't work, return back to previous decimator - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); } if (sloppy_ratio < 0) @@ -1814,7 +1953,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d && sloppy_decimator > precise_ratio && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case { - sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); sloppy_decimator = sloppy_decimator / sloppy_decimation_step; } } @@ -1834,7 +1973,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d else { // Fallback to normal method - precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); } LL_INFOS() << "Model " << target_model->getName() @@ -2562,8 +2701,6 @@ void LLModelPreview::clearBuffers() void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) { - U32 tri_count = 0; - U32 vertex_count = 0; U32 mesh_count = 0; @@ -2596,7 +2733,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) continue; } - LLModel* base_mdl = *base_iter; base_iter++; S32 num_faces = mdl->getNumVolumeFaces(); @@ -2671,7 +2807,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) //find closest weight to vf.mVertices[i].mPosition LLVector3 pos(vf.mPositions[i].getF32ptr()); - const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos); + const LLModel::weight_list& weight_list = mdl->getJointInfluences(pos); llassert(weight_list.size()>0 && weight_list.size() <= 4); // LLModel::loadModel() should guarantee this LLVector4 w(0, 0, 0, 0); @@ -2699,10 +2835,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) mVertexBuffer[lod][mdl].push_back(vb); - vertex_count += num_vertices; - tri_count += num_indices / 3; ++mesh_count; - } } } @@ -2798,6 +2931,20 @@ void LLModelPreview::loadedCallback( { pPreview->lookupLODModelFiles(lod); } + + const LLVOAvatar* avatarp = pPreview->getPreviewAvatar(); + if (avatarp) { // set up ground plane for possible rendering + const LLVector3 root_pos = avatarp->mRoot->getPosition(); + const LLVector4a* ext = avatarp->mDrawable->getSpatialExtents(); + const LLVector4a min = ext[0], max = ext[1]; + const F32 center = (max[2] - min[2]) * 0.5f; + const F32 ground = root_pos[2] - center; + auto plane = pPreview->mGroundPlane; + plane[0] = {min[0], min[1], ground}; + plane[1] = {max[0], min[1], ground}; + plane[2] = {max[0], max[1], ground}; + plane[3] = {min[0], max[1], ground}; + } } } @@ -3005,6 +3152,9 @@ BOOL LLModelPreview::render() // (note: all these UI updates need to be somewhere that is not render) fmp->childSetValue("upload_skin", true); mFirstSkinUpdate = false; + upload_skin = true; + skin_weight = true; + mViewOption["show_skin_weight"] = true; } fmp->enableViewOption("show_skin_weight"); @@ -3609,6 +3759,7 @@ BOOL LLModelPreview::render() { getPreviewAvatar()->renderBones(); } + renderGroundPlane(mPelvisZOffset); if (shader) { shader->bind(); @@ -3630,6 +3781,28 @@ BOOL LLModelPreview::render() return TRUE; } +void LLModelPreview::renderGroundPlane(float z_offset) +{ // Not necesarilly general - beware - but it seems to meet the needs of LLModelPreview::render + + gGL.diffuseColor3f( 1.0f, 0.0f, 1.0f ); + + gGL.begin(LLRender::LINES); + gGL.vertex3fv(mGroundPlane[0].mV); + gGL.vertex3fv(mGroundPlane[1].mV); + + gGL.vertex3fv(mGroundPlane[1].mV); + gGL.vertex3fv(mGroundPlane[2].mV); + + gGL.vertex3fv(mGroundPlane[2].mV); + gGL.vertex3fv(mGroundPlane[3].mV); + + gGL.vertex3fv(mGroundPlane[3].mV); + gGL.vertex3fv(mGroundPlane[0].mV); + + gGL.end(); +} + + //----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- @@ -3745,7 +3918,7 @@ bool LLModelPreview::lodQueryCallback() } // return false to continue cycle - return false; + return preview->mLodsQuery.empty(); } } // nothing to process diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 9e32215e6a..df7320768c 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -125,7 +125,7 @@ public: { LOD_FROM_FILE = 0, MESH_OPTIMIZER_AUTO, // automatically selects method based on model or face - MESH_OPTIMIZER_COMBINE, // combines faces into a single model, simplifies, then splits back into faces + MESH_OPTIMIZER_PRECISE, // combines faces into a single model, simplifies, then splits back into faces MESH_OPTIMIZER_SLOPPY, // uses sloppy method, works per face USE_LOD_ABOVE, } eLoDMode; @@ -224,14 +224,39 @@ private: LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; } // Count amount of original models, excluding sub-models static U32 countRootModels(LLModelLoader::model_list models); + LLVector3 mGroundPlane[4]; + void renderGroundPlane(float z_offset = 0.0f); + /// Indicates whether we should warn of high-lod meshes that do not have a corresponding physics mesh. + /// Reset when resetting the modelpreview (i.e., when the uploader dialog is created or reset), and when + /// about to process a physics file. Set to true immediately after the file is loaded (before rebuildUploadData()). + /// + /// (The rules for mapping the correspondence of high-lod meshes to physics meshes are complex. When + /// lod rendering meshes are used, there is never an unmatched mesh. Nor is there a mismatch when + /// the high-lod file and physics file have ony one mesh each. In these cases, this value is moot. + /// When there are multiple meshes in each file, they are matched by name or order, and some meshes + /// are broken up by limitations into multiple objects, and thus there can be mismatches.) + bool mWarnOfUnmatchedPhyicsMeshes{false}; + /// A mesh to use as the default physics shape in only those cases where the physics shape is not otherwise specified. + /// It is set only when the user chooses a physics shape file that contains a mesh with a name that matches DEFAULT_PHYSICS_MESH_NAME. + /// It is reset when such a name is not found, and when resetting the modelpreview. + /// Not read unless mWarnOfUnmatchedPhyicsMeshes is true. + LLModel* mDefaultPhysicsShapeP{}; + + typedef enum + { + MESH_OPTIMIZER_FULL, + MESH_OPTIMIZER_NO_NORMALS, + MESH_OPTIMIZER_NO_UVS, + MESH_OPTIMIZER_NO_TOPOLOGY, + } eSimplificationMode; // Merges faces into single mesh, simplifies using mesh optimizer, // then splits back into faces. // Returns reached simplification ratio. -1 in case of a failure. - F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, bool sloppy); + F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode); // Simplifies specified face using mesh optimizer. // Returns reached simplification ratio. -1 in case of a failure. - F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, bool sloppy); + F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode); protected: friend class LLModelLoader; diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 4a8ef53a8b..bf00d77dea 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -352,7 +352,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) void LLMuteList::updateAdd(const LLMute& mute) { - // External mutes (e.g. Avaline callers) are local only, don't send them to the server. + // External mutes are local only, don't send them to the server. if (mute.mType == LLMute::EXTERNAL) { return; diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 5215126789..8058faa5c7 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -271,6 +271,25 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) return handled; } +// virtual +BOOL LLNameListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y)); + LLFloater* floater = gFloaterView->getParentFloater(this); + if (floater && floater->isFrontmost() && hit_item) + { + if(hit_item->isGroup()) + { + ContextMenuType prev_menu = getContextMenuType(); + setContextMenu(MENU_GROUP); + BOOL handled = LLScrollListCtrl::handleRightMouseDown(x, y, mask); + setContextMenu(prev_menu); + return handled; + } + } + return LLScrollListCtrl::handleRightMouseDown(x, y, mask); +} + // public void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, BOOL enabled) diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index ef0be135e6..5dd5da5892 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -170,6 +170,7 @@ public: /*virtual*/ void updateColumns(bool force_update); /*virtual*/ void mouseOverHighlightNthItem( S32 index ); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); private: void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, std::string prefix, LLHandle<LLNameListItem> item); diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 19dbbeb60e..f5ee1171d9 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -451,9 +451,9 @@ void LLNavigationBar::onLocationSelection() if(value.has("AssetUUID")) { - gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString())); - mSaveToLocationHistory = true; + // user teleported by manually inputting inventory landmark's name + mSaveToLocationHistory = false; return; } else @@ -713,7 +713,7 @@ void LLNavigationBar::resizeLayoutPanel() } void LLNavigationBar::invokeSearch(std::string search_text) { - LLFloaterReg::showInstance("search", LLSD().with("category", "all").with("query", LLSD(search_text))); + LLFloaterReg::showInstance("search", LLSD().with("category", "standard").with("query", LLSD(search_text))); } void LLNavigationBar::clearHistoryCache() @@ -733,3 +733,8 @@ int LLNavigationBar::getDefFavBarHeight() { return mDefaultFpRect.getHeight(); } + +bool LLNavigationBar::isRebakeNavMeshAvailable() +{ + return mCmbLocation->isNavMeshDirty(); +} diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 646911a62c..11c671294a 100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -102,6 +102,8 @@ public: int getDefNavBarHeight(); int getDefFavBarHeight(); + + bool isRebakeNavMeshAvailable(); private: // the distance between navigation panel and favorites panel in pixels diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 1240ce7c0f..b34be80b07 100644..100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -37,6 +37,7 @@ #include "llfocusmgr.h" #include "lllocalcliprect.h" #include "llrender.h" +#include "llresmgr.h" #include "llui.h" #include "lltooltip.h" @@ -47,11 +48,16 @@ #include "llagentcamera.h" #include "llappviewer.h" // for gDisconnected #include "llcallingcard.h" // LLAvatarTracker +#include "llfloaterland.h" #include "llfloaterworldmap.h" +#include "llparcel.h" #include "lltracker.h" #include "llsurface.h" +#include "llurlmatch.h" +#include "llurlregistry.h" #include "llviewercamera.h" #include "llviewercontrol.h" +#include "llviewerparcelmgr.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewermenu.h" @@ -64,7 +70,10 @@ static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map"); const F32 LLNetMap::MAP_SCALE_MIN = 32; -const F32 LLNetMap::MAP_SCALE_MID = 1024; +const F32 LLNetMap::MAP_SCALE_FAR = 32; +const F32 LLNetMap::MAP_SCALE_MEDIUM = 128; +const F32 LLNetMap::MAP_SCALE_CLOSE = 256; +const F32 LLNetMap::MAP_SCALE_VERY_CLOSE = 1024; const F32 LLNetMap::MAP_SCALE_MAX = 4096; const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%) @@ -78,13 +87,13 @@ const F64 COARSEUPDATE_MAX_Z = 1020.0f; LLNetMap::LLNetMap (const Params & p) : LLUICtrl (p), mBackgroundColor (p.bg_color()), - mScale( MAP_SCALE_MID ), - mPixelsPerMeter( MAP_SCALE_MID / REGION_WIDTH_METERS ), + mScale( MAP_SCALE_MEDIUM ), + mPixelsPerMeter( MAP_SCALE_MEDIUM / REGION_WIDTH_METERS ), mObjectMapTPM(0.f), mObjectMapPixels(0.f), - mTargetPan(0.f, 0.f), mCurPan(0.f, 0.f), mStartPan(0.f, 0.f), + mPopupWorldPos(0.f, 0.f, 0.f), mMouseDown(0, 0), mPanning(false), mUpdateNow(false), @@ -97,6 +106,13 @@ LLNetMap::LLNetMap (const Params & p) mPopupMenu(NULL) { mScale = gSavedSettings.getF32("MiniMapScale"); + if (gAgent.isFirstLogin()) + { + // *HACK: On first run, set this to false for new users, otherwise the + // default is true to maintain consistent experience for existing + // users. + gSavedSettings.setBOOL("MiniMapRotate", false); + } mPixelsPerMeter = mScale / REGION_WIDTH_METERS; mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS); } @@ -107,13 +123,22 @@ LLNetMap::~LLNetMap() BOOL LLNetMap::postBuild() { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - - registrar.add("Minimap.Zoom", boost::bind(&LLNetMap::handleZoom, this, _2)); - registrar.add("Minimap.Tracker", boost::bind(&LLNetMap::handleStopTracking, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - return TRUE; + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commitRegistrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enableRegistrar; + + enableRegistrar.add("Minimap.Zoom.Check", boost::bind(&LLNetMap::isZoomChecked, this, _2)); + commitRegistrar.add("Minimap.Zoom.Set", boost::bind(&LLNetMap::setZoom, this, _2)); + commitRegistrar.add("Minimap.Tracker", boost::bind(&LLNetMap::handleStopTracking, this, _2)); + commitRegistrar.add("Minimap.Center.Activate", boost::bind(&LLNetMap::activateCenterMap, this, _2)); + enableRegistrar.add("Minimap.MapOrientation.Check", boost::bind(&LLNetMap::isMapOrientationChecked, this, _2)); + commitRegistrar.add("Minimap.MapOrientation.Set", boost::bind(&LLNetMap::setMapOrientation, this, _2)); + commitRegistrar.add("Minimap.AboutLand", boost::bind(&LLNetMap::popupShowAboutLand, this, _2)); + + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); + mPopupMenu->setItemEnabled("Re-center map", false); + + return true; } void LLNetMap::setScale( F32 scale ) @@ -158,18 +183,32 @@ void LLNetMap::draw() static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white); //static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white); static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white); - static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white); + static LLUIColor map_parcel_outline_color = LLUIColorTable::instance().getColor("MapParcelOutlineColor", LLColor4(LLColor3(LLColor4::yellow), 0.5f)); if (mObjectImagep.isNull()) { createObjectImage(); } - static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); - if (auto_center) + static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); + bool auto_centering = auto_center && !mPanning; + mCentering = mCentering && !mPanning; + + if (auto_centering || mCentering) { - mCurPan = lerp(mCurPan, mTargetPan, LLSmoothInterpolation::getInterpolant(0.1f)); + mCurPan = lerp(mCurPan, LLVector2(0.0f, 0.0f) , LLSmoothInterpolation::getInterpolant(0.1f)); } + bool centered = abs(mCurPan.mV[VX]) < 0.5f && abs(mCurPan.mV[VY]) < 0.5f; + if (centered) + { + mCurPan.mV[0] = 0.0f; + mCurPan.mV[1] = 0.0f; + mCentering = false; + } + + bool can_recenter_map = !(centered || mCentering || auto_centering); + mPopupMenu->setItemEnabled("Re-center map", can_recenter_map); + updateAboutLandPopupButton(); // Prepare a scissor region F32 rotation = 0; @@ -216,7 +255,8 @@ void LLNetMap::draw() } // figure out where agent is - S32 region_width = ll_round(LLWorld::getInstance()->getRegionWidthInMeters()); + const S32 region_width = ll_round(LLWorld::getInstance()->getRegionWidthInMeters()); + const F32 scale_pixels_per_meter = mScale / region_width; for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -225,8 +265,8 @@ void LLNetMap::draw() // Find x and y position relative to camera's center. LLVector3 origin_agent = regionp->getOriginAgent(); LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent(); - F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale; - F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale; + F32 relative_x = rel_region_pos.mV[0] * scale_pixels_per_meter; + F32 relative_y = rel_region_pos.mV[1] * scale_pixels_per_meter; // background region rectangle F32 bottom = relative_y; @@ -249,6 +289,7 @@ void LLNetMap::draw() } + // Draw using texture. gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture()); gGL.begin(LLRender::QUADS); @@ -310,8 +351,8 @@ void LLNetMap::draw() LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal); LLVector3 camera_position = gAgentCamera.getCameraPositionAgent(); map_center_agent -= camera_position; - map_center_agent.mV[VX] *= mScale/region_width; - map_center_agent.mV[VY] *= mScale/region_width; + map_center_agent.mV[VX] *= scale_pixels_per_meter; + map_center_agent.mV[VY] *= scale_pixels_per_meter; gGL.getTexUnit(0)->bind(mObjectImagep); F32 image_half_width = 0.5f*mObjectMapPixels; @@ -327,6 +368,13 @@ void LLNetMap::draw() gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]); gGL.end(); + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + regionp->renderPropertyLinesOnMinimap(scale_pixels_per_meter, map_parcel_outline_color.get().mV); + } gGL.popMatrix(); @@ -451,41 +499,34 @@ void LLNetMap::draw() F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); F32 far_clip_pixels = far_clip_meters * meters_to_pixels; - - F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); - F32 half_width_pixels = half_width_meters * meters_to_pixels; - F32 ctr_x = (F32)center_sw_left; - F32 ctr_y = (F32)center_sw_bottom; - - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - if( rotate_map ) - { - gGL.color4fv((map_frustum_color()).mV); - - gGL.begin( LLRender::TRIANGLES ); - gGL.vertex2f( ctr_x, ctr_y ); - gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels ); - gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels ); - gGL.end(); - } - else - { - gGL.color4fv((map_frustum_rotating_color()).mV); - - // If we don't rotate the map, we have to rotate the frustum. - gGL.pushMatrix(); - gGL.translatef( ctr_x, ctr_y, 0 ); - gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); - gGL.begin( LLRender::TRIANGLES ); - gGL.vertex2f( 0, 0 ); - gGL.vertex2f( -half_width_pixels, far_clip_pixels ); - gGL.vertex2f( half_width_pixels, far_clip_pixels ); - gGL.end(); - gGL.popMatrix(); - } + F32 ctr_x = (F32)center_sw_left; + F32 ctr_y = (F32)center_sw_bottom; + + const F32 steps_per_circle = 40.0f; + const F32 steps_per_radian = steps_per_circle / F_TWO_PI; + const F32 arc_start = -(horiz_fov / 2.0f) + F_PI_BY_TWO; + const F32 arc_end = (horiz_fov / 2.0f) + F_PI_BY_TWO; + const S32 steps = llmax(1, (S32)((horiz_fov * steps_per_radian) + 0.5f)); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + if( rotate_map ) + { + gGL.pushMatrix(); + gGL.translatef( ctr_x, ctr_y, 0 ); + gl_washer_segment_2d(far_clip_pixels, 0, arc_start, arc_end, steps, map_frustum_color(), map_frustum_color()); + gGL.popMatrix(); + } + else + { + gGL.pushMatrix(); + gGL.translatef( ctr_x, ctr_y, 0 ); + // If we don't rotate the map, we have to rotate the frustum. + gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); + gl_washer_segment_2d(far_clip_pixels, 0, arc_start, arc_end, steps, map_frustum_color(), map_frustum_color()); + gGL.popMatrix(); + } } gGL.popMatrix(); @@ -552,6 +593,65 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, } } +bool LLNetMap::isMouseOnPopupMenu() +{ + if (!mPopupMenu->isOpen()) + { + return false; + } + + S32 popup_x; + S32 popup_y; + LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y); + // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain + // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22 + constexpr S32 tolerance = 10; + // Test tolerance from all four corners, as the popup menu can appear from a different direction if there's not enough space. + // Assume the size of the popup menu is much larger than the provided tolerance. + // In practice, this is a [tolerance]px margin around the popup menu. + for (S32 sign_x = -1; sign_x <= 1; sign_x += 2) + { + for (S32 sign_y = -1; sign_y <= 1; sign_y += 2) + { + if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) + { + return true; + } + } + } + return false; +} + +void LLNetMap::updateAboutLandPopupButton() +{ + if (!mPopupMenu->isOpen()) + { + return; + } + + LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos); + if (!region) + { + mPopupMenu->setItemEnabled("About Land", false); + } + else + { + // Check if the mouse is in the bounds of the popup. If so, it's safe to assume no other hover function will be called, so the hover + // parcel can be used to check if location-sensitive tooltip options are available. + if (isMouseOnPopupMenu()) + { + LLViewerParcelMgr::getInstance()->setHoverParcel(mPopupWorldPos); + LLParcel *hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); + bool valid_parcel = false; + if (hover_parcel) + { + valid_parcel = hover_parcel->getOwnerID().notNull(); + } + mPopupMenu->setItemEnabled("About Land", valid_parcel); + } + } +} + LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y ) { x -= ll_round(getRect().getWidth() / 2 + mCurPan.mV[VX]); @@ -579,66 +679,152 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y ) BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks) { - // note that clicks are reversed from what you'd think: i.e. > 0 means zoom out, < 0 means zoom in - F32 new_scale = mScale * pow(MAP_SCALE_ZOOM_FACTOR, -clicks); + // note that clicks are reversed from what you'd think: i.e. > 0 means zoom out, < 0 means zoom in + F32 new_scale = mScale * pow(MAP_SCALE_ZOOM_FACTOR, -clicks); F32 old_scale = mScale; - setScale(new_scale); + setScale(new_scale); - static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); - if (!auto_center) - { - // Adjust pan to center the zoom on the mouse pointer - LLVector2 zoom_offset; - zoom_offset.mV[VX] = x - getRect().getWidth() / 2; - zoom_offset.mV[VY] = y - getRect().getHeight() / 2; - mCurPan -= zoom_offset * mScale / old_scale - zoom_offset; - } + static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); + if (!auto_center) + { + // Adjust pan to center the zoom on the mouse pointer + LLVector2 zoom_offset; + zoom_offset.mV[VX] = x - getRect().getWidth() / 2; + zoom_offset.mV[VY] = y - getRect().getHeight() / 2; + mCurPan -= zoom_offset * mScale / old_scale - zoom_offset; + } - return TRUE; + return true; } -BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleToolTip(S32 x, S32 y, MASK mask) { - if (gDisconnected) - { - return FALSE; - } + if (gDisconnected) + { + return false; + } - // If the cursor is near an avatar on the minimap, a mini-inspector will be - // shown for the avatar, instead of the normal map tooltip. - if (handleToolTipAgent(mClosestAgentToCursor)) - { - return TRUE; - } + // If the cursor is near an avatar on the minimap, a mini-inspector will be + // shown for the avatar, instead of the normal map tooltip. + if (handleToolTipAgent(mClosestAgentToCursor)) + { + return true; + } - LLRect sticky_rect; - std::string region_name; - LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) ); - if(region) - { - // set sticky_rect - S32 SLOP = 4; - localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect.mLeft), &(sticky_rect.mBottom)); - sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; - sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP; - - region_name = region->getName(); - if (!region_name.empty()) - { - region_name += "\n"; - } - } + // The popup menu uses the hover parcel when it is open and the mouse is on + // top of it, with some additional tolerance. Returning early here prevents + // fighting over that hover parcel when getting tooltip info in the + // tolerance region. + if (isMouseOnPopupMenu()) + { + return false; + } - LLStringUtil::format_map_t args; - args["[REGION]"] = region_name; - std::string msg = mToolTipMsg; - LLStringUtil::format(msg, args); - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(msg) - .sticky_rect(sticky_rect)); - - return TRUE; + LLRect sticky_rect; + S32 SLOP = 4; + localPointToScreen(x - SLOP, y - SLOP, &(sticky_rect.mLeft), &(sticky_rect.mBottom)); + sticky_rect.mRight = sticky_rect.mLeft + 2 * SLOP; + sticky_rect.mTop = sticky_rect.mBottom + 2 * SLOP; + + std::string parcel_name_msg; + std::string parcel_sale_price_msg; + std::string parcel_sale_area_msg; + std::string parcel_owner_msg; + std::string region_name_msg; + + LLVector3d posGlobal = viewPosToGlobal(x, y); + LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(posGlobal); + if (region) + { + std::string region_name = region->getName(); + if (!region_name.empty()) + { + region_name_msg = mRegionNameMsg; + LLStringUtil::format(region_name_msg, {{"[REGION_NAME]", region_name}}); + } + + // Only show parcel information in the tooltip if property lines are visible. Otherwise, the parcel the tooltip is referring to is + // ambiguous. + if (gSavedSettings.getBOOL("MiniMapShowPropertyLines")) + { + LLViewerParcelMgr::getInstance()->setHoverParcel(posGlobal); + LLParcel *hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); + if (hover_parcel) + { + std::string parcel_name = hover_parcel->getName(); + if (!parcel_name.empty()) + { + parcel_name_msg = mParcelNameMsg; + LLStringUtil::format(parcel_name_msg, {{"[PARCEL_NAME]", parcel_name}}); + } + + const LLUUID parcel_owner = hover_parcel->getOwnerID(); + std::string parcel_owner_name_url = LLSLURL("agent", parcel_owner, "inspect").getSLURLString(); + static LLUrlMatch parcel_owner_name_url_match; + LLUrlRegistry::getInstance()->findUrl(parcel_owner_name_url, parcel_owner_name_url_match); + if (!parcel_owner_name_url_match.empty()) + { + parcel_owner_msg = mParcelOwnerMsg; + std::string parcel_owner_name = parcel_owner_name_url_match.getLabel(); + LLStringUtil::format(parcel_owner_msg, {{"[PARCEL_OWNER]", parcel_owner_name}}); + } + + if (hover_parcel->getForSale()) + { + const LLUUID auth_buyer_id = hover_parcel->getAuthorizedBuyerID(); + const LLUUID agent_id = gAgent.getID(); + bool show_for_sale = auth_buyer_id.isNull() || auth_buyer_id == agent_id || parcel_owner == agent_id; + if (show_for_sale) + { + S32 price = hover_parcel->getSalePrice(); + S32 area = hover_parcel->getArea(); + F32 cost_per_sqm = 0.0f; + if (area > 0) + { + cost_per_sqm = F32(price) / area; + } + std::string formatted_price = LLResMgr::getInstance()->getMonetaryString(price); + std::string formatted_cost_per_meter = llformat("%.1f", cost_per_sqm); + parcel_sale_price_msg = mParcelSalePriceMsg; + LLStringUtil::format(parcel_sale_price_msg, + {{"[PRICE]", formatted_price}, {"[PRICE_PER_SQM]", formatted_cost_per_meter}}); + std::string formatted_area = llformat("%d", area); + parcel_sale_area_msg = mParcelSaleAreaMsg; + LLStringUtil::format(parcel_sale_area_msg, {{"[AREA]", formatted_area}}); + } + } + } + } + } + + std::string tool_tip_hint_msg; + if (gSavedSettings.getBOOL("DoubleClickTeleport")) + { + tool_tip_hint_msg = mAltToolTipHintMsg; + } + else if (gSavedSettings.getBOOL("DoubleClickShowWorldMap")) + { + tool_tip_hint_msg = mToolTipHintMsg; + } + + LLStringUtil::format_map_t args; + args["[PARCEL_NAME_MSG]"] = parcel_name_msg.empty() ? "" : parcel_name_msg + '\n'; + args["[PARCEL_SALE_PRICE_MSG]"] = parcel_sale_price_msg.empty() ? "" : parcel_sale_price_msg + '\n'; + args["[PARCEL_SALE_AREA_MSG]"] = parcel_sale_area_msg.empty() ? "" : parcel_sale_area_msg + '\n'; + args["[PARCEL_OWNER_MSG]"] = parcel_owner_msg.empty() ? "" : parcel_owner_msg + '\n'; + args["[REGION_NAME_MSG]"] = region_name_msg.empty() ? "" : region_name_msg + '\n'; + args["[TOOL_TIP_HINT_MSG]"] = tool_tip_hint_msg.empty() ? "" : tool_tip_hint_msg + '\n'; + + std::string msg = mToolTipMsg; + LLStringUtil::format(msg, args); + if (msg.back() == '\n') + { + msg.resize(msg.size() - 1); + } + LLToolTipMgr::instance().show(LLToolTip::Params().message(msg).sticky_rect(sticky_rect)); + + return true; } BOOL LLNetMap::handleToolTipAgent(const LLUUID& avatar_id) @@ -811,59 +997,58 @@ void LLNetMap::createObjectImage() mUpdateNow = true; } -BOOL LLNetMap::handleMouseDown( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleMouseDown(S32 x, S32 y, MASK mask) { - if (!(mask & MASK_SHIFT)) return FALSE; - - // Start panning - gFocusMgr.setMouseCapture(this); + // Start panning + gFocusMgr.setMouseCapture(this); - mStartPan = mCurPan; - mMouseDown.mX = x; - mMouseDown.mY = y; - return TRUE; + mStartPan = mCurPan; + mMouseDown.mX = x; + mMouseDown.mY = y; + return true; } -BOOL LLNetMap::handleMouseUp( S32 x, S32 y, MASK mask ) +BOOL LLNetMap::handleMouseUp(S32 x, S32 y, MASK mask) { - if(abs(mMouseDown.mX-x)<3 && abs(mMouseDown.mY-y)<3) - handleClick(x,y,mask); + if (abs(mMouseDown.mX - x) < 3 && abs(mMouseDown.mY - y) < 3) + { + handleClick(x, y, mask); + } - if (hasMouseCapture()) - { - if (mPanning) - { - // restore mouse cursor - S32 local_x, local_y; - local_x = mMouseDown.mX + llfloor(mCurPan.mV[VX] - mStartPan.mV[VX]); - local_y = mMouseDown.mY + llfloor(mCurPan.mV[VY] - mStartPan.mV[VY]); - LLRect clip_rect = getRect(); - clip_rect.stretch(-8); - clip_rect.clipPointToRect(mMouseDown.mX, mMouseDown.mY, local_x, local_y); - LLUI::getInstance()->setMousePositionLocal(this, local_x, local_y); - - // finish the pan - mPanning = false; - - mMouseDown.set(0, 0); - - // auto centre - mTargetPan.setZero(); - } - gViewerWindow->showCursor(); - gFocusMgr.setMouseCapture(NULL); - return TRUE; - } - return FALSE; + if (hasMouseCapture()) + { + if (mPanning) + { + // restore mouse cursor + S32 local_x, local_y; + local_x = mMouseDown.mX + llfloor(mCurPan.mV[VX] - mStartPan.mV[VX]); + local_y = mMouseDown.mY + llfloor(mCurPan.mV[VY] - mStartPan.mV[VY]); + LLRect clip_rect = getRect(); + clip_rect.stretch(-8); + clip_rect.clipPointToRect(mMouseDown.mX, mMouseDown.mY, local_x, local_y); + LLUI::getInstance()->setMousePositionLocal(this, local_x, local_y); + + // finish the pan + mPanning = false; + + mMouseDown.set(0, 0); + } + gViewerWindow->showCursor(); + gFocusMgr.setMouseCapture(NULL); + return true; + } + + return false; } BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) { if (mPopupMenu) { + mPopupWorldPos = viewPosToGlobal(x, y); mPopupMenu->buildDrawLabels(); mPopupMenu->updateParent(LLMenuGL::sMenuContainer); - mPopupMenu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); + mPopupMenu->setItemEnabled("Stop tracking", LLTracker::isTracking(0)); LLMenuGL::showPopup(this, mPopupMenu, x, y); } return TRUE; @@ -911,6 +1096,27 @@ BOOL LLNetMap::handleDoubleClick(S32 x, S32 y, MASK mask) return TRUE; } +F32 LLNetMap::getScaleForName(std::string scale_name) +{ + if (scale_name == "very close") + { + return LLNetMap::MAP_SCALE_VERY_CLOSE; + } + else if (scale_name == "close") + { + return LLNetMap::MAP_SCALE_CLOSE; + } + else if (scale_name == "medium") + { + return LLNetMap::MAP_SCALE_MEDIUM; + } + else if (scale_name == "far") + { + return LLNetMap::MAP_SCALE_FAR; + } + return 0.0f; +} + // static bool LLNetMap::outsideSlop( S32 x, S32 y, S32 start_x, S32 start_y, S32 slop ) { @@ -928,7 +1134,7 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask ) { if (!mPanning) { - // just started panning, so hide cursor + // Just started panning. Hide cursor. mPanning = true; gViewerWindow->hideCursor(); } @@ -938,61 +1144,89 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask ) // Set pan to value at start of drag + offset mCurPan += delta; - mTargetPan = mCurPan; gViewerWindow->moveCursorToCenter(); } - - // Doesn't really matter, cursor should be hidden - gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); - } - else - { - if (mask & MASK_SHIFT) - { - // If shift is held, change the cursor to hint that the map can be dragged - gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); - } - else - { - gViewerWindow->setCursor( UI_CURSOR_CROSS ); - } } + if (mask & MASK_SHIFT) + { + // If shift is held, change the cursor to hint that the map can be + // dragged. However, holding shift is not required to drag the map. + gViewerWindow->setCursor( UI_CURSOR_TOOLPAN ); + } + else + { + gViewerWindow->setCursor( UI_CURSOR_CROSS ); + } + return TRUE; } -void LLNetMap::handleZoom(const LLSD& userdata) +bool LLNetMap::isZoomChecked(const LLSD &userdata) { - std::string level = userdata.asString(); - - F32 scale = 0.0f; - if (level == std::string("default")) - { - LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale"); - if(pvar) - { - pvar->resetToDefault(); - scale = gSavedSettings.getF32("MiniMapScale"); - } - } - else if (level == std::string("close")) - scale = LLNetMap::MAP_SCALE_MAX; - else if (level == std::string("medium")) - scale = LLNetMap::MAP_SCALE_MID; - else if (level == std::string("far")) - scale = LLNetMap::MAP_SCALE_MIN; - if (scale != 0.0f) - { - setScale(scale); - } + std::string level = userdata.asString(); + F32 scale = getScaleForName(level); + return scale == mScale; +} + +void LLNetMap::setZoom(const LLSD &userdata) +{ + std::string level = userdata.asString(); + F32 scale = getScaleForName(level); + if (scale != 0.0f) + { + setScale(scale); + } } void LLNetMap::handleStopTracking (const LLSD& userdata) { if (mPopupMenu) { - mPopupMenu->setItemEnabled ("Stop Tracking", false); + mPopupMenu->setItemEnabled ("Stop tracking", false); LLTracker::stopTracking (LLTracker::isTracking(NULL)); } } + +void LLNetMap::activateCenterMap(const LLSD &userdata) { mCentering = true; } + +bool LLNetMap::isMapOrientationChecked(const LLSD &userdata) +{ + const std::string command_name = userdata.asString(); + const bool rotate_map = gSavedSettings.getBOOL("MiniMapRotate"); + if (command_name == "north_at_top") + { + return !rotate_map; + } + + if (command_name == "camera_at_top") + { + return rotate_map; + } + + return false; +} + +void LLNetMap::setMapOrientation(const LLSD &userdata) +{ + const std::string command_name = userdata.asString(); + if (command_name == "north_at_top") + { + gSavedSettings.setBOOL("MiniMapRotate", false); + } + else if (command_name == "camera_at_top") + { + gSavedSettings.setBOOL("MiniMapRotate", true); + } +} + +void LLNetMap::popupShowAboutLand(const LLSD &userdata) +{ + // Update parcel selection. It's important to deselect land first so the "About Land" floater doesn't refresh with the old selection. + LLViewerParcelMgr::getInstance()->deselectLand(); + LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt(mPopupWorldPos); + gMenuHolder->setParcelSelection(selection); + + LLFloaterReg::showInstance("about_land", LLSD(), false); +} diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 1f7e7d68c6..fe1aca65a9 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -62,9 +62,12 @@ protected: public: virtual ~LLNetMap(); - static const F32 MAP_SCALE_MIN; - static const F32 MAP_SCALE_MID; - static const F32 MAP_SCALE_MAX; + static const F32 MAP_SCALE_MIN; + static const F32 MAP_SCALE_FAR; + static const F32 MAP_SCALE_MEDIUM; + static const F32 MAP_SCALE_CLOSE; + static const F32 MAP_SCALE_VERY_CLOSE; + static const F32 MAP_SCALE_MAX; /*virtual*/ void draw(); /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); @@ -79,8 +82,17 @@ public: /*virtual*/ BOOL handleClick(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - void setScale( F32 scale ); - void setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; } + void setScale(F32 scale); + + void setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; } + void setParcelNameMsg(const std::string& msg) { mParcelNameMsg = msg; } + void setParcelSalePriceMsg(const std::string& msg) { mParcelSalePriceMsg = msg; } + void setParcelSaleAreaMsg(const std::string& msg) { mParcelSaleAreaMsg = msg; } + void setParcelOwnerMsg(const std::string& msg) { mParcelOwnerMsg = msg; } + void setRegionNameMsg(const std::string& msg) { mRegionNameMsg = msg; } + void setToolTipHintMsg(const std::string& msg) { mToolTipHintMsg = msg; } + void setAltToolTipHintMsg(const std::string& msg) { mAltToolTipHintMsg = msg; } + void renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius ); private: @@ -94,11 +106,14 @@ private: void drawTracking( const LLVector3d& pos_global, const LLColor4& color, BOOL draw_arrow = TRUE); + bool isMouseOnPopupMenu(); + void updateAboutLandPopupButton(); BOOL handleToolTipAgent(const LLUUID& avatar_id); static void showAvatarInspector(const LLUUID& avatar_id); void createObjectImage(); + F32 getScaleForName(std::string scale_name); static bool outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y, S32 slop); private: @@ -112,11 +127,12 @@ private: F32 mObjectMapPixels; // Width of object map in pixels F32 mDotRadius; // Size of avatar markers - bool mPanning; // map is being dragged - LLVector2 mTargetPan; - LLVector2 mCurPan; - LLVector2 mStartPan; // pan offset at start of drag - LLCoordGL mMouseDown; // pointer position at start of drag + bool mPanning; // map is being dragged + bool mCentering; // map is being re-centered around the agent + LLVector2 mCurPan; + LLVector2 mStartPan; // pan offset at start of drag + LLVector3d mPopupWorldPos; // world position picked under mouse when context menu is opened + LLCoordGL mMouseDown; // pointer position at start of drag LLVector3d mObjectImageCenterGlobal; LLPointer<LLImageRaw> mObjectRawImagep; @@ -125,14 +141,26 @@ private: LLUUID mClosestAgentToCursor; LLUUID mClosestAgentAtLastRightClick; - std::string mToolTipMsg; + std::string mToolTipMsg; + std::string mParcelNameMsg; + std::string mParcelSalePriceMsg; + std::string mParcelSaleAreaMsg; + std::string mParcelOwnerMsg; + std::string mRegionNameMsg; + std::string mToolTipHintMsg; + std::string mAltToolTipHintMsg; public: void setSelected(uuid_vec_t uuids) { gmSelected=uuids; }; private: - void handleZoom(const LLSD& userdata); - void handleStopTracking (const LLSD& userdata); + bool isZoomChecked(const LLSD& userdata); + void setZoom(const LLSD& userdata); + void handleStopTracking(const LLSD& userdata); + void activateCenterMap(const LLSD& userdata); + bool isMapOrientationChecked(const LLSD& userdata); + void setMapOrientation(const LLSD& userdata); + void popupShowAboutLand(const LLSD& userdata); LLMenuGL* mPopupMenu; uuid_vec_t gmSelected; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 4febb72c6c..f419e2e06d 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1374,6 +1374,7 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id) texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2)); texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1)); texture_floaterp->setLocalTextureEnabled(FALSE); + texture_floaterp->setBakeTextureEnabled(FALSE); texture_floaterp->setCanApply(false, true); } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 37ed4bc74c..ff33efe4aa 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llpanelavatar.cpp * @brief LLPanelAvatar and related class implementations * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,173 +28,127 @@ #include "llpanelavatar.h" #include "llagent.h" -#include "llavataractions.h" -#include "llcallingcard.h" -#include "llcombobox.h" -#include "lldateutil.h" // ageFromDate() -#include "llimview.h" -#include "llmenubutton.h" -#include "llnotificationsutil.h" -#include "llslurl.h" -#include "lltexteditor.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" +#include "llloadingindicator.h" #include "lltooldraganddrop.h" -#include "llscrollcontainer.h" -#include "llavatariconctrl.h" -#include "llfloaterreg.h" -#include "llnotificationsutil.h" -#include "llviewermenu.h" // is_agent_mappable -#include "llvoiceclient.h" -#include "lltextbox.h" -#include "lltrans.h" - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLDropTarget -// -// This handy class is a simple way to drop something on another -// view. It handles drop events, always setting itself to the size of -// its parent. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLDropTarget : public LLView -{ -public: - struct Params : public LLInitParam::Block<Params, LLView::Params> - { - Optional<LLUUID> agent_id; - Params() - : agent_id("agent_id") - { - changeDefault(mouse_opaque, false); - changeDefault(follows.flags, FOLLOWS_ALL); - } - }; - - LLDropTarget(const Params&); - ~LLDropTarget(); - - void doDrop(EDragAndDropType cargo_type, void* cargo_data); - - // - // LLView functionality - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - void setAgentID(const LLUUID &agent_id) { mAgentID = agent_id; } -protected: - LLUUID mAgentID; -}; - -LLDropTarget::LLDropTarget(const LLDropTarget::Params& p) -: LLView(p), - mAgentID(p.agent_id) -{} -LLDropTarget::~LLDropTarget() +////////////////////////////////////////////////////////////////////////// +// LLProfileDropTarget + +LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p) +: LLView(p), + mAgentID(p.agent_id) {} -void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) +void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) { - LL_INFOS() << "LLDropTarget::doDrop()" << LL_ENDL; + LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL; } -BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) +BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - if(getParent()) - { - LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, - cargo_type, cargo_data, accept); + if (getParent()) + { + LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, + cargo_type, cargo_data, accept); - return TRUE; - } + return TRUE; + } - return FALSE; + return FALSE; } -static LLDefaultChildRegistry::Register<LLDropTarget> r("drop_target"); +static LLDefaultChildRegistry::Register<LLProfileDropTarget> r("profile_drop_target"); ////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// +// LLPanelProfileTab LLPanelProfileTab::LLPanelProfileTab() : LLPanel() , mAvatarId(LLUUID::null) +, mLoadingState(PROFILE_INIT) +, mSelfProfile(false) { } LLPanelProfileTab::~LLPanelProfileTab() { - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); - } } -void LLPanelProfileTab::setAvatarId(const LLUUID& id) +void LLPanelProfileTab::setAvatarId(const LLUUID& avatar_id) { - if(id.notNull()) - { - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this); - } - mAvatarId = id; - LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this); - } + if (avatar_id.notNull()) + { + mAvatarId = avatar_id; + mSelfProfile = (getAvatarId() == gAgentID); + } } void LLPanelProfileTab::onOpen(const LLSD& key) { - // Don't reset panel if we are opening it for same avatar. - if(getAvatarId() != key.asUUID()) - { - resetControls(); - resetData(); - - scrollToTop(); - } - - // Update data even if we are viewing same avatar profile as some data might been changed. - setAvatarId(key.asUUID()); - updateData(); - updateButtons(); + // Update data even if we are viewing same avatar profile as some data might been changed. + setAvatarId(key.asUUID()); + + setApplyProgress(true); +} + +void LLPanelProfileTab::setLoaded() +{ + setApplyProgress(false); + + mLoadingState = PROFILE_LOADED; +} + +void LLPanelProfileTab::setApplyProgress(bool started) +{ + LLLoadingIndicator* indicator = findChild<LLLoadingIndicator>("progress_indicator"); + + if (indicator) + { + indicator->setVisible(started); + + if (started) + { + indicator->start(); + } + else + { + indicator->stop(); + } + } + + LLView* panel = findChild<LLView>("indicator_stack"); + if (panel) + { + panel->setVisible(started); + } } -void LLPanelProfileTab::scrollToTop() +LLPanelProfilePropertiesProcessorTab::LLPanelProfilePropertiesProcessorTab() + : LLPanelProfileTab() { - LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll"); - if (scrollContainer) - scrollContainer->goToTop(); } -void LLPanelProfileTab::onMapButtonClick() +LLPanelProfilePropertiesProcessorTab::~LLPanelProfilePropertiesProcessorTab() { - LLAvatarActions::showOnMap(getAvatarId()); + if (getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + } } -void LLPanelProfileTab::updateButtons() +void LLPanelProfilePropertiesProcessorTab::setAvatarId(const LLUUID & avatar_id) { - bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); - - if(LLAvatarActions::isFriend(getAvatarId())) - { - getChildView("teleport")->setEnabled(is_buddy_online); - } - else - { - getChildView("teleport")->setEnabled(true); - } - - bool enable_map_btn = (is_buddy_online && - is_agent_mappable(getAvatarId())) - || gAgent.isGodlike(); - getChildView("show_on_map_btn")->setEnabled(enable_map_btn); + if (avatar_id.notNull()) + { + if (getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + } + LLPanelProfileTab::setAvatarId(avatar_id); + LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); + } } diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index e33a850cfa..f182660c8e 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -1,25 +1,25 @@ -/** +/** * @file llpanelavatar.h - * @brief LLPanelAvatar and related class definitions + * @brief Legacy profile panel base class * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * + * Copyright (C) 2019, Linden Research, Inc. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -29,80 +29,141 @@ #include "llpanel.h" #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llvoiceclient.h" #include "llavatarnamecache.h" class LLComboBox; class LLLineEditor; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLProfileDropTarget +// +// This handy class is a simple way to drop something on another +// view. It handles drop events, always setting itself to the size of +// its parent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLProfileDropTarget : public LLView +{ +public: + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + Optional<LLUUID> agent_id; + Params() + : agent_id("agent_id") + { + changeDefault(mouse_opaque, false); + changeDefault(follows.flags, FOLLOWS_ALL); + } + }; + + LLProfileDropTarget(const Params&); + ~LLProfileDropTarget() {} + + void doDrop(EDragAndDropType cargo_type, void* cargo_data); + + // + // LLView functionality + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void setAgentID(const LLUUID &agent_id) { mAgentID = agent_id; } + +protected: + LLUUID mAgentID; +}; + + /** * Base class for any Profile View. */ class LLPanelProfileTab - : public LLPanel - , public LLAvatarPropertiesObserver + : public LLPanel { public: - /** - * Sets avatar ID, sets panel as observer of avatar related info replies from server. - */ - virtual void setAvatarId(const LLUUID& id); - - /** - * Returns avatar ID. - */ - virtual const LLUUID& getAvatarId() { return mAvatarId; } - - /** - * Sends update data request to server. - */ - virtual void updateData() = 0; - - /** - * Clears panel data if viewing avatar info for first time and sends update data request. - */ - virtual void onOpen(const LLSD& key); - - /** - * Profile tabs should close any opened panels here. - * - * Called from LLPanelProfile::onOpen() before opening new profile. - * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel - * before new profile is displayed, otherwise new profile will - * be hidden behind picture info panel. - */ - virtual void onClosePanel() {} - - /** - * Resets controls visibility, state, etc. - */ - virtual void resetControls(){}; - - /** - * Clears all data received from server. - */ - virtual void resetData(){}; - - /*virtual*/ ~LLPanelProfileTab(); + /** + * Sets avatar ID, sets panel as observer of avatar related info replies from server. + */ + virtual void setAvatarId(const LLUUID& avatar_id); + + /** + * Returns avatar ID. + */ + virtual const LLUUID& getAvatarId() { return mAvatarId; } + + /** + * Sends update data request to server. + */ + virtual void updateData() {}; + + /** + * Clears panel data if viewing avatar info for first time and sends update data request. + */ + virtual void onOpen(const LLSD& key); + + /** + * Clears all data received from server. + */ + virtual void resetData(){}; + + /*virtual*/ ~LLPanelProfileTab(); protected: - LLPanelProfileTab(); + LLPanelProfileTab(); + + enum ELoadingState + { + PROFILE_INIT, + PROFILE_LOADING, + PROFILE_LOADED, + }; + + + // mLoading: false: Initial state, can request + // true: Data requested, skip duplicate requests (happens due to LLUI's habit of repeated callbacks) + // mLoaded: false: Initial state, show loading indicator + // true: Data recieved, which comes in a single message, hide indicator + ELoadingState getLoadingState() { return mLoadingState; } + virtual void setLoaded(); + void setApplyProgress(bool started); + + const bool getSelfProfile() const { return mSelfProfile; } - /** - * Scrolls panel to top when viewing avatar info for first time. - */ - void scrollToTop(); +public: + void setIsLoading() { mLoadingState = PROFILE_LOADING; } + void resetLoading() { mLoadingState = PROFILE_INIT; } - virtual void onMapButtonClick(); + bool getStarted() { return mLoadingState != PROFILE_INIT; } + bool getIsLoaded() { return mLoadingState == PROFILE_LOADED; } - virtual void updateButtons(); + virtual bool hasUnsavedChanges() { return false; } + virtual void commitUnsavedChanges() {} private: - LLUUID mAvatarId; + LLUUID mAvatarId; + ELoadingState mLoadingState; + bool mSelfProfile; +}; + +class LLPanelProfilePropertiesProcessorTab + : public LLPanelProfileTab + , public LLAvatarPropertiesObserver +{ +public: + LLPanelProfilePropertiesProcessorTab(); + ~LLPanelProfilePropertiesProcessorTab(); + + /*virtual*/ void setAvatarId(const LLUUID& avatar_id); + + /** + * Processes data received from server via LLAvatarPropertiesObserver. + */ + virtual void processProperties(void* data, EAvatarProcessorType type) = 0; }; #endif // LL_LLPANELAVATAR_H diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 3322e8a3df..3a4fc613b7 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -232,7 +232,7 @@ void LLPanelBlockedList::onFilterEdit(const std::string& search_string) void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names) { if (names.empty() || ids.empty()) return; - LLMute mute(ids[0], names[0].getAccountName(), LLMute::AGENT); + LLMute mute(ids[0], names[0].getUserName(), LLMute::AGENT); LLMuteList::getInstance()->add(mute); showPanelAndSelect(mute.mID); } diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index c0342eef4e..183000ceac 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1,10 +1,10 @@ /** * @file llpanelclassified.cpp - * @brief LLPanelClassified class implementation + * @brief LLPanelClassifiedInfo class implementation * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2021, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,33 +34,21 @@ #include "lldispatcher.h" #include "llfloaterreg.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" #include "llparcel.h" #include "llagent.h" #include "llclassifiedflags.h" -#include "llcommandhandler.h" // for classified HTML detail page click tracking #include "lliconctrl.h" -#include "lllineeditor.h" -#include "llcombobox.h" #include "lltexturectrl.h" -#include "lltexteditor.h" -#include "llviewerparcelmgr.h" #include "llfloaterworldmap.h" #include "llviewergenericmessage.h" // send_generic_message #include "llviewerregion.h" -#include "llviewertexture.h" -#include "lltrans.h" #include "llscrollcontainer.h" -#include "llstatusbar.h" -#include "llviewertexture.h" #include "llcorehttputil.h" -const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ - //static LLPanelClassifiedInfo::panel_list_t LLPanelClassifiedInfo::sAllPanels; +static LLPanelInjector<LLPanelClassifiedInfo> t_panel_panel_classified_info("panel_classified_info"); // "classifiedclickthrough" // strings[0] = classified_id @@ -118,17 +106,8 @@ LLPanelClassifiedInfo::~LLPanelClassifiedInfo() sAllPanels.remove(this); } -// static -LLPanelClassifiedInfo* LLPanelClassifiedInfo::create() -{ - LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo(); - panel->buildFromFile("panel_classified_info.xml"); - return panel; -} - BOOL LLPanelClassifiedInfo::postBuild() { - childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this)); childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this)); childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this)); @@ -144,16 +123,6 @@ BOOL LLPanelClassifiedInfo::postBuild() return TRUE; } -void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("back_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedInfo::setEditClassifiedCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("edit_btn")->setClickedCallback(cb); -} - void LLPanelClassifiedInfo::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { LLPanel::reshape(width, height, called_from_parent); @@ -286,6 +255,8 @@ void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType t getChild<LLUICtrl>("creation_date")->setValue(date_str); setInfoLoaded(true); + + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); } } } @@ -590,588 +561,4 @@ void LLPanelClassifiedInfo::onTeleportClick() } } -void LLPanelClassifiedInfo::onExit() -{ - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); - gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -static const S32 CB_ITEM_MATURE = 0; -static const S32 CB_ITEM_PG = 1; - -LLPanelClassifiedEdit::LLPanelClassifiedEdit() - : LLPanelClassifiedInfo() - , mIsNew(false) - , mIsNewWithErrors(false) - , mCanClose(false) - , mPublishFloater(NULL) -{ -} - -LLPanelClassifiedEdit::~LLPanelClassifiedEdit() -{ -} - -//static -LLPanelClassifiedEdit* LLPanelClassifiedEdit::create() -{ - LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit(); - panel->buildFromFile("panel_edit_classified.xml"); - return panel; -} - -BOOL LLPanelClassifiedEdit::postBuild() -{ - LLPanelClassifiedInfo::postBuild(); - - LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon"); - mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon)); - mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon)); - edit_icon->setVisible(false); - - LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name"); - line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - - LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc"); - text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - - LLComboBox* combobox = getChild<LLComboBox>( "category"); - LLClassifiedInfo::cat_map::iterator iter; - for (iter = LLClassifiedInfo::sCategories.begin(); - iter != LLClassifiedInfo::sCategories.end(); - iter++) - { - combobox->add(LLTrans::getString(iter->second)); - } - - combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - - childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - - childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this)); - childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this)); - - mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onTextureSelected, this)); - - return TRUE; -} - -void LLPanelClassifiedEdit::fillIn(const LLSD& key) -{ - setAvatarId(gAgent.getID()); - - if(key.isUndefined()) - { - setPosGlobal(gAgent.getPositionGlobal()); - - LLUUID snapshot_id = LLUUID::null; - std::string desc; - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - - if(parcel) - { - desc = parcel->getDesc(); - snapshot_id = parcel->getSnapshotID(); - } - - std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - region_name = region->getName(); - } - - getChild<LLUICtrl>("classified_name")->setValue(makeClassifiedName()); - getChild<LLUICtrl>("classified_desc")->setValue(desc); - setSnapshotId(snapshot_id); - setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); - // server will set valid parcel id - setParcelId(LLUUID::null); - } - else - { - setClassifiedId(key["classified_id"]); - setClassifiedName(key["name"]); - setDescription(key["desc"]); - setSnapshotId(key["snapshot_id"]); - setCategory((U32)key["category"].asInteger()); - setContentType((U32)key["content_type"].asInteger()); - setClassifiedLocation(key["location_text"]); - getChild<LLUICtrl>("auto_renew")->setValue(key["auto_renew"]); - getChild<LLUICtrl>("price_for_listing")->setValue(key["price_for_listing"].asInteger()); - } -} - -void LLPanelClassifiedEdit::onOpen(const LLSD& key) -{ - mIsNew = key.isUndefined(); - - scrollToTop(); - - // classified is not created yet - bool is_new = isNew() || isNewWithErrors(); - - if(is_new) - { - resetData(); - resetControls(); - - fillIn(key); - - if(isNew()) - { - LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); - } - } - else - { - LLPanelClassifiedInfo::onOpen(key); - } - - std::string save_btn_label = is_new ? getString("publish_label") : getString("save_label"); - getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", save_btn_label); - - enableVerbs(is_new); - enableEditing(is_new); - showEditing(!is_new); - resetDirty(); - setInfoLoaded(false); -} - -void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_CLASSIFIED_INFO == type) - { - LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); - if(c_info && getClassifiedId() == c_info->classified_id) - { - // see LLPanelClassifiedEdit::sendUpdate() for notes - mIsNewWithErrors = false; - // for just created classified - panel will probably be closed when we get here. - if(!getVisible()) - { - return; - } - - enableEditing(true); - - setClassifiedName(c_info->name); - setDescription(c_info->description); - setSnapshotId(c_info->snapshot_id); - setParcelId(c_info->parcel_id); - setPosGlobal(c_info->pos_global); - - setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); - // *HACK see LLPanelClassifiedEdit::sendUpdate() - setCategory(c_info->category - 1); - - bool mature = is_cf_mature(c_info->flags); - bool auto_renew = is_cf_auto_renew(c_info->flags); - - setContentType(mature ? CB_ITEM_MATURE : CB_ITEM_PG); - getChild<LLUICtrl>("auto_renew")->setValue(auto_renew); - getChild<LLUICtrl>("price_for_listing")->setValue(c_info->price_for_listing); - getChildView("price_for_listing")->setEnabled(isNew()); - - resetDirty(); - setInfoLoaded(true); - enableVerbs(false); - - // for just created classified - in case user opened edit panel before processProperties() callback - getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", getString("save_label")); - } - } -} - -BOOL LLPanelClassifiedEdit::isDirty() const -{ - if(mIsNew) - { - return TRUE; - } - - BOOL dirty = false; - - dirty |= LLPanelClassifiedInfo::isDirty(); - dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty(); - dirty |= getChild<LLUICtrl>("classified_name")->isDirty(); - dirty |= getChild<LLUICtrl>("classified_desc")->isDirty(); - dirty |= getChild<LLUICtrl>("category")->isDirty(); - dirty |= getChild<LLUICtrl>("content_type")->isDirty(); - dirty |= getChild<LLUICtrl>("auto_renew")->isDirty(); - dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty(); - - return dirty; -} - -void LLPanelClassifiedEdit::resetDirty() -{ - LLPanelClassifiedInfo::resetDirty(); - getChild<LLUICtrl>("classified_snapshot")->resetDirty(); - getChild<LLUICtrl>("classified_name")->resetDirty(); - - LLTextEditor* desc = getChild<LLTextEditor>("classified_desc"); - // call blockUndo() to really reset dirty(and make isDirty work as intended) - desc->blockUndo(); - desc->resetDirty(); - - getChild<LLUICtrl>("category")->resetDirty(); - getChild<LLUICtrl>("content_type")->resetDirty(); - getChild<LLUICtrl>("auto_renew")->resetDirty(); - getChild<LLUICtrl>("price_for_listing")->resetDirty(); -} - -void LLPanelClassifiedEdit::setSaveCallback(const commit_signal_t::slot_type& cb) -{ - mSaveButtonClickedSignal.connect(cb); -} - -void LLPanelClassifiedEdit::setCancelCallback(const commit_signal_t::slot_type& cb) -{ - getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedEdit::resetControls() -{ - LLPanelClassifiedInfo::resetControls(); - - getChild<LLComboBox>("category")->setCurrentByIndex(0); - getChild<LLComboBox>("content_type")->setCurrentByIndex(0); - getChild<LLUICtrl>("auto_renew")->setValue(false); - getChild<LLUICtrl>("price_for_listing")->setValue(MINIMUM_PRICE_FOR_LISTING); - getChildView("price_for_listing")->setEnabled(TRUE); -} - -bool LLPanelClassifiedEdit::canClose() -{ - return mCanClose; -} - -void LLPanelClassifiedEdit::draw() -{ - LLPanel::draw(); - - // Need to re-stretch on every draw because LLTextureCtrl::onSelectCallback - // does not trigger callbacks when user navigates through images. - stretchSnapshot(); -} - -void LLPanelClassifiedEdit::stretchSnapshot() -{ - LLPanelClassifiedInfo::stretchSnapshot(); - - getChild<LLUICtrl>("edit_icon")->setShape(mSnapshotCtrl->getRect()); -} - -U32 LLPanelClassifiedEdit::getContentType() -{ - LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); - return ct_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setContentType(U32 content_type) -{ - LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); - ct_cb->setCurrentByIndex(content_type); - ct_cb->resetDirty(); -} - -bool LLPanelClassifiedEdit::getAutoRenew() -{ - return getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); -} - -void LLPanelClassifiedEdit::sendUpdate() -{ - LLAvatarClassifiedInfo c_data; - - if(getClassifiedId().isNull()) - { - setClassifiedId(LLUUID::generateNewID()); - } - - c_data.agent_id = gAgent.getID(); - c_data.classified_id = getClassifiedId(); - // *HACK - // Categories on server start with 1 while combo-box index starts with 0 - c_data.category = getCategory() + 1; - c_data.name = getClassifiedName(); - c_data.description = getDescription(); - c_data.parcel_id = getParcelId(); - c_data.snapshot_id = getSnapshotId(); - c_data.pos_global = getPosGlobal(); - c_data.flags = getFlags(); - c_data.price_for_listing = getPriceForListing(); - - LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); - - if(isNew()) - { - // Lets assume there will be some error. - // Successful sendClassifiedInfoUpdate will trigger processProperties and - // let us know there was no error. - mIsNewWithErrors = true; - } -} - -U32 LLPanelClassifiedEdit::getCategory() -{ - LLComboBox* cat_cb = getChild<LLComboBox>("category"); - return cat_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setCategory(U32 category) -{ - LLComboBox* cat_cb = getChild<LLComboBox>("category"); - cat_cb->setCurrentByIndex(category); - cat_cb->resetDirty(); -} - -U8 LLPanelClassifiedEdit::getFlags() -{ - bool auto_renew = getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); - - LLComboBox* content_cb = getChild<LLComboBox>("content_type"); - bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE; - - return pack_classified_flags_request(auto_renew, false, mature, false); -} - -void LLPanelClassifiedEdit::enableVerbs(bool enable) -{ - getChildView("save_changes_btn")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::enableEditing(bool enable) -{ - getChildView("classified_snapshot")->setEnabled(enable); - getChildView("classified_name")->setEnabled(enable); - getChildView("classified_desc")->setEnabled(enable); - getChildView("set_to_curr_location_btn")->setEnabled(enable); - getChildView("category")->setEnabled(enable); - getChildView("content_type")->setEnabled(enable); - getChildView("price_for_listing")->setEnabled(enable); - getChildView("auto_renew")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::showEditing(bool show) -{ - getChildView("price_for_listing_label")->setVisible( show); - getChildView("price_for_listing")->setVisible( show); -} - -std::string LLPanelClassifiedEdit::makeClassifiedName() -{ - std::string name; - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if(parcel) - { - name = parcel->getName(); - } - - if(!name.empty()) - { - return name; - } - - LLViewerRegion* region = gAgent.getRegion(); - if(region) - { - name = region->getName(); - } - - return name; -} - -S32 LLPanelClassifiedEdit::getPriceForListing() -{ - return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPanelClassifiedEdit::setPriceForListing(S32 price) -{ - getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -void LLPanelClassifiedEdit::onSetLocationClick() -{ - setPosGlobal(gAgent.getPositionGlobal()); - setParcelId(LLUUID::null); - - std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - region_name = region->getName(); - } - - setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); - - // mark classified as dirty - setValue(LLSD()); - - onChange(); -} - -void LLPanelClassifiedEdit::onChange() -{ - enableVerbs(isDirty()); -} - -void LLPanelClassifiedEdit::onSaveClick() -{ - mCanClose = false; - - if(!isValidName()) - { - notifyInvalidName(); - return; - } - if(isNew() || isNewWithErrors()) - { - if(gStatusBar->getBalance() < getPriceForListing()) - { - LLNotificationsUtil::add("ClassifiedInsufficientFunds"); - return; - } - - mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( - "publish_classified", LLSD()); - - if(!mPublishFloater) - { - mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( - "publish_classified", LLSD()); - - mPublishFloater->setPublishClickedCallback(boost::bind - (&LLPanelClassifiedEdit::onPublishFloaterPublishClicked, this)); - } - - // set spinner value before it has focus or value wont be set - mPublishFloater->setPrice(getPriceForListing()); - mPublishFloater->openFloater(mPublishFloater->getKey()); - mPublishFloater->center(); - } - else - { - doSave(); - } -} - -void LLPanelClassifiedEdit::doSave() -{ - mCanClose = true; - sendUpdate(); - resetDirty(); - - mSaveButtonClickedSignal(this, LLSD()); -} - -void LLPanelClassifiedEdit::onPublishFloaterPublishClicked() -{ - setPriceForListing(mPublishFloater->getPrice()); - - doSave(); -} - -std::string LLPanelClassifiedEdit::getLocationNotice() -{ - static std::string location_notice = getString("location_notice"); - return location_notice; -} - -bool LLPanelClassifiedEdit::isValidName() -{ - std::string name = getClassifiedName(); - if (name.empty()) - { - return false; - } - if (!isalnum(name[0])) - { - return false; - } - - return true; -} - -void LLPanelClassifiedEdit::notifyInvalidName() -{ - std::string name = getClassifiedName(); - if (name.empty()) - { - LLNotificationsUtil::add("BlankClassifiedName"); - } - else if (!isalnum(name[0])) - { - LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); - } -} - -void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) -{ - ctrl->setVisible(TRUE); -} - -void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) -{ - ctrl->setVisible(FALSE); -} - -void LLPanelClassifiedEdit::onTextureSelected() -{ - setSnapshotId(mSnapshotCtrl->getValue().asUUID()); - onChange(); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) - : LLFloater(key) -{ -} - -LLPublishClassifiedFloater::~LLPublishClassifiedFloater() -{ -} - -BOOL LLPublishClassifiedFloater::postBuild() -{ - LLFloater::postBuild(); - - childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); - childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); - - return TRUE; -} - -void LLPublishClassifiedFloater::setPrice(S32 price) -{ - getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -S32 LLPublishClassifiedFloater::getPrice() -{ - return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) -{ - getChild<LLButton>("publish_btn")->setClickedCallback(cb); -} - -void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) -{ - getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - //EOF diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index b292782615..471becd0f7 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -1,10 +1,10 @@ /** * @file llpanelclassified.h - * @brief LLPanelClassified class definition + * @brief LLPanelClassifiedInfo class definition * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2021, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,39 +35,16 @@ #include "llfloater.h" #include "llpanel.h" #include "llrect.h" -#include "lluuid.h" -#include "v3dmath.h" -#include "llcoros.h" -#include "lleventcoro.h" class LLScrollContainer; class LLTextureCtrl; -class LLUICtrl; - -class LLPublishClassifiedFloater : public LLFloater -{ -public: - LLPublishClassifiedFloater(const LLSD& key); - virtual ~LLPublishClassifiedFloater(); - - /*virtual*/ BOOL postBuild(); - - void setPrice(S32 price); - S32 getPrice(); - - void setPublishClickedCallback(const commit_signal_t::slot_type& cb); - void setCancelClickedCallback(const commit_signal_t::slot_type& cb); - -private: -}; class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver { LOG_CLASS(LLPanelClassifiedInfo); public: - static LLPanelClassifiedInfo* create(); - + LLPanelClassifiedInfo(); virtual ~LLPanelClassifiedInfo(); /*virtual*/ void onOpen(const LLSD& key); @@ -135,18 +112,12 @@ public: const LLVector3d& global_pos, const std::string& sim_name); - void setExitCallback(const commit_callback_t& cb); - - void setEditClassifiedCallback(const commit_callback_t& cb); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); /*virtual*/ void draw(); protected: - LLPanelClassifiedInfo(); - virtual void resetData(); virtual void resetControls(); @@ -165,7 +136,6 @@ protected: void onMapClick(); void onTeleportClick(); - void onExit(); bool mSnapshotStreched; LLRect mSnapshotRect; @@ -202,100 +172,4 @@ private: static panel_list_t sAllPanels; }; -class LLPanelClassifiedEdit : public LLPanelClassifiedInfo -{ - LOG_CLASS(LLPanelClassifiedEdit); -public: - - static LLPanelClassifiedEdit* create(); - - virtual ~LLPanelClassifiedEdit(); - - /*virtual*/ BOOL postBuild(); - - void fillIn(const LLSD& key); - - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - /*virtual*/ BOOL isDirty() const; - - /*virtual*/ void resetDirty(); - - void setSaveCallback(const commit_signal_t::slot_type& cb); - - void setCancelCallback(const commit_signal_t::slot_type& cb); - - /*virtual*/ void resetControls(); - - bool isNew() { return mIsNew; } - - bool isNewWithErrors() { return mIsNewWithErrors; } - - bool canClose(); - - void draw(); - - void stretchSnapshot(); - - U32 getCategory(); - - void setCategory(U32 category); - - U32 getContentType(); - - void setContentType(U32 content_type); - - bool getAutoRenew(); - - S32 getPriceForListing(); - -protected: - - LLPanelClassifiedEdit(); - - void sendUpdate(); - - void enableVerbs(bool enable); - - void enableEditing(bool enable); - - void showEditing(bool show); - - std::string makeClassifiedName(); - - void setPriceForListing(S32 price); - - U8 getFlags(); - - std::string getLocationNotice(); - - bool isValidName(); - - void notifyInvalidName(); - - void onSetLocationClick(); - void onChange(); - void onSaveClick(); - - void doSave(); - - void onPublishFloaterPublishClicked(); - - void onTexturePickerMouseEnter(LLUICtrl* ctrl); - void onTexturePickerMouseLeave(LLUICtrl* ctrl); - - void onTextureSelected(); - -private: - bool mIsNew; - bool mIsNewWithErrors; - bool mCanClose; - - LLPublishClassifiedFloater* mPublishFloater; - - commit_signal_t mSaveButtonClickedSignal; -}; - #endif // LL_LLPANELCLASSIFIED_H diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index be11a4a9f3..ea10aa75ae 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1308,7 +1308,9 @@ void LLPanelEditWearable::changeCamera(U8 subpart) gMorphView->setCameraOffset( subpart_entry->mCameraOffset ); if (gSavedSettings.getBOOL("AppearanceCameraMovement")) { - gMorphView->updateCamera(); + // Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE + gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating()); + gMorphView->updateCamera(); } } diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h index 9d5afd1a6a..11111f2a2e 100644 --- a/indra/newview/llpanelexperiences.h +++ b/indra/newview/llpanelexperiences.h @@ -29,7 +29,6 @@ #include "llaccordionctrltab.h" #include "llflatlistview.h" -#include "llpanelavatar.h" class LLExperienceItem; class LLPanelProfile; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 71657239a6..178aba11a3 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@ #include "llfontgl.h" // project includes +#include "llagent.h" #include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -45,10 +46,18 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" // gInventory +#include "llinventorymodelbackgroundfetch.h" +#include "llfloatermediasettings.h" +#include "llfloaterreg.h" #include "lllineeditor.h" #include "llmaterialmgr.h" +#include "llmediactrl.h" #include "llmediaentry.h" +#include "llmenubutton.h" #include "llnotificationsutil.h" +#include "llpanelcontents.h" #include "llradiogroup.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -57,6 +66,8 @@ #include "lltexturectrl.h" #include "lltextureentry.h" #include "lltooldraganddrop.h" +#include "lltoolface.h" +#include "lltoolmgr.h" #include "lltrans.h" #include "llui.h" #include "llviewercontrol.h" @@ -92,10 +103,9 @@ std::string USE_TEXTURE; LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit() { - LLComboBox* combobox_matmedia = getChild<LLComboBox>("combobox matmedia"); LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); - LLRender::eTexIndex channel_to_edit = (combobox_matmedia && combobox_matmedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? + LLRender::eTexIndex channel_to_edit = (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? (radio_mat_type ? (LLRender::eTexIndex)radio_mat_type->getSelectedIndex() : LLRender::DIFFUSE_MAP) : LLRender::DIFFUSE_MAP; channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit; @@ -154,6 +164,8 @@ BOOL LLPanelFace::postBuild() childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this); childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this); childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this); + childSetCommitCallback("add_media", &LLPanelFace::onClickBtnAddMedia, this); + childSetCommitCallback("delete_media", &LLPanelFace::onClickBtnDeleteMedia, this); childSetAction("button align",&LLPanelFace::onClickAutoFix,this); childSetAction("button align textures", &LLPanelFace::onAlignTexture, this); @@ -165,7 +177,6 @@ BOOL LLPanelFace::postBuild() LLColorSwatchCtrl* mShinyColorSwatch; LLComboBox* mComboTexGen; - LLComboBox* mComboMatMedia; LLCheckBoxCtrl *mCheckFullbright; @@ -298,7 +309,12 @@ BOOL LLPanelFace::postBuild() { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - + + mMenuClipboardColor = getChild<LLMenuButton>("clipboard_color_params_btn"); + mMenuClipboardTexture = getChild<LLMenuButton>("clipboard_texture_params_btn"); + + mTitleMedia = getChild<LLMediaCtrl>("title_media"); + mTitleMediaText = getChild<LLTextBox>("media_info"); clearCtrls(); @@ -307,17 +323,33 @@ BOOL LLPanelFace::postBuild() LLPanelFace::LLPanelFace() : LLPanel(), - mIsAlpha(false) + mIsAlpha(false), + mComboMatMedia(NULL), + mTitleMedia(NULL), + mTitleMediaText(NULL), + mNeedMediaTitle(true) { - USE_TEXTURE = LLTrans::getString("use_texture"); + USE_TEXTURE = LLTrans::getString("use_texture"); + mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2)); } - LLPanelFace::~LLPanelFace() { - // Children all cleaned up by default view destructor. + unloadMedia(); } +void LLPanelFace::draw() +{ + updateCopyTexButton(); + + // grab media name/title and update the UI widget + // Todo: move it, it's preferable not to update + // labels inside draw + updateMediaTitle(); + + LLPanel::draw(); +} void LLPanelFace::sendTexture() { @@ -806,21 +838,20 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); // only turn on auto-adjust button if there is a media renderer and the media is loaded - getChildView("button align")->setEnabled(editable); + childSetEnabled("button align", editable); - LLComboBox* combobox_matmedia = getChild<LLComboBox>("combobox matmedia"); - if (combobox_matmedia) + if (mComboMatMedia) { - if (combobox_matmedia->getCurrentIndex() < MATMEDIA_MATERIAL) + if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL) { - combobox_matmedia->selectNthItem(MATMEDIA_MATERIAL); + mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); } + mComboMatMedia->setEnabled(editable); } else { LL_WARNS() << "failed getChild for 'combobox matmedia'" << LL_ENDL; } - getChildView("combobox matmedia")->setEnabled(editable); LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); if(radio_mat_type) @@ -829,7 +860,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { radio_mat_type->selectNthItem(MATTYPE_DIFFUSE); } - } else { @@ -858,22 +888,22 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { getChildView("color label")->setEnabled(editable); } - LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); + LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("colorswatch"); LLColor4 color = LLColor4::white; bool identical_color = false; - if(mColorSwatch) + if(color_swatch) { LLSelectedTE::getColor(color, identical_color); - LLColor4 prev_color = mColorSwatch->get(); + LLColor4 prev_color = color_swatch->get(); - mColorSwatch->setOriginal(color); - mColorSwatch->set(color, force_set_values || (prev_color != color) || !editable); + color_swatch->setOriginal(color); + color_swatch->set(color, force_set_values || (prev_color != color) || !editable); - mColorSwatch->setValid(editable); - mColorSwatch->setEnabled( editable ); - mColorSwatch->setCanApplyImmediately( editable ); + color_swatch->setValid(editable); + color_swatch->setEnabled( editable ); + color_swatch->setCanApplyImmediately( editable ); } // Color transparency @@ -1356,7 +1386,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) BOOL identical_repeats = true; F32 repeats = 1.0f; - U32 material_type = (combobox_matmedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? radio_mat_type->getSelectedIndex() : MATTYPE_DIFFUSE; + U32 material_type = (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? radio_mat_type->getSelectedIndex() : MATTYPE_DIFFUSE; LLSelectMgr::getInstance()->setTextureChannel(LLRender::eTexIndex(material_type)); switch (material_type) @@ -1508,6 +1538,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } } + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (selected_count == 1); + mMenuClipboardColor->setEnabled(editable && single_volume); // Set variable values for numeric expressions LLCalc* calcp = LLCalc::getInstance(); @@ -1568,12 +1601,772 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } +void LLPanelFace::updateCopyTexButton() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify() + && !objectp->isPermanentEnforced() && !objectp->isInventoryPending() + && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)); + std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options"); + mMenuClipboardTexture->setToolTip(tooltip); + +} + void LLPanelFace::refresh() { LL_DEBUGS("Materials") << LL_ENDL; getState(); } +void LLPanelFace::refreshMedia() +{ + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* first_object = selected_objects->getFirstObject(); + + if (!(first_object + && first_object->getPCode() == LL_PCODE_VOLUME + && first_object->permModify() + )) + { + getChildView("add_media")->setEnabled(FALSE); + mTitleMediaText->clear(); + clearMediaSettings(); + return; + } + + std::string url = first_object->getRegion()->getCapability("ObjectMedia"); + bool has_media_capability = (!url.empty()); + + if (!has_media_capability) + { + getChildView("add_media")->setEnabled(FALSE); + LL_WARNS("LLFloaterToolsMedia") << "Media not enabled (no capability) in this region!" << LL_ENDL; + clearMediaSettings(); + return; + } + + BOOL is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) + || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced(); + bool editable = is_nonpermanent_enforced && (first_object->permModify() || selectedMediaEditable()); + + // Check modify permissions and whether any selected objects are in + // the process of being fetched. If they are, then we're not editable + if (editable) + { + LLObjectSelection::iterator iter = selected_objects->begin(); + LLObjectSelection::iterator end = selected_objects->end(); + for (; iter != end; ++iter) + { + LLSelectNode* node = *iter; + LLVOVolume* object = dynamic_cast<LLVOVolume*>(node->getObject()); + if (NULL != object) + { + if (!object->permModify()) + { + LL_INFOS("LLFloaterToolsMedia") + << "Selection not editable due to lack of modify permissions on object id " + << object->getID() << LL_ENDL; + + editable = false; + break; + } + } + } + } + + // Media settings + bool bool_has_media = false; + struct media_functor : public LLSelectedTEGetFunctor<bool> + { + bool get(LLViewerObject* object, S32 face) + { + LLTextureEntry *te = object->getTE(face); + if (te) + { + return te->hasMedia(); + } + return false; + } + } func; + + + // check if all faces have media(or, all dont have media) + LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue(&func, bool_has_media); + + const LLMediaEntry default_media_data; + + struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry> + { + functor_getter_media_data(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + LLMediaEntry get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return *(object->getTE(face)->getMediaData()); + return mMediaEntry; + }; + + const LLMediaEntry& mMediaEntry; + + } func_media_data(default_media_data); + + LLMediaEntry media_data_get; + LLFloaterMediaSettings::getInstance()->mMultipleMedia = !(selected_objects->getSelectedTEValue(&func_media_data, media_data_get)); + + std::string multi_media_info_str = LLTrans::getString("Multiple Media"); + std::string media_title = ""; + // update UI depending on whether "object" (prim or face) has media + // and whether or not you are allowed to edit it. + + getChildView("add_media")->setEnabled(editable); + // IF all the faces have media (or all dont have media) + if (LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo) + { + // TODO: get media title and set it. + mTitleMediaText->clear(); + // if identical is set, all faces are same (whether all empty or has the same media) + if (!(LLFloaterMediaSettings::getInstance()->mMultipleMedia)) + { + // Media data is valid + if (media_data_get != default_media_data) + { + // initial media title is the media URL (until we get the name) + media_title = media_data_get.getHomeURL(); + } + // else all faces might be empty. + } + else // there' re Different Medias' been set on on the faces. + { + media_title = multi_media_info_str; + } + + getChildView("delete_media")->setEnabled(bool_has_media && editable); + // TODO: display a list of all media on the face - use 'identical' flag + } + else // not all face has media but at least one does. + { + // seleted faces have not identical value + LLFloaterMediaSettings::getInstance()->mMultipleValidMedia = selected_objects->isMultipleTEValue(&func_media_data, default_media_data); + + if (LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) + { + media_title = multi_media_info_str; + } + else + { + // Media data is valid + if (media_data_get != default_media_data) + { + // initial media title is the media URL (until we get the name) + media_title = media_data_get.getHomeURL(); + } + } + + getChildView("delete_media")->setEnabled(TRUE); + } + + U32 materials_media = mComboMatMedia->getCurrentIndex(); + if (materials_media == MATMEDIA_MEDIA) + { + // currently displaying media info, navigateTo and update title + navigateToTitleMedia(media_title); + } + else + { + // Media can be heavy, don't keep it around + // MAC specific: MAC doesn't support setVolume(0) so if not + // unloaded, it might keep playing audio until user closes editor + unloadMedia(); + mNeedMediaTitle = false; + } + + mTitleMediaText->setText(media_title); + + // load values for media settings + updateMediaSettings(); + + LLFloaterMediaSettings::initValues(mMediaSettings, editable); +} + +void LLPanelFace::unloadMedia() +{ + // destroy media source used to grab media title + if (mTitleMedia) + mTitleMedia->unloadMediaSource(); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLPanelFace::navigateToTitleMedia( const std::string url ) +{ + std::string multi_media_info_str = LLTrans::getString("Multiple Media"); + if (url.empty() || multi_media_info_str == url) + { + // nothing to show + mNeedMediaTitle = false; + } + else if (mTitleMedia) + { + LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); + // check if url changed or if we need a new media source + if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL) + { + mTitleMedia->navigateTo( url ); + + LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mTitleMedia->getTextureID()); + if (impl) + { + // if it's a page with a movie, we don't want to hear it + impl->setVolume(0); + }; + } + + // flag that we need to update the title (even if no request were made) + mNeedMediaTitle = true; + } +} + +bool LLPanelFace::selectedMediaEditable() +{ + U32 owner_mask_on; + U32 owner_mask_off; + U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, + &owner_mask_on, &owner_mask_off); + U32 group_mask_on; + U32 group_mask_off; + U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP, + &group_mask_on, &group_mask_off); + U32 everyone_mask_on; + U32 everyone_mask_off; + S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE, + &everyone_mask_on, &everyone_mask_off); + + bool selected_Media_editable = false; + + // if perms we got back are valid + if (valid_owner_perms && + valid_group_perms && + valid_everyone_perms) + { + + if ((owner_mask_on & PERM_MODIFY) || + (group_mask_on & PERM_MODIFY) || + (everyone_mask_on & PERM_MODIFY)) + { + selected_Media_editable = true; + } + else + // user is NOT allowed to press the RESET button + { + selected_Media_editable = false; + }; + }; + + return selected_Media_editable; +} + +void LLPanelFace::clearMediaSettings() +{ + LLFloaterMediaSettings::clearValues(false); +} + +void LLPanelFace::updateMediaSettings() +{ + bool identical(false); + std::string base_key(""); + std::string value_str(""); + int value_int = 0; + bool value_bool = false; + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + // TODO: (CP) refactor this using something clever or boost or both !! + + const LLMediaEntry default_media_data; + + // controls + U8 value_u8 = default_media_data.getControls(); + struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 > + { + functor_getter_controls(const LLMediaEntry &entry) : mMediaEntry(entry) {} + + U8 get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getControls(); + return mMediaEntry.getControls(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_controls(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_controls, value_u8); + base_key = std::string(LLMediaEntry::CONTROLS_KEY); + mMediaSettings[base_key] = value_u8; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // First click (formerly left click) + value_bool = default_media_data.getFirstClickInteract(); + struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool > + { + functor_getter_first_click(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getFirstClickInteract(); + return mMediaEntry.getFirstClickInteract(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_first_click(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_first_click, value_bool); + base_key = std::string(LLMediaEntry::FIRST_CLICK_INTERACT_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Home URL + value_str = default_media_data.getHomeURL(); + struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string > + { + functor_getter_home_url(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + std::string get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getHomeURL(); + return mMediaEntry.getHomeURL(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_home_url(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_home_url, value_str); + base_key = std::string(LLMediaEntry::HOME_URL_KEY); + mMediaSettings[base_key] = value_str; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Current URL + value_str = default_media_data.getCurrentURL(); + struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string > + { + functor_getter_current_url(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + std::string get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getCurrentURL(); + return mMediaEntry.getCurrentURL(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_current_url(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_current_url, value_str); + base_key = std::string(LLMediaEntry::CURRENT_URL_KEY); + mMediaSettings[base_key] = value_str; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Auto zoom + value_bool = default_media_data.getAutoZoom(); + struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool > + { + + functor_getter_auto_zoom(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getAutoZoom(); + return mMediaEntry.getAutoZoom(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_auto_zoom(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_auto_zoom, value_bool); + base_key = std::string(LLMediaEntry::AUTO_ZOOM_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Auto play + //value_bool = default_media_data.getAutoPlay(); + // set default to auto play TRUE -- angela EXT-5172 + value_bool = true; + struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool > + { + functor_getter_auto_play(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getAutoPlay(); + //return mMediaEntry.getAutoPlay(); set default to auto play TRUE -- angela EXT-5172 + return true; + }; + + const LLMediaEntry &mMediaEntry; + + } func_auto_play(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_auto_play, value_bool); + base_key = std::string(LLMediaEntry::AUTO_PLAY_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + + // Auto scale + // set default to auto scale TRUE -- angela EXT-5172 + //value_bool = default_media_data.getAutoScale(); + value_bool = true; + struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool > + { + functor_getter_auto_scale(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getAutoScale(); + // return mMediaEntry.getAutoScale(); set default to auto scale TRUE -- angela EXT-5172 + return true; + }; + + const LLMediaEntry &mMediaEntry; + + } func_auto_scale(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_auto_scale, value_bool); + base_key = std::string(LLMediaEntry::AUTO_SCALE_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Auto loop + value_bool = default_media_data.getAutoLoop(); + struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool > + { + functor_getter_auto_loop(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getAutoLoop(); + return mMediaEntry.getAutoLoop(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_auto_loop(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_auto_loop, value_bool); + base_key = std::string(LLMediaEntry::AUTO_LOOP_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // width pixels (if not auto scaled) + value_int = default_media_data.getWidthPixels(); + struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int > + { + functor_getter_width_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + int get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getWidthPixels(); + return mMediaEntry.getWidthPixels(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_width_pixels(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_width_pixels, value_int); + base_key = std::string(LLMediaEntry::WIDTH_PIXELS_KEY); + mMediaSettings[base_key] = value_int; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // height pixels (if not auto scaled) + value_int = default_media_data.getHeightPixels(); + struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int > + { + functor_getter_height_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + int get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getHeightPixels(); + return mMediaEntry.getHeightPixels(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_height_pixels(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_height_pixels, value_int); + base_key = std::string(LLMediaEntry::HEIGHT_PIXELS_KEY); + mMediaSettings[base_key] = value_int; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Enable Alt image + value_bool = default_media_data.getAltImageEnable(); + struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool > + { + functor_getter_enable_alt_image(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getAltImageEnable(); + return mMediaEntry.getAltImageEnable(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_enable_alt_image(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_enable_alt_image, value_bool); + base_key = std::string(LLMediaEntry::ALT_IMAGE_ENABLE_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - owner interact + value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER); + struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_owner_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER)); + return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_owner_interact(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_perms_owner_interact, value_bool); + base_key = std::string(LLPanelContents::PERMS_OWNER_INTERACT_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - owner control + value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER); + struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_owner_control(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER)); + return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_owner_control(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_perms_owner_control, value_bool); + base_key = std::string(LLPanelContents::PERMS_OWNER_CONTROL_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - group interact + value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP); + struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_group_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP)); + return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_group_interact(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_perms_group_interact, value_bool); + base_key = std::string(LLPanelContents::PERMS_GROUP_INTERACT_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - group control + value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP); + struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_group_control(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP)); + return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_group_control(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_perms_group_control, value_bool); + base_key = std::string(LLPanelContents::PERMS_GROUP_CONTROL_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - anyone interact + value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE); + struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_anyone_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE)); + return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_anyone_interact(default_media_data); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func_perms_anyone_interact, value_bool); + base_key = std::string(LLPanelContents::PERMS_ANYONE_INTERACT_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // Perms - anyone control + value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE); + struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool > + { + functor_getter_perms_anyone_control(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE)); + return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE); + }; + + const LLMediaEntry &mMediaEntry; + + } func_perms_anyone_control(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_perms_anyone_control, value_bool); + base_key = std::string(LLPanelContents::PERMS_ANYONE_CONTROL_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // security - whitelist enable + value_bool = default_media_data.getWhiteListEnable(); + struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool > + { + functor_getter_whitelist_enable(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + bool get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getWhiteListEnable(); + return mMediaEntry.getWhiteListEnable(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_whitelist_enable(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_whitelist_enable, value_bool); + base_key = std::string(LLMediaEntry::WHITELIST_ENABLE_KEY); + mMediaSettings[base_key] = value_bool; + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; + + // security - whitelist URLs + std::vector<std::string> value_vector_str = default_media_data.getWhiteList(); + struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector<std::string> > + { + functor_getter_whitelist_urls(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + std::vector<std::string> get(LLViewerObject* object, S32 face) + { + if (object) + if (object->getTE(face)) + if (object->getTE(face)->getMediaData()) + return object->getTE(face)->getMediaData()->getWhiteList(); + return mMediaEntry.getWhiteList(); + }; + + const LLMediaEntry &mMediaEntry; + + } func_whitelist_urls(default_media_data); + identical = selected_objects->getSelectedTEValue(&func_whitelist_urls, value_vector_str); + base_key = std::string(LLMediaEntry::WHITELIST_KEY); + mMediaSettings[base_key].clear(); + std::vector< std::string >::iterator iter = value_vector_str.begin(); + while (iter != value_vector_str.end()) + { + std::string white_list_url = *iter; + mMediaSettings[base_key].append(white_list_url); + ++iter; + }; + + mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical; +} + +void LLPanelFace::updateMediaTitle() +{ + // only get the media name if we need it + if (!mNeedMediaTitle) + return; + + // get plugin impl + LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); + if (media_plugin && mTitleMedia->getCurrentNavUrl() == media_plugin->getNavigateURI()) + { + // get the media name (asynchronous - must call repeatedly) + std::string media_title = media_plugin->getMediaName(); + + // only replace the title if what we get contains something + if (!media_title.empty()) + { + // update the UI widget + if (mTitleMediaText) + { + mTitleMediaText->setText(media_title); + + // stop looking for a title when we get one + mNeedMediaTitle = false; + }; + }; + }; +} + // // Static functions // @@ -1632,30 +2425,29 @@ void LLPanelFace::onCommitMaterialsMedia(LLUICtrl* ctrl, void* userdata) self->updateShinyControls(false,true); self->updateBumpyControls(false,true); self->updateUI(); + self->refreshMedia(); } -// static void LLPanelFace::updateVisibility() { - LLComboBox* combo_matmedia = getChild<LLComboBox>("combobox matmedia"); LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); LLComboBox* combo_shininess = getChild<LLComboBox>("combobox shininess"); LLComboBox* combo_bumpiness = getChild<LLComboBox>("combobox bumpiness"); - if (!radio_mat_type || !combo_matmedia || !combo_shininess || !combo_bumpiness) + if (!radio_mat_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness) { LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL; return; } - U32 materials_media = combo_matmedia->getCurrentIndex(); + U32 materials_media = mComboMatMedia->getCurrentIndex(); U32 material_type = radio_mat_type->getSelectedIndex(); - bool show_media = (materials_media == MATMEDIA_MEDIA) && combo_matmedia->getEnabled(); - bool show_texture = (show_media || ((material_type == MATTYPE_DIFFUSE) && combo_matmedia->getEnabled())); - bool show_bumpiness = (!show_media) && (material_type == MATTYPE_NORMAL) && combo_matmedia->getEnabled(); - bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && combo_matmedia->getEnabled(); + bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled(); + bool show_texture = (show_media || ((material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled())); + bool show_bumpiness = (!show_media) && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled(); + bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); getChildView("radio_material_type")->setVisible(!show_media); // Media controls - getChildView("media_info")->setVisible(show_media); + mTitleMediaText->setVisible(show_media); getChildView("add_media")->setVisible(show_media); getChildView("delete_media")->setVisible(show_media); getChildView("button align")->setVisible(show_media); @@ -1787,12 +2579,11 @@ void LLPanelFace::updateShinyControls(bool is_setting_texture, bool mess_with_sh } - LLComboBox* combo_matmedia = getChild<LLComboBox>("combobox matmedia"); LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); - U32 materials_media = combo_matmedia->getCurrentIndex(); + U32 materials_media = mComboMatMedia->getCurrentIndex(); U32 material_type = radio_mat_type->getSelectedIndex(); - bool show_media = (materials_media == MATMEDIA_MEDIA) && combo_matmedia->getEnabled(); - bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && combo_matmedia->getEnabled(); + bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled(); + bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); U32 shiny_value = comboShiny->getCurrentIndex(); bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture getChildView("label glossiness")->setVisible(show_shinyctrls); @@ -1866,11 +2657,10 @@ void LLPanelFace::updateAlphaControls() U32 alpha_value = comboAlphaMode->getCurrentIndex(); bool show_alphactrls = (alpha_value == ALPHAMODE_MASK); // Alpha masking - LLComboBox* combobox_matmedia = getChild<LLComboBox>("combobox matmedia"); U32 mat_media = MATMEDIA_MATERIAL; - if (combobox_matmedia) + if (mComboMatMedia) { - mat_media = combobox_matmedia->getCurrentIndex(); + mat_media = mComboMatMedia->getCurrentIndex(); } U32 mat_type = MATTYPE_DIFFUSE; @@ -2027,6 +2817,77 @@ void LLPanelFace::onSelectNormalTexture(const LLSD& data) sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE); } +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to edit existing media settings on a prim or prim face +// TODO: test if there is media on the item and only allow editing if present +void LLPanelFace::onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*)userdata; + self->refreshMedia(); + LLFloaterReg::showInstance("media_settings"); +} + +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to delete media from a prim or prim face +void LLPanelFace::onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata) +{ + LLNotificationsUtil::add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm); +} + +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to add media to a prim or prim face +void LLPanelFace::onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata) +{ + // check if multiple faces are selected + if (LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) + { + LLPanelFace* self = (LLPanelFace*)userdata; + self->refreshMedia(); + LLNotificationsUtil::add("MultipleFacesSelected", LLSD(), LLSD(), multipleFacesSelectedConfirm); + } + else + { + onClickBtnEditMedia(ctrl, userdata); + } +} + +// static +bool LLPanelFace::deleteMediaConfirm(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch (option) + { + case 0: // "Yes" + LLSelectMgr::getInstance()->selectionSetMedia(0, LLSD()); + if (LLFloaterReg::instanceVisible("media_settings")) + { + LLFloaterReg::hideInstance("media_settings"); + } + break; + + case 1: // "No" + default: + break; + } + return false; +} + +// static +bool LLPanelFace::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch (option) + { + case 0: // "Yes" + LLFloaterReg::showInstance("media_settings"); + break; + case 1: // "No" + default: + break; + } + return false; +} + //static void LLPanelFace::syncOffsetX(LLPanelFace* self, F32 offsetU) { @@ -2404,10 +3265,9 @@ void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata) LLPanelFace* self = (LLPanelFace*) userdata; LLUICtrl* repeats_ctrl = self->getChild<LLUICtrl>("rptctrl"); - LLComboBox* combo_matmedia = self->getChild<LLComboBox>("combobox matmedia"); LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_material_type"); - U32 materials_media = combo_matmedia->getCurrentIndex(); + U32 materials_media = self->mComboMatMedia->getCurrentIndex(); U32 material_type = (materials_media == MATMEDIA_MATERIAL) ? radio_mat_type->getSelectedIndex() : 0; F32 repeats_per_meter = repeats_ctrl->getValue().asReal(); @@ -2538,15 +3398,811 @@ void LLPanelFace::onAlignTexture(void* userdata) self->alignTestureLayer(); } +enum EPasteMode +{ + PASTE_COLOR, + PASTE_TEXTURE +}; + +struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor +{ + LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) : + mPanelFace(panel), mMode(mode) {} + + virtual bool apply(LLViewerObject* objectp, S32 te) + { + switch (mMode) + { + case PASTE_COLOR: + mPanelFace->onPasteColor(objectp, te); + break; + case PASTE_TEXTURE: + mPanelFace->onPasteTexture(objectp, te); + break; + } + return true; + } +private: + LLPanelFace *mPanelFace; + EPasteMode mMode; +}; + +struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor +{ + LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} + virtual bool apply(LLViewerObject* object) + { + object->sendTEUpdate(); + if (mUpdateMedia) + { + LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object); + if (vo && vo->hasMedia()) + { + vo->sendMediaDataUpdate(); + } + } + return true; + } +private: + bool mUpdateMedia; +}; + +struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor +{ + virtual bool apply(LLViewerObject* objectp, S32 te) + { + if (objectp && objectp->getTE(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + const LLMediaEntry *media_data = tep->getMediaData(); + if (media_data) + { + if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) + { + viewer_media_t media_impl = + LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); + if (media_impl) + { + media_impl->navigateHome(); + } + } + } + } + return true; + } +}; + +void LLPanelFace::onCopyColor() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + return; + } + + if (mClipboardParams.has("color")) + { + mClipboardParams["color"].clear(); + } + else + { + mClipboardParams["color"] = LLSD::emptyArray(); + } + + std::map<LLUUID, LLUUID> asset_item_map; + + // a way to resolve situations where source and target have different amount of faces + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + mClipboardParams["color_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + LLSD te_data; + + // asLLSD() includes media + te_data["te"] = tep->asLLSD(); // Note: includes a lot more than just color/alpha/glow + + mClipboardParams["color"].append(te_data); + } + } + } +} + +void LLPanelFace::onPasteColor() +{ + if (!mClipboardParams.has("color")) + { + return; + } + + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + // not supposed to happen + LL_WARNS() << "Failed to paste color due to missing or wrong selection" << LL_ENDL; + return; + } + + bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + LLSD &clipboard = mClipboardParams["color"]; // array + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + S32 compare_tes = num_tes; + + if (face_selection_mode) + { + compare_tes = 0; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + compare_tes++; + } + } + } + + // we can copy if single face was copied in edit face mode or if face count matches + if (!((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) + && compare_tes != clipboard.size()) + { + LLSD notif_args; + if (face_selection_mode) + { + static std::string reason = getString("paste_error_face_selection_mismatch"); + notif_args["REASON"] = reason; + } + else + { + static std::string reason = getString("paste_error_object_face_count_mismatch"); + notif_args["REASON"] = reason; + } + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); -// TODO: I don't know who put these in or what these are for??? -void LLPanelFace::setMediaURL(const std::string& url) + LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(false); + selected_objects->applyToObjects(&sendfunc); +} + +void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te) { + LLSD te_data; + LLSD &clipboard = mClipboardParams["color"]; // array + if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) + { + te_data = *(clipboard.beginArray()); + } + else if (clipboard[te]) + { + te_data = clipboard[te]; + } + else + { + return; + } + + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + if (te_data.has("te")) + { + // Color / Alpha + if (te_data["te"].has("colors")) + { + LLColor4 color = tep->getColor(); + + LLColor4 clip_color; + clip_color.setValue(te_data["te"]["colors"]); + + // Color + color.mV[VRED] = clip_color.mV[VRED]; + color.mV[VGREEN] = clip_color.mV[VGREEN]; + color.mV[VBLUE] = clip_color.mV[VBLUE]; + + // Alpha + color.mV[VALPHA] = clip_color.mV[VALPHA]; + + objectp->setTEColor(te, color); + } + + // Color/fullbright + if (te_data["te"].has("fullbright")) + { + objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger()); + } + + // Glow + if (te_data["te"].has("glow")) + { + objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal()); + } + } + } } -void LLPanelFace::setMediaType(const std::string& mime_type) + +void LLPanelFace::onCopyTexture() { + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + return; + } + + if (mClipboardParams.has("texture")) + { + mClipboardParams["texture"].clear(); + } + else + { + mClipboardParams["texture"] = LLSD::emptyArray(); + } + + std::map<LLUUID, LLUUID> asset_item_map; + + // a way to resolve situations where source and target have different amount of faces + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + mClipboardParams["texture_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + LLSD te_data; + + // asLLSD() includes media + te_data["te"] = tep->asLLSD(); + te_data["te"]["shiny"] = tep->getShiny(); + te_data["te"]["bumpmap"] = tep->getBumpmap(); + te_data["te"]["bumpshiny"] = tep->getBumpShiny(); + te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright(); + + if (te_data["te"].has("imageid")) + { + LLUUID item_id; + LLUUID id = te_data["te"]["imageid"].asUUID(); + bool from_library = get_is_predefined_texture(id); + bool full_perm = from_library; + + if (!full_perm + && objectp->permCopy() + && objectp->permTransfer() + && objectp->permModify()) + { + // If agent created this object and nothing is limiting permissions, mark as full perm + // If agent was granted permission to edit objects owned and created by somebody else, mark full perm + // This check is not perfect since we can't figure out whom textures belong to so this ended up restrictive + std::string creator_app_link; + LLUUID creator_id; + LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link); + full_perm = objectp->mOwnerID == creator_id; + } + + if (id.notNull() && !full_perm) + { + std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id); + if (iter != asset_item_map.end()) + { + item_id = iter->second; + } + else + { + // What this does is simply searches inventory for item with same asset id, + // as result it is Hightly unreliable, leaves little control to user, borderline hack + // but there are little options to preserve permissions - multiple inventory + // items might reference same asset and inventory search is expensive. + bool no_transfer = false; + if (objectp->getInventoryItemByAsset(id)) + { + no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm(); + } + item_id = get_copy_free_item_by_asset_id(id, no_transfer); + // record value to avoid repeating inventory search when possible + asset_item_map[id] = item_id; + } + } + + if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID())) + { + full_perm = true; + from_library = true; + } + + { + te_data["te"]["itemfullperm"] = full_perm; + te_data["te"]["fromlibrary"] = from_library; + + // If full permission object, texture is free to copy, + // but otherwise we need to check inventory and extract permissions + // + // Normally we care only about restrictions for current user and objects + // don't inherit any 'next owner' permissions from texture, so there is + // no need to record item id if full_perm==true + if (!full_perm && !from_library && item_id.notNull()) + { + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (itemp) + { + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + te_data["te"]["imageitemid"] = item_id; + te_data["te"]["itemfullperm"] = itemp->getIsFullPerm(); + if (!itemp->isFinished()) + { + // needed for dropTextureAllFaces + LLInventoryModelBackgroundFetch::instance().start(item_id, false); + } + } + } + } + } + } + + LLMaterialPtr material_ptr = tep->getMaterialParams(); + if (!material_ptr.isNull()) + { + LLSD mat_data; + + mat_data["NormMap"] = material_ptr->getNormalID(); + mat_data["SpecMap"] = material_ptr->getSpecularID(); + + mat_data["NormRepX"] = material_ptr->getNormalRepeatX(); + mat_data["NormRepY"] = material_ptr->getNormalRepeatY(); + mat_data["NormOffX"] = material_ptr->getNormalOffsetX(); + mat_data["NormOffY"] = material_ptr->getNormalOffsetY(); + mat_data["NormRot"] = material_ptr->getNormalRotation(); + + mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX(); + mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY(); + mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX(); + mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY(); + mat_data["SpecRot"] = material_ptr->getSpecularRotation(); + + mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue(); + mat_data["SpecExp"] = material_ptr->getSpecularLightExponent(); + mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity(); + mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff(); + mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode(); + + // Replace no-copy textures, destination texture will get used instead if available + if (mat_data.has("NormMap")) + { + LLUUID id = mat_data["NormMap"].asUUID(); + if (id.notNull() && !get_can_copy_texture(id)) + { + mat_data["NormMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + mat_data["NormMapNoCopy"] = true; + } + + } + if (mat_data.has("SpecMap")) + { + LLUUID id = mat_data["SpecMap"].asUUID(); + if (id.notNull() && !get_can_copy_texture(id)) + { + mat_data["SpecMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + mat_data["SpecMapNoCopy"] = true; + } + + } + + te_data["material"] = mat_data; + } + + mClipboardParams["texture"].append(te_data); + } + } + } } +void LLPanelFace::onPasteTexture() +{ + if (!mClipboardParams.has("texture")) + { + return; + } + + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (!objectp || !node + || objectp->getPCode() != LL_PCODE_VOLUME + || !objectp->permModify() + || objectp->isPermanentEnforced() + || selected_count > 1) + { + // not supposed to happen + LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL; + return; + } + + bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + LLSD &clipboard = mClipboardParams["texture"]; // array + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); + S32 compare_tes = num_tes; + + if (face_selection_mode) + { + compare_tes = 0; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + compare_tes++; + } + } + } + + // we can copy if single face was copied in edit face mode or if face count matches + if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) + && compare_tes != clipboard.size()) + { + LLSD notif_args; + if (face_selection_mode) + { + static std::string reason = getString("paste_error_face_selection_mismatch"); + notif_args["REASON"] = reason; + } + else + { + static std::string reason = getString("paste_error_object_face_count_mismatch"); + notif_args["REASON"] = reason; + } + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + + bool full_perm_object = true; + LLSD::array_const_iterator iter = clipboard.beginArray(); + LLSD::array_const_iterator end = clipboard.endArray(); + for (; iter != end; ++iter) + { + const LLSD& te_data = *iter; + if (te_data.has("te") && te_data["te"].has("imageid")) + { + bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + full_perm_object &= full_perm; + if (!full_perm) + { + if (te_data["te"].has("imageitemid")) + { + LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); + if (item_id.notNull()) + { + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (!itemp) + { + // image might be in object's inventory, but it can be not up to date + LLSD notif_args; + static std::string reason = getString("paste_error_inventory_not_found"); + notif_args["REASON"] = reason; + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + } + } + else + { + // Item was not found on 'copy' stage + // Since this happened at copy, might be better to either show this + // at copy stage or to drop clipboard here + LLSD notif_args; + static std::string reason = getString("paste_error_inventory_not_found"); + notif_args["REASON"] = reason; + LLNotificationsUtil::add("FacePasteFailed", notif_args); + return; + } + } + } + } + + if (!full_perm_object) + { + LLNotificationsUtil::add("FacePasteTexturePermissions"); + } + + LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + + LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); + selected_objects->applyToTEs(&paste_func); + + LLPanelFaceUpdateFunctor sendfunc(true); + selected_objects->applyToObjects(&sendfunc); + + LLPanelFaceNavigateHomeFunctor navigate_home_func; + selected_objects->applyToTEs(&navigate_home_func); +} + +void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) +{ + LLSD te_data; + LLSD &clipboard = mClipboardParams["texture"]; // array + if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) + { + te_data = *(clipboard.beginArray()); + } + else if (clipboard[te]) + { + te_data = clipboard[te]; + } + else + { + return; + } + + LLTextureEntry* tep = objectp->getTE(te); + if (tep) + { + if (te_data.has("te")) + { + // Texture + bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); + bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean(); + if (te_data["te"].has("imageid")) + { + const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id + LLViewerInventoryItem* itemp_res = NULL; + + if (te_data["te"].has("imageitemid")) + { + LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); + if (item_id.notNull()) + { + LLViewerInventoryItem* itemp = gInventory.getItem(item_id); + if (itemp && itemp->isFinished()) + { + // dropTextureAllFaces will fail if incomplete + itemp_res = itemp; + } + else + { + // Theoretically shouldn't happend, but if it does happen, we + // might need to add a notification to user that paste will fail + // since inventory isn't fully loaded + LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL; + } + } + } + // for case when item got removed from inventory after we pressed 'copy' + // or texture got pasted into previous object + if (!itemp_res && !full_perm) + { + // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable. + LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL; + // Todo: fix this, we are often searching same texture multiple times (equal to number of faces) + // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(imageid); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + // Extremely unreliable and perfomance unfriendly. + // But we need this to check permissions and it is how texture control finds items + for (S32 i = 0; i < items.size(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp && itemp->isFinished()) + { + // dropTextureAllFaces will fail if incomplete + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + itemp_res = itemp; + break; // first match + } + } + } + } + + if (itemp_res) + { + if (te == -1) // all faces + { + LLToolDragAndDrop::dropTextureAllFaces(objectp, + itemp_res, + from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + else // one face + { + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + itemp_res, + from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null, + 0); + } + } + // not an inventory item or no complete items + else if (full_perm) + { + // Either library, local or existed as fullperm when user made a copy + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + objectp->setTEImage(U8(te), image); + } + } + + if (te_data["te"].has("bumpmap")) + { + objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger()); + } + if (te_data["te"].has("bumpshiny")) + { + objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger()); + } + if (te_data["te"].has("bumpfullbright")) + { + objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger()); + } + + // Texture map + if (te_data["te"].has("scales") && te_data["te"].has("scalet")) + { + objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal()); + } + if (te_data["te"].has("offsets") && te_data["te"].has("offsett")) + { + objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal()); + } + if (te_data["te"].has("imagerot")) + { + objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal()); + } + + // Media + if (te_data["te"].has("media_flags")) + { + U8 media_flags = te_data["te"]["media_flags"].asInteger(); + objectp->setTEMediaFlags(te, media_flags); + LLVOVolume *vo = dynamic_cast<LLVOVolume*>(objectp); + if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY)) + { + vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/); + } + } + else + { + // Keep media flags on destination unchanged + } + } + + if (te_data.has("material")) + { + LLUUID object_id = objectp->getID(); + + LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + + // Normal + // Replace placeholders with target's + if (te_data["material"].has("NormMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getNormalID(); + if (id.notNull()) + { + te_data["material"]["NormMap"] = id; + } + } + } + LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id); + + // Specular + // Replace placeholders with target's + if (te_data["material"].has("SpecMapNoCopy")) + { + LLMaterialPtr material = tep->getMaterialParams(); + if (material.notNull()) + { + LLUUID id = material->getSpecularID(); + if (id.notNull()) + { + te_data["material"]["SpecMap"] = id; + } + } + } + LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id); + LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id); + LLColor4 spec_color(te_data["material"]["SpecColor"]); + LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); + LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); + LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id); + LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + if (te_data.has("te") && te_data["te"].has("shiny")) + { + objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger()); + } + } + } +} + +void LLPanelFace::menuDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste + if (command == "color_paste") + { + onPasteColor(); + } + else if (command == "texture_paste") + { + onPasteTexture(); + } + // copy + else if (command == "color_copy") + { + onCopyColor(); + } + else if (command == "texture_copy") + { + onCopyTexture(); + } +} + +bool LLPanelFace::menuEnableItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste options + if (command == "color_paste") + { + return mClipboardParams.has("color"); + } + else if (command == "texture_paste") + { + return mClipboardParams.has("texture"); + } + return false; +} + + // static void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 2d57d89a44..44bc442bbb 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,6 +47,8 @@ class LLUICtrl; class LLViewerObject; class LLFloater; class LLMaterialID; +class LLMediaCtrl; +class LLMenuButton; // Represents an edit for use in replicating the op across one or more materials in the selection set. // @@ -97,8 +99,10 @@ public: virtual ~LLPanelFace(); void refresh(); - void setMediaURL(const std::string& url); - void setMediaType(const std::string& mime_type); + void refreshMedia(); + void unloadMedia(); + + /*virtual*/ void draw(); LLMaterialPtr createDefaultMaterial(LLMaterialPtr current_material) { @@ -114,6 +118,12 @@ public: LLRender::eTexIndex getTextureChannelToEdit(); protected: + void navigateToTitleMedia(const std::string url); + bool selectedMediaEditable(); + void clearMediaSettings(); + void updateMediaSettings(); + void updateMediaTitle(); + void getState(); void sendTexture(); // applies and sends texture @@ -128,6 +138,8 @@ protected: void sendMedia(); void alignTestureLayer(); + void updateCopyTexButton(); + // this function is to return TRUE if the drag should succeed. static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); @@ -150,6 +162,9 @@ protected: void onCloseTexturePicker(const LLSD& data); + static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response); + static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response); + // Make UI reflect state of currently selected material (refresh) // and UI mode (e.g. editing normal map v diffuse map) // @@ -194,6 +209,9 @@ protected: static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata); static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata); + static void onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata); + static void onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata); + static void onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata); static void onCommitBump( LLUICtrl* ctrl, void* userdata); static void onCommitTexGen( LLUICtrl* ctrl, void* userdata); static void onCommitShiny( LLUICtrl* ctrl, void* userdata); @@ -205,6 +223,18 @@ protected: static void onClickAutoFix(void*); static void onAlignTexture(void*); +public: // needs to be accessible to selection manager + void onCopyColor(); // records all selected faces + void onPasteColor(); // to specific face + void onPasteColor(LLViewerObject* objectp, S32 te); // to specific face + void onCopyTexture(); + void onPasteTexture(); + void onPasteTexture(LLViewerObject* objectp, S32 te); + +protected: + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); + static F32 valueGlow(LLViewerObject* object, S32 face); @@ -234,6 +264,10 @@ private: F32 getCurrentShinyOffsetU(); F32 getCurrentShinyOffsetV(); + LLComboBox *mComboMatMedia; + LLMediaCtrl *mTitleMedia; + LLTextBox *mTitleMediaText; + // Update visibility of controls to match current UI mode // (e.g. materials vs media editing) // @@ -241,10 +275,6 @@ private: // void updateVisibility(); - // Make material(s) reflect current state of UI (apply edit) - // - void updateMaterial(); - // Hey look everyone, a type-safe alternative to copy and paste! :) // @@ -400,7 +430,10 @@ private: * If agent selects texture which is not allowed to be applied for the currently selected object, * all controls of the floater texture picker which allow to apply the texture will be disabled. */ - void onTextureSelectionChanged(LLInventoryItem* itemp); + void onTextureSelectionChanged(LLInventoryItem* itemp); + + LLMenuButton* mMenuClipboardColor; + LLMenuButton* mMenuClipboardTexture; bool mIsAlpha; @@ -415,7 +448,12 @@ private: * up-arrow on a spinner, and avoids running afoul of its throttle. */ bool mUpdateInFlight; - bool mUpdatePending; + bool mUpdatePending; + + LLSD mClipboardParams; + + LLSD mMediaSettings; + bool mNeedMediaTitle; public: #if defined(DEF_GET_MAT_STATE) diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 389baa86cd..07a8641a92 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,6 +1,6 @@ /** - * @file llpanelavatar.cpp - * @brief LLPanelAvatar and related class implementations + * @file llpanelimcontrolpanel.cpp + * @brief LLPanelIMControlPanel and related class implementations * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp index e7bdc51b4a..9e3fc54477 100644 --- a/indra/newview/llpanellandaudio.cpp +++ b/indra/newview/llpanellandaudio.cpp @@ -97,6 +97,9 @@ BOOL LLPanelLandAudio::postBuild() mCheckAVSoundGroup = getChild<LLCheckBoxCtrl>("group av sound check"); childSetCommitCallback("group av sound check", onCommitAny, this); + mCheckObscureMOAP = getChild<LLCheckBoxCtrl>("obscure_moap"); + childSetCommitCallback("obscure_moap", onCommitAny, this); + return TRUE; } @@ -157,6 +160,9 @@ void LLPanelLandAudio::refresh() mCheckAVSoundGroup->set(parcel->getAllowGroupAVSounds() || parcel->getAllowAnyAVSounds()); // On if "Everyone" is on mCheckAVSoundGroup->setEnabled(can_change_av_sounds && !parcel->getAllowAnyAVSounds()); // Enabled if "Everyone" is off + + mCheckObscureMOAP->set(parcel->getObscureMOAP()); + mCheckObscureMOAP->setEnabled(can_change_media); } } // static @@ -184,6 +190,8 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata) group_av_sound = self->mCheckAVSoundGroup->get(); } + bool obscure_moap = self->mCheckObscureMOAP->get(); + // Remove leading/trailing whitespace (common when copying/pasting) LLStringUtil::trim(music_url); @@ -194,6 +202,7 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata) parcel->setMusicURL(music_url); parcel->setAllowAnyAVSounds(any_av_sound); parcel->setAllowGroupAVSounds(group_av_sound); + parcel->setObscureMOAP(obscure_moap); // Send current parcel data upstream to server LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); diff --git a/indra/newview/llpanellandaudio.h b/indra/newview/llpanellandaudio.h index 7e4fce80e4..b54fe62179 100644 --- a/indra/newview/llpanellandaudio.h +++ b/indra/newview/llpanellandaudio.h @@ -53,6 +53,7 @@ private: LLLineEditor* mMusicURLEdit; LLCheckBoxCtrl* mCheckAVSoundAny; LLCheckBoxCtrl* mCheckAVSoundGroup; + LLCheckBoxCtrl* mCheckObscureMOAP; LLSafeHandle<LLParcelSelection>& mParcel; }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index ce17da3076..c3334605ae 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -29,6 +29,7 @@ #include "llpanellandmarks.h" #include "llbutton.h" +#include "llfloaterprofile.h" #include "llfloaterreg.h" #include "llnotificationsutil.h" #include "llsdutil.h" @@ -1003,17 +1004,6 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold return can_be_modified; } -void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params) -{ - pick_panel->setVisible(FALSE); - owner->removeChild(pick_panel); - //we need remove observer to avoid processParcelInfo in the future. - LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this); - - delete pick_panel; - pick_panel = NULL; -} - bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data , EAcceptance* accept) { *accept = ACCEPT_NO; @@ -1080,49 +1070,21 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, LLInventoryItem* inv_item, const LLParcelData& parcel_data) { - LLPanelPickEdit* panel_pick = LLPanelPickEdit::create(); LLVector3d landmark_global_pos; landmark->getGlobalPos(landmark_global_pos); - // let's toggle pick panel into panel places - LLPanel* panel_places = NULL; - LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("places"); - if (floaterp) - { - panel_places = floaterp->findChild<LLPanel>("main_panel"); - } - - if (!panel_places) - { - llassert(NULL != panel_places); - return; - } - panel_places->addChild(panel_pick); - LLRect paren_rect(panel_places->getRect()); - panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE); - panel_pick->setRect(paren_rect); - panel_pick->onOpen(LLSD()); - LLPickData data; data.pos_global = landmark_global_pos; data.name = inv_item->getName(); data.desc = inv_item->getDescription(); data.snapshot_id = parcel_data.snapshot_id; data.parcel_id = parcel_data.parcel_id; - panel_pick->setPickData(&data); - - LLSD params; - params["parcel_id"] = parcel_data.parcel_id; - /* set exit callback to get back onto panel places - in callback we will make cleaning up( delete pick_panel instance, - remove landmark panel from observer list - */ - panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, - panel_pick, panel_places,params)); - panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, - panel_pick, panel_places,params)); - panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, - panel_pick, panel_places,params)); + + LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgentID))); + if (profile_floater) + { + profile_floater->createPick(data); + } } void LLLandmarksPanel::doCreatePick(LLLandmark* landmark, const LLUUID &item_id) diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index d7408269b5..16f3a5dc24 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -34,7 +34,6 @@ #include "llinventorymodel.h" #include "lllandmarklist.h" #include "llpanelplacestab.h" -#include "llpanelpick.h" #include "llremoteparcelrequest.h" class LLAccordionCtrlTab; @@ -136,7 +135,6 @@ private: * For now it checks cut/rename/delete/paste actions. */ bool canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const; - void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params); /** * Landmark actions callbacks. Fire when a landmark is loaded from the list. diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp deleted file mode 100644 index 55e4ffff5e..0000000000 --- a/indra/newview/llpanelme.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file llpanelme.cpp - * @brief Side tray "Me" (My Profile) panel - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelme.h" - -// Viewer includes -#include "llpanelprofile.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llfirstuse.h" -#include "llfloaterreg.h" -#include "llhints.h" -#include "llviewercontrol.h" - -// Linden libraries -#include "llavatarnamecache.h" // IDEVO -#include "lliconctrl.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" // IDEVO -#include "lltabcontainer.h" -#include "lltexturectrl.h" - -static LLPanelInjector<LLPanelMe> t_panel_me_profile("panel_me"); - -LLPanelMe::LLPanelMe(void) - : LLPanelProfile() -{ - setAvatarId(gAgent.getID()); -} - -BOOL LLPanelMe::postBuild() -{ - LLPanelProfile::postBuild(); - - return TRUE; -} - -void LLPanelMe::onOpen(const LLSD& key) -{ - LLPanelProfile::onOpen(key); -} diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 9730f0f16d..e1818cc68b 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -98,9 +98,6 @@ BOOL LLPanelMediaSettingsGeneral::postBuild() childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this); childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this); - // interrogates controls and updates widgets as required - updateMediaPreview(); - return true; } @@ -313,9 +310,6 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); }; }; - - // interrogates controls and updates widgets as required - self->updateMediaPreview(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 64f1fc9b90..0bfc1297d3 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -46,6 +46,7 @@ #include "llcombobox.h" #include "llfocusmgr.h" #include "llmanipscale.h" +#include "llmenubutton.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -117,8 +118,9 @@ BOOL LLPanelObject::postBuild() // Phantom checkbox mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl"); childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this); - + // Position + mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn"); mLabelPosition = getChild<LLTextBox>("label position"); mCtrlPosX = getChild<LLSpinCtrl>("Pos X"); childSetCommitCallback("Pos X",onCommitPosition,this); @@ -128,6 +130,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Pos Z",onCommitPosition,this); // Scale + mMenuClipboardSize = getChild<LLMenuButton>("clipboard_size_btn"); mLabelSize = getChild<LLTextBox>("label size"); mCtrlScaleX = getChild<LLSpinCtrl>("Scale X"); childSetCommitCallback("Scale X",onCommitScale,this); @@ -141,6 +144,7 @@ BOOL LLPanelObject::postBuild() childSetCommitCallback("Scale Z",onCommitScale,this); // Rotation + mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn"); mLabelRotation = getChild<LLTextBox>("label rotation"); mCtrlRotX = getChild<LLSpinCtrl>("Rot X"); childSetCommitCallback("Rot X",onCommitRotation,this); @@ -155,6 +159,8 @@ BOOL LLPanelObject::postBuild() mComboBaseType = getChild<LLComboBox>("comboBaseType"); childSetCommitCallback("comboBaseType",onCommitParametric,this); + mMenuClipboardParams = getChild<LLMenuButton>("clipboard_obj_params_btn"); + // Cut mLabelCut = getChild<LLTextBox>("text cut"); mSpinCutBegin = getChild<LLSpinCtrl>("cut begin"); @@ -285,8 +291,13 @@ LLPanelObject::LLPanelObject() mSelectedType(MI_BOX), mSculptTextureRevert(LLUUID::null), mSculptTypeRevert(0), + mHasClipboardPos(false), + mHasClipboardSize(false), + mHasClipboardRot(false), mSizeChanged(FALSE) { + mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2)); } @@ -373,7 +384,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_POS); } - + mMenuClipboardPos->setEnabled(enable_move); mLabelPosition->setEnabled( enable_move ); mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); @@ -399,6 +410,7 @@ void LLPanelObject::getState( ) calcp->setVar(LLCalc::Z_SCALE, 0.f); } + mMenuClipboardSize->setEnabled(enable_scale); mLabelSize->setEnabled( enable_scale ); mCtrlScaleX->setEnabled( enable_scale ); mCtrlScaleY->setEnabled( enable_scale ); @@ -430,6 +442,7 @@ void LLPanelObject::getState( ) calcp->clearVar(LLCalc::Z_ROT); } + mMenuClipboardRot->setEnabled(enable_rotate); mLabelRotation->setEnabled( enable_rotate ); mCtrlRotX->setEnabled( enable_rotate ); mCtrlRotY->setEnabled( enable_rotate ); @@ -607,7 +620,7 @@ void LLPanelObject::getState( ) } else { - LL_INFOS() << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; + LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; selected_item = MI_BOX; } @@ -933,6 +946,7 @@ void LLPanelObject::getState( ) // Update field enablement mComboBaseType ->setEnabled( enabled ); + mMenuClipboardParams->setEnabled(enabled); mLabelCut ->setEnabled( enabled ); mSpinCutBegin ->setEnabled( enabled ); @@ -1093,7 +1107,8 @@ void LLPanelObject::getState( ) } mComboBaseType->setEnabled(!isMesh); - + mMenuClipboardParams->setEnabled(!isMesh); + if (mCtrlSculptType) { if (sculpt_stitching == LL_SCULPT_TYPE_NONE) @@ -1157,11 +1172,11 @@ void LLPanelObject::sendIsPhysical() LLSelectMgr::getInstance()->selectionUpdatePhysics(value); mIsPhysical = value; - LL_INFOS() << "update physics sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL; } else { - LL_INFOS() << "update physics not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL; } } @@ -1173,11 +1188,11 @@ void LLPanelObject::sendIsTemporary() LLSelectMgr::getInstance()->selectionUpdateTemporary(value); mIsTemporary = value; - LL_INFOS() << "update temporary sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL; } else { - LL_INFOS() << "update temporary not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL; } } @@ -1190,11 +1205,11 @@ void LLPanelObject::sendIsPhantom() LLSelectMgr::getInstance()->selectionUpdatePhantom(value); mIsPhantom = value; - LL_INFOS() << "update phantom sent" << LL_ENDL; + LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL; } else { - LL_INFOS() << "update phantom not changed" << LL_ENDL; + LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL; } } @@ -1304,7 +1319,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) break; default: - LL_WARNS() << "Unknown base type " << selected_type + LL_WARNS("FloaterTools") << "Unknown base type " << selected_type << " in getVolumeParams()" << LL_ENDL; // assume a box selected_type = MI_BOX; @@ -1644,13 +1659,15 @@ void LLPanelObject::sendPosition(BOOL btn_down) LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); LLViewerRegion* regionp = mObject->getRegion(); - // Clamp the Z height - const F32 height = newpos.mV[VZ]; - const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); - const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); + if (!regionp) return; if (!mObject->isAttachment()) { + // Clamp the Z height + const F32 height = newpos.mV[VZ]; + const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); + const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); + if ( height < min_height) { newpos.mV[VZ] = min_height; @@ -2011,3 +2028,283 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) self->sendSculpt(); } + +void LLPanelObject::menuDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste + if (command == "psr_paste") + { + onPastePos(); + onPasteSize(); + onPasteRot(); + } + else if (command == "pos_paste") + { + onPastePos(); + } + else if (command == "size_paste") + { + onPasteSize(); + } + else if (command == "rot_paste") + { + onPasteRot(); + } + else if (command == "params_paste") + { + onPasteParams(); + } + // copy + else if (command == "psr_copy") + { + onCopyPos(); + onCopySize(); + onCopyRot(); + } + else if (command == "pos_copy") + { + onCopyPos(); + } + else if (command == "size_copy") + { + onCopySize(); + } + else if (command == "rot_copy") + { + onCopyRot(); + } + else if (command == "params_copy") + { + onCopyParams(); + } +} + +bool LLPanelObject::menuEnableItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste options + if (command == "psr_paste") + { + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) + && (selected_count == 1); + + if (!single_volume) + { + return false; + } + + bool enable_move; + bool enable_modify; + + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + + return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot; + } + else if (command == "pos_paste") + { + // assumes that menu won't be active if there is no move permission + return mHasClipboardPos; + } + else if (command == "size_paste") + { + return mHasClipboardSize; + } + else if (command == "rot_paste") + { + return mHasClipboardRot; + } + else if (command == "params_paste") + { + return mClipboardParams.isMap() && !mClipboardParams.emptyMap(); + } + // copy options + else if (command == "psr_copy") + { + S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) + && (selected_count == 1); + + if (!single_volume) + { + return false; + } + + bool enable_move; + bool enable_modify; + + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + + // since we forbid seeing values we also should forbid copying them + return enable_move && enable_modify; + } + return false; +} + +void LLPanelObject::onCopyPos() +{ + mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); + + std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + + mHasClipboardPos = true; +} + +void LLPanelObject::onCopySize() +{ + mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); + + std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + + mHasClipboardSize = true; +} + +void LLPanelObject::onCopyRot() +{ + mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); + + std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + + mHasClipboardRot = true; +} + +void LLPanelObject::onPastePos() +{ + if (!mHasClipboardPos) return; + if (mObject.isNull()) return; + + LLViewerRegion* regionp = mObject->getRegion(); + if (!regionp) return; + + + // Clamp pos on non-attachments, just keep the prims within the region + if (!mObject->isAttachment()) + { + F32 max_width = regionp->getWidth(); // meters + mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, max_width); + mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width); + //height will get properly clamped by sendPosition + } + + mCtrlPosX->set( mClipboardPos.mV[VX] ); + mCtrlPosY->set( mClipboardPos.mV[VY] ); + mCtrlPosZ->set( mClipboardPos.mV[VZ] ); + + sendPosition(FALSE); +} + +void LLPanelObject::onPasteSize() +{ + if (!mHasClipboardSize) return; + + mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + + mCtrlScaleX->set(mClipboardSize.mV[VX]); + mCtrlScaleY->set(mClipboardSize.mV[VY]); + mCtrlScaleZ->set(mClipboardSize.mV[VZ]); + + sendScale(FALSE); +} + +void LLPanelObject::onPasteRot() +{ + if (!mHasClipboardRot) return; + + mCtrlRotX->set(mClipboardRot.mV[VX]); + mCtrlRotY->set(mClipboardRot.mV[VY]); + mCtrlRotZ->set(mClipboardRot.mV[VZ]); + + sendRotation(FALSE); +} + +void LLPanelObject::onCopyParams() +{ + LLViewerObject* objectp = mObject; + if (!objectp || objectp->isMesh()) + { + return; + } + + mClipboardParams.clear(); + + // Parametrics + LLVolumeParams params; + getVolumeParams(params); + mClipboardParams["volume_params"] = params.asLLSD(); + + // Sculpted Prim + if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) + { + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; + } + else + { + mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); + } + + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + } +} + +void LLPanelObject::onPasteParams() +{ + LLViewerObject* objectp = mObject; + if (!objectp) + { + return; + } + + // Sculpted Prim + if (mClipboardParams.has("sculpt")) + { + LLSculptParams sculpt_params; + LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID(); + U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger(); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); + objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); + } + else + { + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if (sculpt_params) + { + objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); + } + } + + // volume params + // make sure updateVolume() won't affect flexible + if (mClipboardParams.has("volume_params")) + { + LLVolumeParams params; + params.fromLLSD(mClipboardParams["volume_params"]); + LLVOVolume *volobjp = (LLVOVolume *)objectp; + if (volobjp->isFlexible()) + { + if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE) + { + params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE); + } + } + else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) + { + params.getPathParams().setCurveType(LL_PCODE_PATH_LINE); + } + + objectp->updateVolume(params); + } +} diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 8829f493fa..515dd27c0a 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLTextBox; class LLUICtrl; class LLButton; +class LLMenuButton; class LLViewerObject; class LLComboBox; class LLColorSwatchCtrl; @@ -66,6 +67,14 @@ public: static void onCommitPhantom( LLUICtrl* ctrl, void* userdata); static void onCommitPhysics( LLUICtrl* ctrl, void* userdata); + void onCopyPos(); + void onPastePos(); + void onCopySize(); + void onPasteSize(); + void onCopyRot(); + void onPasteRot(); + void onCopyParams(); + void onPasteParams(); static void onCommitParametric(LLUICtrl* ctrl, void* userdata); @@ -75,6 +84,9 @@ public: BOOL onDropSculpt(LLInventoryItem* item); static void onCommitSculptType( LLUICtrl *ctrl, void* userdata); + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); + protected: void getState(); @@ -92,6 +104,7 @@ protected: protected: // Per-object options LLComboBox* mComboBaseType; + LLMenuButton* mMenuClipboardParams; LLTextBox* mLabelCut; LLSpinCtrl* mSpinCutBegin; @@ -131,17 +144,20 @@ protected: LLTextBox* mLabelRevolutions; LLSpinCtrl* mSpinRevolutions; + LLMenuButton* mMenuClipboardPos; LLTextBox* mLabelPosition; LLSpinCtrl* mCtrlPosX; LLSpinCtrl* mCtrlPosY; LLSpinCtrl* mCtrlPosZ; + LLMenuButton* mMenuClipboardSize; LLTextBox* mLabelSize; LLSpinCtrl* mCtrlScaleX; LLSpinCtrl* mCtrlScaleY; LLSpinCtrl* mCtrlScaleZ; BOOL mSizeChanged; + LLMenuButton* mMenuClipboardRot; LLTextBox* mLabelRotation; LLSpinCtrl* mCtrlRotX; LLSpinCtrl* mCtrlRotY; @@ -157,7 +173,7 @@ protected: LLComboBox *mCtrlSculptType; LLCheckBoxCtrl *mCtrlSculptMirror; LLCheckBoxCtrl *mCtrlSculptInvert; - + LLVector3 mCurEulerDegrees; // to avoid sending rotation when not changed BOOL mIsPhysical; // to avoid sending "physical" when not changed BOOL mIsTemporary; // to avoid sending "temporary" when not changed @@ -167,6 +183,15 @@ protected: LLUUID mSculptTextureRevert; // so we can revert the sculpt texture on cancel U8 mSculptTypeRevert; // so we can revert the sculpt type on cancel + LLVector3 mClipboardPos; + LLVector3 mClipboardSize; + LLVector3 mClipboardRot; + LLSD mClipboardParams; + + bool mHasClipboardPos; + bool mHasClipboardSize; + bool mHasClipboardRot; + LLPointer<LLViewerObject> mObject; LLPointer<LLViewerObject> mRootObject; }; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 0d987df6ca..cfaa9456be 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -618,7 +618,18 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const if (cat) { - mDisplayName.assign(cat->getName()); + std::string name = cat->getName(); + if (mChildren.size() > 0) + { + // Add item count + // Normally we would be using getLabelSuffix for this + // but object's inventory just uses displaynames + LLStringUtil::format_map_t args; + args["[ITEMS_COUNT]"] = llformat("%d", mChildren.size()); + + name.append(" " + LLTrans::getString("InventoryItemsCount", args)); + } + mDisplayName.assign(name); } return mDisplayName; @@ -1522,6 +1533,8 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root { createViewsForCategory(&contents, inventory_root, new_folder); } + // Refresh for label to add item count + new_folder->refresh(); } } diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp deleted file mode 100644 index 40326cfb39..0000000000 --- a/indra/newview/llpanelpick.cpp +++ /dev/null @@ -1,620 +0,0 @@ -/** - * @file llpanelpick.cpp - * @brief LLPanelPick class implementation - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Display of a "Top Pick" used both for the global top picks in the -// Find directory, and also for each individual user's picks in their -// profile. - -#include "llviewerprecompiledheaders.h" - -#include "llpanelpick.h" - -#include "message.h" - -#include "llparcel.h" - -#include "llbutton.h" -#include "llfloaterreg.h" -#include "lliconctrl.h" -#include "lllineeditor.h" -#include "llpanel.h" -#include "llscrollcontainer.h" -#include "lltexteditor.h" - -#include "llagent.h" -#include "llagentpicksinfo.h" -#include "llavatarpropertiesprocessor.h" -#include "llfloaterworldmap.h" -#include "lltexturectrl.h" -#include "lluiconstants.h" -#include "llviewerparcelmgr.h" -#include "llviewerregion.h" -#include "llworldmap.h" - - -#define XML_PANEL_EDIT_PICK "panel_edit_pick.xml" -#define XML_PANEL_PICK_INFO "panel_pick_info.xml" - -#define XML_NAME "pick_name" -#define XML_DESC "pick_desc" -#define XML_SNAPSHOT "pick_snapshot" -#define XML_LOCATION "pick_location" - -#define XML_BTN_ON_TXTR "edit_icon" -#define XML_BTN_SAVE "save_changes_btn" - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -//static -LLPanelPickInfo* LLPanelPickInfo::create() -{ - LLPanelPickInfo* panel = new LLPanelPickInfo(); - panel->buildFromFile(XML_PANEL_PICK_INFO); - return panel; -} - -LLPanelPickInfo::LLPanelPickInfo() - : LLPanel() - , LLAvatarPropertiesObserver() - , LLRemoteParcelInfoObserver() - , mAvatarId(LLUUID::null) - , mSnapshotCtrl(NULL) - , mPickId(LLUUID::null) - , mParcelId(LLUUID::null) - , mRequestedId(LLUUID::null) - , mScrollingPanelMinHeight(0) - , mScrollingPanelWidth(0) - , mScrollingPanel(NULL) - , mScrollContainer(NULL) -{ -} - -LLPanelPickInfo::~LLPanelPickInfo() -{ - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); - - if (mParcelId.notNull()) - { - LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); - } -} - -void LLPanelPickInfo::onOpen(const LLSD& key) -{ - LLUUID avatar_id = key["avatar_id"]; - if(avatar_id.isNull()) - { - return; - } - - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver( - getAvatarId(), this); - } - - setAvatarId(avatar_id); - - resetData(); - resetControls(); - - setPickId(key["pick_id"]); - setPickName(key["pick_name"]); - setPickDesc(key["pick_desc"]); - setSnapshotId(key["snapshot_id"]); - - LLAvatarPropertiesProcessor::getInstance()->addObserver( - getAvatarId(), this); - LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest( - getAvatarId(), getPickId()); -} - -BOOL LLPanelPickInfo::postBuild() -{ - mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT); - - childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this)); - childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this)); - childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this)); - - mScrollingPanel = getChild<LLPanel>("scroll_content_panel"); - mScrollContainer = getChild<LLScrollContainer>("profile_scroll"); - - mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight(); - mScrollingPanelWidth = mScrollingPanel->getRect().getWidth(); - - LLTextEditor* text_desc = getChild<LLTextEditor>(XML_DESC); - text_desc->setContentTrusted(false); - - return TRUE; -} - -void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - LLPanel::reshape(width, height, called_from_parent); - - if (!mScrollContainer || !mScrollingPanel) - return; - - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - - S32 scroll_height = mScrollContainer->getRect().getHeight(); - if (mScrollingPanelMinHeight >= scroll_height) - { - mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight); - } - else - { - mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height); - } -} - -void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_PICK_INFO != type) - { - return; - } - LLPickData* pick_info = static_cast<LLPickData*>(data); - if(!pick_info - || pick_info->creator_id != getAvatarId() - || pick_info->pick_id != getPickId()) - { - return; - } - - mParcelId = pick_info->parcel_id; - setSnapshotId(pick_info->snapshot_id); - setPickName(pick_info->name); - setPickDesc(pick_info->desc); - setPosGlobal(pick_info->pos_global); - - // Send remote parcel info request to get parcel name and sim (region) name. - sendParcelInfoRequest(); - - // *NOTE dzaporozhan - // We want to keep listening to APT_PICK_INFO because user may - // edit the Pick and we have to update Pick info panel. - // revomeObserver is called from onClickBack -} - -void LLPanelPickInfo::sendParcelInfoRequest() -{ - if (mParcelId != mRequestedId) - { - LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); - LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); - - mRequestedId = mParcelId; - } -} - -void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("back_btn")->setClickedCallback(cb); -} - -void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data) -{ - setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, - parcel_data.sim_name, getPosGlobal())); - - // We have received parcel info for the requested ID so clear it now. - mRequestedId.setNull(); - - if (mParcelId.notNull()) - { - LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); - } -} - -void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("edit_btn")->setClickedCallback(cb); -} - -// PROTECTED AREA - -void LLPanelPickInfo::resetControls() -{ - if(getAvatarId() == gAgent.getID()) - { - getChildView("edit_btn")->setEnabled(TRUE); - getChildView("edit_btn")->setVisible( TRUE); - } - else - { - getChildView("edit_btn")->setEnabled(FALSE); - getChildView("edit_btn")->setVisible( FALSE); - } -} - -void LLPanelPickInfo::resetData() -{ - setPickName(LLStringUtil::null); - setPickDesc(LLStringUtil::null); - setPickLocation(LLStringUtil::null); - setPickId(LLUUID::null); - setSnapshotId(LLUUID::null); - mPosGlobal.clearVec(); - mParcelId.setNull(); - mRequestedId.setNull(); -} - -// static -std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global) -{ - std::string location_text; - location_text.append(owner_name); - if (!original_name.empty()) - { - if (!location_text.empty()) location_text.append(", "); - location_text.append(original_name); - - } - if (!sim_name.empty()) - { - if (!location_text.empty()) location_text.append(", "); - location_text.append(sim_name); - } - - if (!location_text.empty()) location_text.append(" "); - - if (!pos_global.isNull()) - { - S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; - S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; - S32 region_z = ll_round((F32)pos_global.mdV[VZ]); - location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); - } - return location_text; -} - -void LLPanelPickInfo::setSnapshotId(const LLUUID& id) -{ - mSnapshotCtrl->setImageAssetID(id); - mSnapshotCtrl->setValid(TRUE); -} - -void LLPanelPickInfo::setPickName(const std::string& name) -{ - getChild<LLUICtrl>(XML_NAME)->setValue(name); -} - -void LLPanelPickInfo::setPickDesc(const std::string& desc) -{ - getChild<LLUICtrl>(XML_DESC)->setValue(desc); -} - -void LLPanelPickInfo::setPickLocation(const std::string& location) -{ - getChild<LLUICtrl>(XML_LOCATION)->setValue(location); -} - -void LLPanelPickInfo::onClickMap() -{ - LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); - LLFloaterReg::showInstance("world_map", "center"); -} - -void LLPanelPickInfo::onClickTeleport() -{ - if (!getPosGlobal().isExactlyZero()) - { - gAgent.teleportViaLocation(getPosGlobal()); - LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); - } -} - -void LLPanelPickInfo::onClickBack() -{ - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -//static -LLPanelPickEdit* LLPanelPickEdit::create() -{ - LLPanelPickEdit* panel = new LLPanelPickEdit(); - panel->buildFromFile(XML_PANEL_EDIT_PICK); - return panel; -} - -LLPanelPickEdit::LLPanelPickEdit() - : LLPanelPickInfo() - , mLocationChanged(false) - , mNeedData(true) - , mNewPick(false) -{ -} - -LLPanelPickEdit::~LLPanelPickEdit() -{ -} - -void LLPanelPickEdit::onOpen(const LLSD& key) -{ - LLUUID pick_id = key["pick_id"]; - mNeedData = true; - - // creating new Pick - if(pick_id.isNull()) - { - mNewPick = true; - - setAvatarId(gAgent.getID()); - - resetData(); - resetControls(); - - setPosGlobal(gAgent.getPositionGlobal()); - - LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; - std::string pick_name, pick_desc, region_name; - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if(parcel) - { - parcel_id = parcel->getID(); - pick_name = parcel->getName(); - pick_desc = parcel->getDesc(); - snapshot_id = parcel->getSnapshotID(); - } - - LLViewerRegion* region = gAgent.getRegion(); - if(region) - { - region_name = region->getName(); - } - - setParcelID(parcel_id); - getChild<LLUICtrl>("pick_name")->setValue(pick_name.empty() ? region_name : pick_name); - getChild<LLUICtrl>("pick_desc")->setValue(pick_desc); - setSnapshotId(snapshot_id); - setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal())); - - enableSaveButton(true); - } - // editing existing pick - else - { - mNewPick = false; - LLPanelPickInfo::onOpen(key); - - enableSaveButton(false); - } - - resetDirty(); -} - -void LLPanelPickEdit::setPickData(const LLPickData* pick_data) -{ - if(!pick_data) - { - return; - } - - mNeedData = false; - - setParcelID(pick_data->parcel_id); - getChild<LLUICtrl>("pick_name")->setValue(pick_data->name); - getChild<LLUICtrl>("pick_desc")->setValue(pick_data->desc); - setSnapshotId(pick_data->snapshot_id); - setPosGlobal(pick_data->pos_global); - setPickLocation(createLocationText(LLStringUtil::null, pick_data->name, - pick_data->sim_name, pick_data->pos_global)); -} - -BOOL LLPanelPickEdit::postBuild() -{ - LLPanelPickInfo::postBuild(); - - mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this)); - - LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name"); - line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL); - - LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc"); - text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1)); - - childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this)); - childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this)); - - initTexturePickerMouseEvents(); - - return TRUE; -} - -void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("save_changes_btn")->setClickedCallback(cb); -} - -void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb) -{ - getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -void LLPanelPickEdit::resetDirty() -{ - LLPanelPickInfo::resetDirty(); - - getChild<LLLineEditor>("pick_name")->resetDirty(); - getChild<LLTextEditor>("pick_desc")->resetDirty(); - mSnapshotCtrl->resetDirty(); - mLocationChanged = false; -} - -BOOL LLPanelPickEdit::isDirty() const -{ - if( mNewPick - || LLPanelPickInfo::isDirty() - || mLocationChanged - || mSnapshotCtrl->isDirty() - || getChild<LLLineEditor>("pick_name")->isDirty() - || getChild<LLTextEditor>("pick_desc")->isDirty()) - { - return TRUE; - } - return FALSE; -} - -// PROTECTED AREA - -void LLPanelPickEdit::sendUpdate() -{ - LLPickData pick_data; - - // If we don't have a pick id yet, we'll need to generate one, - // otherwise we'll keep overwriting pick_id 00000 in the database. - if (getPickId().isNull()) - { - getPickId().generate(); - } - - pick_data.agent_id = gAgent.getID(); - pick_data.session_id = gAgent.getSessionID(); - pick_data.pick_id = getPickId(); - pick_data.creator_id = gAgent.getID();; - - //legacy var need to be deleted - pick_data.top_pick = FALSE; - pick_data.parcel_id = mParcelId; - pick_data.name = getChild<LLUICtrl>(XML_NAME)->getValue().asString(); - pick_data.desc = getChild<LLUICtrl>(XML_DESC)->getValue().asString(); - pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); - pick_data.pos_global = getPosGlobal(); - pick_data.sort_order = 0; - pick_data.enabled = TRUE; - - LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); - - if(mNewPick) - { - // Assume a successful create pick operation, make new number of picks - // available immediately. Actual number of picks will be requested in - // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. - LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); - } -} - -void LLPanelPickEdit::onSnapshotChanged() -{ - enableSaveButton(true); -} - -void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl) -{ - enableSaveButton(isDirty()); -} - -void LLPanelPickEdit::resetData() -{ - LLPanelPickInfo::resetData(); - mLocationChanged = false; -} - -void LLPanelPickEdit::enableSaveButton(bool enable) -{ - getChildView(XML_BTN_SAVE)->setEnabled(enable); -} - -void LLPanelPickEdit::onClickSetLocation() -{ - // Save location for later use. - setPosGlobal(gAgent.getPositionGlobal()); - - std::string parcel_name, region_name; - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (parcel) - { - mParcelId = parcel->getID(); - parcel_name = parcel->getName(); - } - - LLViewerRegion* region = gAgent.getRegion(); - if(region) - { - region_name = region->getName(); - } - - setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); - - mLocationChanged = true; - enableSaveButton(TRUE); -} - -void LLPanelPickEdit::onClickSave() -{ - sendUpdate(); - - mLocationChanged = false; - - LLSD params; - params["action"] = "save_new_pick"; - notifyParent(params); -} - -std::string LLPanelPickEdit::getLocationNotice() -{ - static std::string notice = getString("location_notice"); - return notice; -} - -void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type) -{ - if(mNeedData) - { - LLPanelPickInfo::processProperties(data, type); - } -} - -// PRIVATE AREA - -void LLPanelPickEdit::initTexturePickerMouseEvents() -{ - text_icon = getChild<LLIconCtrl>(XML_BTN_ON_TXTR); - mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1)); - mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1)); - - text_icon->setVisible(FALSE); -} - -void LLPanelPickEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) -{ - text_icon->setVisible(TRUE); -} - -void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) -{ - text_icon->setVisible(FALSE); -} diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h deleted file mode 100644 index 7a8bd66fcf..0000000000 --- a/indra/newview/llpanelpick.h +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @file llpanelpick.h - * @brief LLPanelPick class definition - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Display of a "Top Pick" used both for the global top picks in the -// Find directory, and also for each individual user's picks in their -// profile. - -#ifndef LL_LLPANELPICK_H -#define LL_LLPANELPICK_H - -#include "llpanel.h" -#include "llremoteparcelrequest.h" -#include "llavatarpropertiesprocessor.h" - -class LLIconCtrl; -class LLTextureCtrl; -class LLScrollContainer; -class LLMessageSystem; -class LLAvatarPropertiesObserver; - -/** - * Panel for displaying Pick Information - snapshot, name, description, etc. - */ -class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver -{ - LOG_CLASS(LLPanelPickInfo); -public: - - // Creates new panel - static LLPanelPickInfo* create(); - - virtual ~LLPanelPickInfo(); - - /** - * Initializes panel properties - * - * By default Pick will be created for current Agent location. - * Use setPickData to change Pick properties. - */ - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - /** - * Sends remote parcel info request to resolve parcel name from its ID. - */ - void sendParcelInfoRequest(); - - /** - * Sets "Back" button click callback - */ - virtual void setExitCallback(const commit_callback_t& cb); - - /** - * Sets "Edit" button click callback - */ - virtual void setEditPickCallback(const commit_callback_t& cb); - - //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing - /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); - /*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } - /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {}; - -protected: - - LLPanelPickInfo(); - - /** - * Resets Pick information - */ - virtual void resetData(); - - /** - * Resets UI controls (visibility, values) - */ - virtual void resetControls(); - - /** - * "Location text" is actually the owner name, the original - * name that owner gave the parcel, and the location. - */ - static std::string createLocationText( - const std::string& owner_name, - const std::string& original_name, - const std::string& sim_name, - const LLVector3d& pos_global); - - virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } - virtual LLUUID& getAvatarId() { return mAvatarId; } - - /** - * Sets snapshot id. - * - * Will mark snapshot control as valid if id is not null. - * Will mark snapshot control as invalid if id is null. If null id is a valid value, - * you have to manually mark snapshot is valid. - */ - virtual void setSnapshotId(const LLUUID& id); - - virtual void setPickId(const LLUUID& id) { mPickId = id; } - virtual LLUUID& getPickId() { return mPickId; } - - virtual void setPickName(const std::string& name); - - virtual void setPickDesc(const std::string& desc); - - virtual void setPickLocation(const std::string& location); - - virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } - virtual LLVector3d& getPosGlobal() { return mPosGlobal; } - - /** - * Callback for "Map" button, opens Map - */ - void onClickMap(); - - /** - * Callback for "Teleport" button, teleports user to Pick location. - */ - void onClickTeleport(); - - void onClickBack(); - -protected: - - S32 mScrollingPanelMinHeight; - S32 mScrollingPanelWidth; - LLScrollContainer* mScrollContainer; - LLPanel* mScrollingPanel; - LLTextureCtrl* mSnapshotCtrl; - - LLUUID mAvatarId; - LLVector3d mPosGlobal; - LLUUID mParcelId; - LLUUID mPickId; - LLUUID mRequestedId; -}; - -/** - * Panel for creating/editing Pick. - */ -class LLPanelPickEdit : public LLPanelPickInfo -{ - LOG_CLASS(LLPanelPickEdit); -public: - - /** - * Creates new panel - */ - static LLPanelPickEdit* create(); - - /*virtual*/ ~LLPanelPickEdit(); - - /*virtual*/ void onOpen(const LLSD& key); - - virtual void setPickData(const LLPickData* pick_data); - - /*virtual*/ BOOL postBuild(); - - /** - * Sets "Save" button click callback - */ - virtual void setSaveCallback(const commit_callback_t& cb); - - /** - * Sets "Cancel" button click callback - */ - virtual void setCancelCallback(const commit_callback_t& cb); - - /** - * Resets panel and all cantrols to unedited state - */ - /*virtual*/ void resetDirty(); - - /** - * Returns true if any of Pick properties was changed by user. - */ - /*virtual*/ BOOL isDirty() const; - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -protected: - - LLPanelPickEdit(); - - /** - * Sends Pick properties to server. - */ - void sendUpdate(); - - /** - * Called when snapshot image changes. - */ - void onSnapshotChanged(); - - /** - * Callback for Pick snapshot, name and description changed event. - */ - void onPickChanged(LLUICtrl* ctrl); - - /*virtual*/ void resetData(); - - /** - * Enables/disables "Save" button - */ - void enableSaveButton(bool enable); - - /** - * Callback for "Set Location" button click - */ - void onClickSetLocation(); - - /** - * Callback for "Save" button click - */ - void onClickSave(); - - std::string getLocationNotice(); - -protected: - - bool mLocationChanged; - bool mNeedData; - bool mNewPick; - -private: - - void initTexturePickerMouseEvents(); - void onTexturePickerMouseEnter(LLUICtrl* ctrl); - void onTexturePickerMouseLeave(LLUICtrl* ctrl); - -private: - - LLIconCtrl* text_icon; -}; - -#endif // LL_LLPANELPICK_H diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp deleted file mode 100644 index 8294977f99..0000000000 --- a/indra/newview/llpanelpicks.cpp +++ /dev/null @@ -1,1484 +0,0 @@ -/** - * @file llpanelpicks.cpp - * @brief LLPanelPicks and related class implementations - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelpicks.h" - -#include "llagent.h" -#include "llagentpicksinfo.h" -#include "llcommandhandler.h" -#include "lldispatcher.h" -#include "llflatlistview.h" -#include "llfloaterreg.h" -#include "llfloatersidepanelcontainer.h" -#include "llfloaterworldmap.h" -#include "llnotificationsutil.h" -#include "llstartup.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" -#include "lltrans.h" -#include "llviewergenericmessage.h" // send_generic_message -#include "llmenugl.h" -#include "llviewermenu.h" -#include "llregistry.h" - -#include "llaccordionctrl.h" -#include "llaccordionctrltab.h" -#include "llavatarpropertiesprocessor.h" -#include "llfloatersidepanelcontainer.h" -#include "llpanelavatar.h" -#include "llpanelprofile.h" -#include "llpanelpick.h" -#include "llpanelclassified.h" - -static const std::string XML_BTN_NEW = "new_btn"; -static const std::string XML_BTN_DELETE = "trash_btn"; -static const std::string XML_BTN_INFO = "info_btn"; -static const std::string XML_BTN_TELEPORT = "teleport_btn"; -static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn"; - -static const std::string PICK_ID("pick_id"); -static const std::string PICK_CREATOR_ID("pick_creator_id"); -static const std::string PICK_NAME("pick_name"); - -static const std::string CLASSIFIED_ID("classified_id"); -static const std::string CLASSIFIED_NAME("classified_name"); - - -static LLPanelInjector<LLPanelPicks> t_panel_picks("panel_picks"); - - -class LLPickHandler : public LLCommandHandler, - public LLAvatarPropertiesObserver -{ -public: - - std::set<LLUUID> mPickIds; - - // requires trusted browser to trigger - LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } - - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) - { - if (LLStartUp::getStartupState() < STATE_STARTED) - { - return true; - } - - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnablePicks")) - { - LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - - // handle app/classified/create urls first - if (params.size() == 1 && params[0].asString() == "create") - { - createPick(); - return true; - } - - // then handle the general app/pick/{UUID}/{CMD} urls - if (params.size() < 2) - { - return false; - } - - // get the ID for the pick_id - LLUUID pick_id; - if (!pick_id.set(params[0], FALSE)) - { - return false; - } - - // edit the pick in the side tray. - // need to ask the server for more info first though... - const std::string verb = params[1].asString(); - if (verb == "edit") - { - mPickIds.insert(pick_id); - LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); - LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(gAgent.getID(),pick_id); - return true; - } - else - { - LL_WARNS() << "unknown verb " << verb << LL_ENDL; - return false; - } - } - - void createPick() - { - // open the new pick panel on the Picks floater - LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - - LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); - if (picks) - { - picks->createNewPick(); - } - } - - void editPick(LLPickData* pick_info) - { - LLSD params; - params["open_tab_name"] = "panel_picks"; - params["show_tab_panel"] = "edit_pick"; - params["pick_id"] = pick_info->pick_id; - params["avatar_id"] = pick_info->creator_id; - params["snapshot_id"] = pick_info->snapshot_id; - params["pick_name"] = pick_info->name; - params["pick_desc"] = pick_info->desc; - LLFloaterSidePanelContainer::showPanel("picks", params); - } - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) - { - if (APT_PICK_INFO != type) - { - return; - } - - // is this the pick that we asked for? - LLPickData* pick_info = static_cast<LLPickData*>(data); - if (!pick_info || mPickIds.find(pick_info->pick_id) == mPickIds.end()) - { - return; - } - - // open the edit side tray for this pick - if (pick_info->creator_id == gAgent.getID()) - { - editPick(pick_info); - } - else - { - LL_WARNS() << "Can't edit a pick you did not create" << LL_ENDL; - } - - // remove our observer now that we're done - mPickIds.erase(pick_info->pick_id); - LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); - } -}; - -LLPickHandler gPickHandler; - -class LLClassifiedHandler : - public LLCommandHandler, - public LLAvatarPropertiesObserver -{ -public: - // throttle calls from untrusted browsers - LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} - - std::set<LLUUID> mClassifiedIds; - - std::string mRequestVerb; - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) - { - if (LLStartUp::getStartupState() < STATE_STARTED) - { - return true; - } - - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds")) - { - LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - - // handle app/classified/create urls first - if (params.size() == 1 && params[0].asString() == "create") - { - createClassified(); - return true; - } - - // then handle the general app/classified/{UUID}/{CMD} urls - if (params.size() < 2) - { - return false; - } - - // get the ID for the classified - LLUUID classified_id; - if (!classified_id.set(params[0], FALSE)) - { - return false; - } - - // show the classified in the side tray. - // need to ask the server for more info first though... - const std::string verb = params[1].asString(); - if (verb == "about") - { - mRequestVerb = verb; - mClassifiedIds.insert(classified_id); - LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); - LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); - return true; - } - else if (verb == "edit") - { - mRequestVerb = verb; - mClassifiedIds.insert(classified_id); - LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); - LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); - return true; - } - - return false; - } - - void createClassified() - { - // open the new classified panel on the Picks floater - LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - - LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); - if (picks) - { - picks->createNewClassified(); - } - } - - void openClassified(LLAvatarClassifiedInfo* c_info) - { - if (mRequestVerb == "about") - { - // open the classified info panel on the Me > Picks sidetray - LLSD params; - params["id"] = c_info->creator_id; - params["open_tab_name"] = "panel_picks"; - params["show_tab_panel"] = "classified_details"; - params["classified_id"] = c_info->classified_id; - params["classified_creator_id"] = c_info->creator_id; - params["classified_snapshot_id"] = c_info->snapshot_id; - params["classified_name"] = c_info->name; - params["classified_desc"] = c_info->description; - params["from_search"] = true; - LLFloaterSidePanelContainer::showPanel("picks", params); - } - else if (mRequestVerb == "edit") - { - if (c_info->creator_id == gAgent.getID()) - { - LL_WARNS() << "edit in progress" << LL_ENDL; - // open the new classified panel on the Me > Picks sidetray - LLSD params; - params["id"] = gAgent.getID(); - params["open_tab_name"] = "panel_picks"; - params["show_tab_panel"] = "edit_classified"; - params["classified_id"] = c_info->classified_id; - LLFloaterSidePanelContainer::showPanel("my_profile", params); - } - else - { - LL_WARNS() << "Can't edit a classified you did not create" << LL_ENDL; - } - } - } - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) - { - if (APT_CLASSIFIED_INFO != type) - { - return; - } - - // is this the classified that we asked for? - LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); - if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) - { - return; - } - - // open the detail side tray for this classified - openClassified(c_info); - - // remove our observer now that we're done - mClassifiedIds.erase(c_info->classified_id); - LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); - } - -}; -LLClassifiedHandler gClassifiedHandler; - -////////////////////////////////////////////////////////////////////////// - - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPanelPicks::LLPanelPicks() -: LLPanelProfileTab(), - mPopupMenu(NULL), - mProfilePanel(NULL), - mPickPanel(NULL), - mPicksList(NULL), - mClassifiedsList(NULL), - mPanelPickInfo(NULL), - mPanelPickEdit(NULL), - mPlusMenu(NULL), - mPicksAccTab(NULL), - mClassifiedsAccTab(NULL), - mPanelClassifiedInfo(NULL), - mNoClassifieds(false), - mNoPicks(false) -{ -} - -LLPanelPicks::~LLPanelPicks() -{ - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); - } -} - -void* LLPanelPicks::create(void* data /* = NULL */) -{ - return new LLPanelPicks(); -} - -void LLPanelPicks::updateData() -{ - // Send Picks request only when we need to, not on every onOpen(during tab switch). - if(isDirty()) - { - mNoPicks = false; - mNoClassifieds = false; - - mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); - mNoItemsLabel->setVisible(TRUE); - - mPicksList->clear(); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); - - mClassifiedsList->clear(); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); - } -} - -void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_PICKS == type) - { - LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); - if(avatar_picks && getAvatarId() == avatar_picks->target_id) - { - LLAvatarName av_name; - LLAvatarNameCache::get(getAvatarId(), &av_name); - getChild<LLUICtrl>("pick_title")->setTextArg("[NAME]", av_name.getUserName()); - - // Save selection, to be able to edit same item after saving changes. See EXT-3023. - LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID]; - - mPicksList->clear(); - - LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); - for(; avatar_picks->picks_list.end() != it; ++it) - { - LLUUID pick_id = it->first; - std::string pick_name = it->second; - - LLPickItem* picture = LLPickItem::create(); - picture->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); - picture->setPickName(pick_name); - picture->setPickId(pick_id); - picture->setCreatorId(getAvatarId()); - - LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture); - picture->update(); - - LLSD pick_value = LLSD(); - pick_value.insert(PICK_ID, pick_id); - pick_value.insert(PICK_NAME, pick_name); - pick_value.insert(PICK_CREATOR_ID, getAvatarId()); - - mPicksList->addItem(picture, pick_value); - - // Restore selection by item id. - if ( pick_id == selected_id ) - mPicksList->selectItemByValue(pick_value); - - picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1)); - picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); - picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); - } - - showAccordion("tab_picks", mPicksList->size()); - - resetDirty(); - updateButtons(); - } - - mNoPicks = !mPicksList->size(); - } - else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) - { - LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); - if(c_info && getAvatarId() == c_info->target_id) - { - // do not clear classified list in case we will receive two or more data packets. - // list has been cleared in updateData(). (fix for EXT-6436) - - LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); - for(; c_info->classifieds_list.end() != it; ++it) - { - LLAvatarClassifieds::classified_data c_data = *it; - - LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), c_data.classified_id); - c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); - c_item->setClassifiedName(c_data.name); - - LLSD pick_value = LLSD(); - pick_value.insert(CLASSIFIED_ID, c_data.classified_id); - pick_value.insert(CLASSIFIED_NAME, c_data.name); - - if (!findClassifiedById(c_data.classified_id)) - { - mClassifiedsList->addItem(c_item, pick_value); - } - - c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); - c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); - c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); - } - - showAccordion("tab_classifieds", mClassifiedsList->size()); - - resetDirty(); - updateButtons(); - } - - mNoClassifieds = !mClassifiedsList->size(); - } - - updateNoItemsLabel(); -} - -LLPickItem* LLPanelPicks::getSelectedPickItem() -{ - LLPanel* selected_item = mPicksList->getSelectedItem(); - if (!selected_item) return NULL; - - return dynamic_cast<LLPickItem*>(selected_item); -} - -LLClassifiedItem* LLPanelPicks::getSelectedClassifiedItem() -{ - LLPanel* selected_item = mClassifiedsList->getSelectedItem(); - if (!selected_item) - { - return NULL; - } - return dynamic_cast<LLClassifiedItem*>(selected_item); -} - -BOOL LLPanelPicks::postBuild() -{ - mPicksList = getChild<LLFlatListView>("picks_list"); - mClassifiedsList = getChild<LLFlatListView>("classifieds_list"); - - mPicksList->setCommitOnSelectionChange(true); - mClassifiedsList->setCommitOnSelectionChange(true); - - mPicksList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mPicksList)); - mClassifiedsList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mClassifiedsList)); - - mPicksList->setNoItemsCommentText(getString("no_picks")); - mClassifiedsList->setNoItemsCommentText(getString("no_classifieds")); - - mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); - - childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this)); - childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this)); - childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this)); - childSetAction(XML_BTN_SHOW_ON_MAP, boost::bind(&LLPanelPicks::onClickMap, this)); - childSetAction(XML_BTN_INFO, boost::bind(&LLPanelPicks::onClickInfo, this)); - - mPicksAccTab = getChild<LLAccordionCtrlTab>("tab_picks"); - mPicksAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mPicksAccTab)); - mPicksAccTab->setDisplayChildren(true); - - mClassifiedsAccTab = getChild<LLAccordionCtrlTab>("tab_classifieds"); - mClassifiedsAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mClassifiedsAccTab)); - mClassifiedsAccTab->setDisplayChildren(false); - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; - registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this)); - registar.add("Pick.Edit", boost::bind(&LLPanelPicks::onClickMenuEdit, this)); - registar.add("Pick.Teleport", boost::bind(&LLPanelPicks::onClickTeleport, this)); - registar.add("Pick.Map", boost::bind(&LLPanelPicks::onClickMap, this)); - registar.add("Pick.Delete", boost::bind(&LLPanelPicks::onClickDelete, this)); - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registar; - enable_registar.add("Pick.Enable", boost::bind(&LLPanelPicks::onEnableMenuItem, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar; - plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2)); - mEnableCallbackRegistrar.add("Picks.Plus.Enable", boost::bind(&LLPanelPicks::isActionEnabled, this, _2)); - mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - - return TRUE; -} - -void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param) -{ - std::string value = param.asString(); - - if("new_pick" == value) - { - createNewPick(); - } - else if("new_classified" == value) - { - createNewClassified(); - } -} - -bool LLPanelPicks::isActionEnabled(const LLSD& userdata) const -{ - std::string command_name = userdata.asString(); - - if (command_name == "new_pick" && LLAgentPicksInfo::getInstance()->isPickLimitReached()) - { - return false; - } - - return true; -} - -bool LLPanelPicks::isClassifiedPublished(LLClassifiedItem* c_item) -{ - if(c_item) - { - LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; - if(panel) - { - return !panel->isNewWithErrors(); - } - - // we've got this classified from server - it's published - return true; - } - return false; -} - -void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab) -{ - if(!mPicksAccTab->getDisplayChildren()) - { - mPicksList->resetSelection(true); - } - if(!mClassifiedsAccTab->getDisplayChildren()) - { - mClassifiedsList->resetSelection(true); - } - - updateButtons(); -} - -void LLPanelPicks::onOpen(const LLSD& key) -{ - const LLUUID id(key.asUUID()); - BOOL self = (gAgent.getID() == id); - - // only agent can edit her picks - getChildView("edit_panel")->setEnabled(self); - getChildView("edit_panel")->setVisible( self); - - // Disable buttons when viewing profile for first time - if(getAvatarId() != id) - { - getChildView(XML_BTN_INFO)->setEnabled(FALSE); - getChildView(XML_BTN_TELEPORT)->setEnabled(FALSE); - getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(FALSE); - } - - // and see a special title - set as invisible by default in xml file - if (self) - { - getChildView("pick_title")->setVisible( !self); - getChildView("pick_title_agent")->setVisible( self); - - mPopupMenu->setItemVisible("pick_delete", TRUE); - mPopupMenu->setItemVisible("pick_edit", TRUE); - mPopupMenu->setItemVisible("pick_separator", TRUE); - } - - if(getAvatarId() != id) - { - showAccordion("tab_picks", false); - showAccordion("tab_classifieds", false); - - mPicksList->goToTop(); - // Set dummy value to make panel dirty and make it reload picks - setValue(LLSD()); - } - - LLPanelProfileTab::onOpen(key); -} - -void LLPanelPicks::onClosePanel() -{ - if (mPanelClassifiedInfo) - { - onPanelClassifiedClose(mPanelClassifiedInfo); - } - if (mPanelPickInfo) - { - onPanelPickClose(mPanelPickInfo); - } -} - -void LLPanelPicks::onListCommit(const LLFlatListView* f_list) -{ - // Make sure only one of the lists has selection. - if(f_list == mPicksList) - { - mClassifiedsList->resetSelection(true); - } - else if(f_list == mClassifiedsList) - { - mPicksList->resetSelection(true); - } - else - { - LL_WARNS() << "Unknown list" << LL_ENDL; - } - - updateButtons(); -} - -//static -void LLPanelPicks::onClickDelete() -{ - LLSD value = mPicksList->getSelectedValue(); - if (value.isDefined()) - { - LLSD args; - args["PICK"] = value[PICK_NAME]; - LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeletePick, this, _1, _2)); - return; - } - - value = mClassifiedsList->getSelectedValue(); - if(value.isDefined()) - { - LLSD args; - args["NAME"] = value[CLASSIFIED_NAME]; - LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeleteClassified, this, _1, _2)); - return; - } -} - -bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLSD pick_value = mPicksList->getSelectedValue(); - - if (0 == option) - { - LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]); - mPicksList->removeItemByValue(pick_value); - - mNoPicks = !mPicksList->size(); - if (mNoPicks) - { - showAccordion("tab_picks", false); - } - updateNoItemsLabel(); - } - updateButtons(); - return false; -} - -bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLSD value = mClassifiedsList->getSelectedValue(); - - if (0 == option) - { - LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]); - mClassifiedsList->removeItemByValue(value); - - mNoClassifieds = !mClassifiedsList->size(); - if (mNoClassifieds) - { - showAccordion("tab_classifieds", false); - } - updateNoItemsLabel(); - } - updateButtons(); - return false; -} - -bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response ) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if (0 == option) - { - onClickTeleport(); - } - return false; -} - -//static -void LLPanelPicks::onClickTeleport() -{ - LLPickItem* pick_item = getSelectedPickItem(); - LLClassifiedItem* c_item = getSelectedClassifiedItem(); - - LLVector3d pos; - if(pick_item) - pos = pick_item->getPosGlobal(); - else if(c_item) - { - pos = c_item->getPosGlobal(); - LLPanelClassifiedInfo::sendClickMessage("teleport", false, - c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); - } - - if (!pos.isExactlyZero()) - { - gAgent.teleportViaLocation(pos); - LLFloaterWorldMap::getInstance()->trackLocation(pos); - } -} - -//static -void LLPanelPicks::onClickMap() -{ - LLPickItem* pick_item = getSelectedPickItem(); - LLClassifiedItem* c_item = getSelectedClassifiedItem(); - - LLVector3d pos; - if (pick_item) - pos = pick_item->getPosGlobal(); - else if(c_item) - { - LLPanelClassifiedInfo::sendClickMessage("map", false, - c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); - pos = c_item->getPosGlobal(); - } - - LLFloaterWorldMap::getInstance()->trackLocation(pos); - LLFloaterReg::showInstance("world_map", "center"); -} - - -void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) -{ - updateButtons(); - - if (mPopupMenu) - { - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); - ((LLContextMenu*)mPopupMenu)->show(x, y); - LLMenuGL::showPopup(item, mPopupMenu, x, y); - } -} - -void LLPanelPicks::onDoubleClickPickItem(LLUICtrl* item) -{ - LLSD pick_value = mPicksList->getSelectedValue(); - if (pick_value.isUndefined()) return; - - LLSD args; - args["PICK"] = pick_value[PICK_NAME]; - LLNotificationsUtil::add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2)); -} - -void LLPanelPicks::onDoubleClickClassifiedItem(LLUICtrl* item) -{ - LLSD value = mClassifiedsList->getSelectedValue(); - if (value.isUndefined()) return; - - LLSD args; - args["CLASSIFIED"] = value[CLASSIFIED_NAME]; - LLNotificationsUtil::add("TeleportToClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2)); -} - -void LLPanelPicks::updateButtons() -{ - bool has_selected = mPicksList->numSelected() > 0 || mClassifiedsList->numSelected() > 0; - - if (getAvatarId() == gAgentID) - { - getChildView(XML_BTN_DELETE)->setEnabled(has_selected); - } - - getChildView(XML_BTN_INFO)->setEnabled(has_selected); - getChildView(XML_BTN_TELEPORT)->setEnabled(has_selected); - getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(has_selected); - - LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); - if(c_item) - { - getChildView(XML_BTN_INFO)->setEnabled(isClassifiedPublished(c_item)); - } -} - -void LLPanelPicks::updateNoItemsLabel() -{ - bool no_data = mNoPicks && mNoClassifieds; - mNoItemsLabel->setVisible(no_data); - if (no_data) - { - if (getAvatarId() == gAgentID) - { - mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText")); - } - else - { - mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText")); - } - } -} - -void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel) -{ - mProfilePanel = profile_panel; -} - - -void LLPanelPicks::buildPickPanel() -{ -// if (mPickPanel == NULL) -// { -// mPickPanel = new LLPanelPick(); -// mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, NULL)); -// } -} - -void LLPanelPicks::onClickPlusBtn() -{ - LLRect rect(getChildView(XML_BTN_NEW)->getRect()); - - mPlusMenu->updateParent(LLMenuGL::sMenuContainer); - mPlusMenu->setButtonRect(rect, this); - LLMenuGL::showPopup(this, mPlusMenu, rect.mLeft, rect.mTop); -} - -void LLPanelPicks::createNewPick() -{ - createPickEditPanel(); - - getProfilePanel()->openPanel(mPanelPickEdit, LLSD()); -} - -void LLPanelPicks::createNewClassified() -{ - LLPanelClassifiedEdit* panel = NULL; - createClassifiedEditPanel(&panel); - - getProfilePanel()->openPanel(panel, LLSD()); -} - -void LLPanelPicks::onClickInfo() -{ - if(mPicksList->numSelected() > 0) - { - openPickInfo(); - } - else if(mClassifiedsList->numSelected() > 0) - { - openClassifiedInfo(); - } -} - -void LLPanelPicks::openPickInfo() -{ - LLSD selected_value = mPicksList->getSelectedValue(); - if (selected_value.isUndefined()) return; - - LLPickItem* pick = (LLPickItem*)mPicksList->getSelectedItem(); - - createPickInfoPanel(); - - LLSD params; - params["pick_id"] = pick->getPickId(); - params["avatar_id"] = pick->getCreatorId(); - params["snapshot_id"] = pick->getSnapshotId(); - params["pick_name"] = pick->getPickName(); - params["pick_desc"] = pick->getPickDesc(); - - getProfilePanel()->openPanel(mPanelPickInfo, params); -} - -void LLPanelPicks::openClassifiedInfo() -{ - LLSD selected_value = mClassifiedsList->getSelectedValue(); - if (selected_value.isUndefined()) return; - - LLClassifiedItem* c_item = getSelectedClassifiedItem(); - LLSD params; - params["classified_id"] = c_item->getClassifiedId(); - params["classified_creator_id"] = c_item->getAvatarId(); - params["classified_snapshot_id"] = c_item->getSnapshotId(); - params["classified_name"] = c_item->getClassifiedName(); - params["classified_desc"] = c_item->getDescription(); - params["from_search"] = false; - - openClassifiedInfo(params); -} - -void LLPanelPicks::openClassifiedInfo(const LLSD ¶ms) -{ - createClassifiedInfoPanel(); - getProfilePanel()->openPanel(mPanelClassifiedInfo, params); -} - -void LLPanelPicks::openClassifiedEdit(const LLSD& params) -{ - LLUUID classified_id = params["classified_id"].asUUID();; - LL_INFOS() << "opening classified " << classified_id << " for edit" << LL_ENDL; - editClassified(classified_id); -} - -void LLPanelPicks::showAccordion(const std::string& name, bool show) -{ - LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); - tab->setVisible(show); - LLAccordionCtrl* acc = getChild<LLAccordionCtrl>("accordion"); - acc->arrange(); -} - -void LLPanelPicks::onPanelPickClose(LLPanel* panel) -{ - getProfilePanel()->closePanel(panel); -} - -void LLPanelPicks::onPanelPickSave(LLPanel* panel) -{ - onPanelPickClose(panel); - updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel) -{ - if(!panel->canClose()) - { - return; - } - - if(panel->isNew()) - { - mEditClassifiedPanels[panel->getClassifiedId()] = panel; - - LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); - c_item->fillIn(panel); - - LLSD c_value; - c_value.insert(CLASSIFIED_ID, c_item->getClassifiedId()); - c_value.insert(CLASSIFIED_NAME, c_item->getClassifiedName()); - mClassifiedsList->addItem(c_item, c_value, ADD_TOP); - - c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); - c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); - c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); - c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); - - // order does matter, showAccordion will invoke arrange for accordions. - mClassifiedsAccTab->changeOpenClose(false); - showAccordion("tab_classifieds", true); - } - else if(panel->isNewWithErrors()) - { - LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); - llassert(c_item); - if (c_item) - { - c_item->fillIn(panel); - } - } - else - { - onPanelClassifiedClose(panel); - return; - } - - onPanelPickClose(panel); - updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedClose(LLPanelClassifiedInfo* panel) -{ - if(panel->getInfoLoaded() && !panel->isDirty()) - { - std::vector<LLSD> values; - mClassifiedsList->getValues(values); - for(size_t n = 0; n < values.size(); ++n) - { - LLUUID c_id = values[n][CLASSIFIED_ID].asUUID(); - if(panel->getClassifiedId() == c_id) - { - LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>( - mClassifiedsList->getItemByValue(values[n])); - llassert(c_item); - if (c_item) - { - c_item->setClassifiedName(panel->getClassifiedName()); - c_item->setDescription(panel->getDescription()); - c_item->setSnapshotId(panel->getSnapshotId()); - } - } - } - } - - onPanelPickClose(panel); - updateButtons(); -} - -void LLPanelPicks::createPickInfoPanel() -{ - if(!mPanelPickInfo) - { - mPanelPickInfo = LLPanelPickInfo::create(); - mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); - mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); - mPanelPickInfo->setVisible(FALSE); - } -} - -void LLPanelPicks::createClassifiedInfoPanel() -{ - mPanelClassifiedInfo = LLPanelClassifiedInfo::create(); - mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo)); - mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this)); - mPanelClassifiedInfo->setVisible(FALSE); -} - -void LLPanelPicks::createClassifiedEditPanel(LLPanelClassifiedEdit** panel) -{ - if(panel) - { - LLPanelClassifiedEdit* new_panel = LLPanelClassifiedEdit::create(); - new_panel->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); - new_panel->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, new_panel)); - new_panel->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); - new_panel->setVisible(FALSE); - *panel = new_panel; - } -} - -void LLPanelPicks::createPickEditPanel() -{ - mPanelPickEdit = LLPanelPickEdit::create(); - mPanelPickEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); - mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickSave, this, mPanelPickEdit)); - mPanelPickEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); - mPanelPickEdit->setVisible(FALSE); -} - -// void LLPanelPicks::openPickEditPanel(LLPickItem* pick) -// { -// if(!pick) -// { -// return; -// } -// } - -// void LLPanelPicks::openPickInfoPanel(LLPickItem* pick) -// { -// if(!mPanelPickInfo) -// { -// mPanelPickInfo = LLPanelPickInfo::create(); -// mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); -// mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); -// mPanelPickInfo->setVisible(FALSE); -// } -// -// LLSD params; -// params["pick_id"] = pick->getPickId(); -// params["avatar_id"] = pick->getCreatorId(); -// params["snapshot_id"] = pick->getSnapshotId(); -// params["pick_name"] = pick->getPickName(); -// params["pick_desc"] = pick->getPickDesc(); -// -// getProfilePanel()->openPanel(mPanelPickInfo, params); -// } - -void LLPanelPicks::openPickEdit(const LLSD& params) -{ - createPickEditPanel(); - getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelPickEdit() -{ - LLSD selected_value = mPicksList->getSelectedValue(); - if (selected_value.isUndefined()) return; - - LLPickItem* pick = dynamic_cast<LLPickItem*>(mPicksList->getSelectedItem()); - - createPickEditPanel(); - - LLSD params; - params["pick_id"] = pick->getPickId(); - params["avatar_id"] = pick->getCreatorId(); - params["snapshot_id"] = pick->getSnapshotId(); - params["pick_name"] = pick->getPickName(); - params["pick_desc"] = pick->getPickDesc(); - - getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelClassifiedEdit() -{ - LLSD selected_value = mClassifiedsList->getSelectedValue(); - if (selected_value.isUndefined()) - { - return; - } - - LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); - llassert(c_item); - if (!c_item) - { - return; - } - editClassified(c_item->getClassifiedId()); -} - -LLClassifiedItem *LLPanelPicks::findClassifiedById(const LLUUID& classified_id) -{ - // HACK - find item by classified id. Should be a better way. - std::vector<LLPanel*> items; - mClassifiedsList->getItems(items); - LLClassifiedItem* c_item = NULL; - for(std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) - { - LLClassifiedItem *test_item = dynamic_cast<LLClassifiedItem*>(*it); - if (test_item && test_item->getClassifiedId() == classified_id) - { - c_item = test_item; - break; - } - } - return c_item; -} - -void LLPanelPicks::editClassified(const LLUUID& classified_id) -{ - LLClassifiedItem* c_item = findClassifiedById(classified_id); - if (!c_item) - { - LL_WARNS() << "item not found for classified_id " << classified_id << LL_ENDL; - return; - } - - LLSD params; - params["classified_id"] = c_item->getClassifiedId(); - params["classified_creator_id"] = c_item->getAvatarId(); - params["snapshot_id"] = c_item->getSnapshotId(); - params["name"] = c_item->getClassifiedName(); - params["desc"] = c_item->getDescription(); - params["category"] = (S32)c_item->getCategory(); - params["content_type"] = (S32)c_item->getContentType(); - params["auto_renew"] = c_item->getAutoRenew(); - params["price_for_listing"] = c_item->getPriceForListing(); - params["location_text"] = c_item->getLocationText(); - - LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; - if(!panel) - { - createClassifiedEditPanel(&panel); - mEditClassifiedPanels[c_item->getClassifiedId()] = panel; - } - getProfilePanel()->openPanel(panel, params); - panel->setPosGlobal(c_item->getPosGlobal()); -} - -void LLPanelPicks::onClickMenuEdit() -{ - if(getSelectedPickItem()) - { - onPanelPickEdit(); - } - else if(getSelectedClassifiedItem()) - { - onPanelClassifiedEdit(); - } -} - -bool LLPanelPicks::onEnableMenuItem(const LLSD& user_data) -{ - std::string param = user_data.asString(); - - LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); - if(c_item && "info" == param) - { - // dont show Info panel if classified was not created - return isClassifiedPublished(c_item); - } - - return true; -} - -inline LLPanelProfile* LLPanelPicks::getProfilePanel() -{ - llassert_always(NULL != mProfilePanel); - return mProfilePanel; -} - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPickItem::LLPickItem() -: LLPanel() -, mPickID(LLUUID::null) -, mCreatorID(LLUUID::null) -, mParcelID(LLUUID::null) -, mSnapshotID(LLUUID::null) -, mNeedData(true) -{ - buildFromFile("panel_pick_list_item.xml"); -} - -LLPickItem::~LLPickItem() -{ - if (mCreatorID.notNull()) - { - LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); - } - -} - -LLPickItem* LLPickItem::create() -{ - return new LLPickItem(); -} - -void LLPickItem::init(LLPickData* pick_data) -{ - setPickDesc(pick_data->desc); - setSnapshotId(pick_data->snapshot_id); - mPosGlobal = pick_data->pos_global; - mSimName = pick_data->sim_name; - mPickDescription = pick_data->desc; - mUserName = pick_data->user_name; - mOriginalName = pick_data->original_name; - - LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture"); - picture->setImageAssetID(pick_data->snapshot_id); -} - -void LLPickItem::setPickName(const std::string& name) -{ - mPickName = name; - getChild<LLUICtrl>("picture_name")->setValue(name); - -} - -const std::string& LLPickItem::getPickName() -{ - return mPickName; -} - -const LLUUID& LLPickItem::getCreatorId() -{ - return mCreatorID; -} - -const LLUUID& LLPickItem::getSnapshotId() -{ - return mSnapshotID; -} - -void LLPickItem::setPickDesc(const std::string& descr) -{ - getChild<LLUICtrl>("picture_descr")->setValue(descr); -} - -void LLPickItem::setPickId(const LLUUID& id) -{ - mPickID = id; -} - -const LLUUID& LLPickItem::getPickId() -{ - return mPickID; -} - -const LLVector3d& LLPickItem::getPosGlobal() -{ - return mPosGlobal; -} - -const std::string LLPickItem::getDescription() -{ - return getChild<LLUICtrl>("picture_descr")->getValue().asString(); -} - -void LLPickItem::update() -{ - setNeedData(true); - LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID); -} - -void LLPickItem::processProperties(void *data, EAvatarProcessorType type) -{ - if (APT_PICK_INFO != type) - { - return; - } - - LLPickData* pick_data = static_cast<LLPickData *>(data); - if (!pick_data || mPickID != pick_data->pick_id) - { - return; - } - - init(pick_data); - setNeedData(false); - LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); -} - -void set_child_visible(LLView* parent, const std::string& child_name, bool visible) -{ - parent->getChildView(child_name)->setVisible(visible); -} - -BOOL LLPickItem::postBuild() -{ - setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); - setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); - return TRUE; -} - -void LLPickItem::setValue(const LLSD& value) -{ - if (!value.isMap()) return;; - if (!value.has("selected")) return; - getChildView("selected_icon")->setVisible( value["selected"]); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id) - : LLPanel() - , mAvatarId(avatar_id) - , mClassifiedId(classified_id) -{ - buildFromFile("panel_classifieds_list_item.xml"); - - LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); - LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); -} - -LLClassifiedItem::~LLClassifiedItem() -{ - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_CLASSIFIED_INFO != type) - { - return; - } - - LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); - if( !c_info || c_info->classified_id != getClassifiedId() ) - { - return; - } - - setClassifiedName(c_info->name); - setDescription(c_info->description); - setSnapshotId(c_info->snapshot_id); - setPosGlobal(c_info->pos_global); - - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -BOOL LLClassifiedItem::postBuild() -{ - setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); - setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); - return TRUE; -} - -void LLClassifiedItem::setValue(const LLSD& value) -{ - if (!value.isMap()) return;; - if (!value.has("selected")) return; - getChildView("selected_icon")->setVisible( value["selected"]); -} - -void LLClassifiedItem::fillIn(LLPanelClassifiedEdit* panel) -{ - if(!panel) - { - return; - } - - setClassifiedName(panel->getClassifiedName()); - setDescription(panel->getDescription()); - setSnapshotId(panel->getSnapshotId()); - setCategory(panel->getCategory()); - setContentType(panel->getContentType()); - setAutoRenew(panel->getAutoRenew()); - setPriceForListing(panel->getPriceForListing()); - setPosGlobal(panel->getPosGlobal()); - setLocationText(panel->getClassifiedLocation()); -} - -void LLClassifiedItem::setClassifiedName(const std::string& name) -{ - getChild<LLUICtrl>("name")->setValue(name); -} - -void LLClassifiedItem::setDescription(const std::string& desc) -{ - getChild<LLUICtrl>("description")->setValue(desc); -} - -void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id) -{ - getChild<LLUICtrl>("picture")->setValue(snapshot_id); -} - -LLUUID LLClassifiedItem::getSnapshotId() -{ - return getChild<LLUICtrl>("picture")->getValue(); -} - -//EOF diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h deleted file mode 100644 index fd7688b99d..0000000000 --- a/indra/newview/llpanelpicks.h +++ /dev/null @@ -1,315 +0,0 @@ -/** - * @file llpanelpicks.h - * @brief LLPanelPicks and related class definitions - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPANELPICKS_H -#define LL_LLPANELPICKS_H - -#include "llpanel.h" -#include "v3dmath.h" -#include "lluuid.h" -#include "llavatarpropertiesprocessor.h" -#include "llpanelavatar.h" -#include "llregistry.h" - -class LLAccordionCtrlTab; -class LLPanelProfile; -class LLMessageSystem; -class LLVector3d; -class LLPanelProfileTab; -class LLAgent; -class LLMenuGL; -class LLPickItem; -class LLClassifiedItem; -class LLFlatListView; -class LLPanelPickInfo; -class LLPanelPickEdit; -class LLToggleableMenu; -class LLPanelClassifiedInfo; -class LLPanelClassifiedEdit; - -// *TODO -// Panel Picks has been consolidated with Classifieds (EXT-2095), give LLPanelPicks -// and corresponding files (cpp, h, xml) a new name. (new name is TBD at the moment) - -class LLPanelPicks - : public LLPanelProfileTab -{ -public: - LLPanelPicks(); - ~LLPanelPicks(); - - static void* create(void* data); - - /*virtual*/ BOOL postBuild(void); - - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ void onClosePanel(); - - void processProperties(void* data, EAvatarProcessorType type); - - void updateData(); - - // returns the selected pick item - LLPickItem* getSelectedPickItem(); - LLClassifiedItem* getSelectedClassifiedItem(); - LLClassifiedItem* findClassifiedById(const LLUUID& classified_id); - - //*NOTE top down approch when panel toggling is done only by - // parent panels failed to work (picks related code was in my profile panel) - void setProfilePanel(LLPanelProfile* profile_panel); - - void createNewPick(); - void createNewClassified(); - -protected: - /*virtual*/void updateButtons(); - void updateNoItemsLabel(); - -private: - void onClickDelete(); - void onClickTeleport(); - void onClickMap(); - - void onPlusMenuItemClicked(const LLSD& param); - bool isActionEnabled(const LLSD& userdata) const; - - bool isClassifiedPublished(LLClassifiedItem* c_item); - - void onListCommit(const LLFlatListView* f_list); - void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); - - //------------------------------------------------ - // Callbacks which require panel toggling - //------------------------------------------------ - void onClickPlusBtn(); - void onClickInfo(); - void onPanelPickClose(LLPanel* panel); - void onPanelPickSave(LLPanel* panel); - void onPanelClassifiedSave(LLPanelClassifiedEdit* panel); - void onPanelClassifiedClose(LLPanelClassifiedInfo* panel); - void openPickEdit(const LLSD& params); - void onPanelPickEdit(); - void onPanelClassifiedEdit(); - void editClassified(const LLUUID& classified_id); - void onClickMenuEdit(); - - bool onEnableMenuItem(const LLSD& user_data); - - void openPickInfo(); - void openClassifiedInfo(); - void openClassifiedInfo(const LLSD& params); - void openClassifiedEdit(const LLSD& params); - friend class LLPanelProfile; - - void showAccordion(const std::string& name, bool show); - - void buildPickPanel(); - - bool callbackDeletePick(const LLSD& notification, const LLSD& response); - bool callbackDeleteClassified(const LLSD& notification, const LLSD& response); - bool callbackTeleport(const LLSD& notification, const LLSD& response); - - - virtual void onDoubleClickPickItem(LLUICtrl* item); - virtual void onDoubleClickClassifiedItem(LLUICtrl* item); - virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); - - LLPanelProfile* getProfilePanel(); - - void createPickInfoPanel(); - void createPickEditPanel(); - void createClassifiedInfoPanel(); - void createClassifiedEditPanel(LLPanelClassifiedEdit** panel); - - LLMenuGL* mPopupMenu; - LLPanelProfile* mProfilePanel; - LLPanelPickInfo* mPickPanel; - LLFlatListView* mPicksList; - LLFlatListView* mClassifiedsList; - LLPanelPickInfo* mPanelPickInfo; - LLPanelClassifiedInfo* mPanelClassifiedInfo; - LLPanelPickEdit* mPanelPickEdit; - LLToggleableMenu* mPlusMenu; - LLUICtrl* mNoItemsLabel; - - // <classified_id, edit_panel> - typedef std::map<LLUUID, LLPanelClassifiedEdit*> panel_classified_edit_map_t; - - // This map is needed for newly created classifieds. The purpose of panel is to - // sit in this map and listen to LLPanelClassifiedEdit::processProperties callback. - panel_classified_edit_map_t mEditClassifiedPanels; - - LLAccordionCtrlTab* mPicksAccTab; - LLAccordionCtrlTab* mClassifiedsAccTab; - - //true if picks list is empty after processing picks - bool mNoPicks; - //true if classifieds list is empty after processing classifieds - bool mNoClassifieds; -}; - -class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - - LLPickItem(); - - static LLPickItem* create(); - - void init(LLPickData* pick_data); - - void setPickName(const std::string& name); - - void setPickDesc(const std::string& descr); - - void setPickId(const LLUUID& id); - - void setCreatorId(const LLUUID& id) {mCreatorID = id;}; - - void setSnapshotId(const LLUUID& id) {mSnapshotID = id;}; - - void setNeedData(bool need){mNeedData = need;}; - - const LLUUID& getPickId(); - - const std::string& getPickName(); - - const LLUUID& getCreatorId(); - - const LLUUID& getSnapshotId(); - - const LLVector3d& getPosGlobal(); - - const std::string getDescription(); - - const std::string& getSimName() { return mSimName; } - - const std::string& getUserName() { return mUserName; } - - const std::string& getOriginalName() { return mOriginalName; } - - const std::string& getPickDesc() { return mPickDescription; } - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - void update(); - - ~LLPickItem(); - - /*virtual*/ BOOL postBuild(); - - /** setting on/off background icon to indicate selected state */ - /*virtual*/ void setValue(const LLSD& value); - -protected: - - LLUUID mPickID; - LLUUID mCreatorID; - LLUUID mParcelID; - LLUUID mSnapshotID; - LLVector3d mPosGlobal; - bool mNeedData; - - std::string mPickName; - std::string mUserName; - std::string mOriginalName; - std::string mPickDescription; - std::string mSimName; -}; - -class LLClassifiedItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - - LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id); - - virtual ~LLClassifiedItem(); - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void setValue(const LLSD& value); - - void fillIn(LLPanelClassifiedEdit* panel); - - LLUUID getAvatarId() {return mAvatarId;} - - void setAvatarId(const LLUUID& avatar_id) {mAvatarId = avatar_id;} - - LLUUID getClassifiedId() {return mClassifiedId;} - - void setClassifiedId(const LLUUID& classified_id) {mClassifiedId = classified_id;} - - void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } - - const LLVector3d getPosGlobal() { return mPosGlobal; } - - void setLocationText(const std::string location) { mLocationText = location; } - - std::string getLocationText() { return mLocationText; } - - void setClassifiedName (const std::string& name); - - std::string getClassifiedName() { return getChild<LLUICtrl>("name")->getValue().asString(); } - - void setDescription(const std::string& desc); - - std::string getDescription() { return getChild<LLUICtrl>("description")->getValue().asString(); } - - void setSnapshotId(const LLUUID& snapshot_id); - - LLUUID getSnapshotId(); - - void setCategory(U32 cat) { mCategory = cat; } - - U32 getCategory() { return mCategory; } - - void setContentType(U32 ct) { mContentType = ct; } - - U32 getContentType() { return mContentType; } - - void setAutoRenew(U32 renew) { mAutoRenew = renew; } - - bool getAutoRenew() { return mAutoRenew; } - - void setPriceForListing(S32 price) { mPriceForListing = price; } - - S32 getPriceForListing() { return mPriceForListing; } - -private: - LLUUID mAvatarId; - LLUUID mClassifiedId; - LLVector3d mPosGlobal; - std::string mLocationText; - U32 mCategory; - U32 mContentType; - bool mAutoRenew; - S32 mPriceForListing; -}; - -#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 9157df789f..fb5957ff8f 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -27,6 +27,8 @@ #include "llviewerprecompiledheaders.h" #include "llpanelplaceinfo.h" +#include "llfloaterprofile.h" +#include "llfloaterreg.h" #include "llavatarname.h" #include "llsdutil.h" @@ -42,7 +44,6 @@ #include "llagent.h" #include "llexpandabletextbox.h" -#include "llpanelpick.h" #include "llslurl.h" #include "lltexturectrl.h" #include "llviewerregion.h" @@ -287,7 +288,7 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent) } } -void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel) +void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global) { LLPickData data; data.pos_global = pos_global; @@ -296,7 +297,12 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* data.desc = mDescEditor->getText(); data.snapshot_id = mSnapshotCtrl->getImageAssetID(); data.parcel_id = mParcelID; - pick_panel->setPickData(&data); + + LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgentID))); + if (profile_floater) + { + profile_floater->createPick(data); + } } // static diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 8bf67cfe7d..533215016a 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -38,7 +38,6 @@ class LLAvatarName; class LLExpandableTextBox; class LLIconCtrl; class LLInventoryItem; -class LLPanelPickEdit; class LLParcel; class LLScrollContainer; class LLTextBox; @@ -94,7 +93,7 @@ public: // Create a pick for the location specified // by global_pos. - void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel); + void createPick(const LLVector3d& pos_global); protected: static void onNameCache(LLTextBox* text, const std::string& full_name); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 69f181e1b3..74ec576554 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -63,7 +63,6 @@ #include "lllayoutstack.h" #include "llpanellandmarkinfo.h" #include "llpanellandmarks.h" -#include "llpanelpick.h" #include "llpanelplaceprofile.h" #include "llpanelteleporthistory.h" #include "llremoteparcelrequest.h" @@ -238,7 +237,6 @@ LLPanelPlaces::LLPanelPlaces() mFilterEditor(NULL), mPlaceProfile(NULL), mLandmarkInfo(NULL), - mPickPanel(NULL), mItem(NULL), mPlaceMenu(NULL), mLandmarkMenu(NULL), @@ -952,28 +950,11 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) } else if (item == "pick") { - if (mPickPanel == NULL) - { - mPickPanel = LLPanelPickEdit::create(); - addChild(mPickPanel); - - mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); - mPickPanel->setCancelCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); - mPickPanel->setSaveCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); - } - - togglePickPanel(TRUE); - mPickPanel->onOpen(LLSD()); - LLPanelPlaceInfo* panel = getCurrentInfoPanel(); if (panel) { - panel->createPick(mPosGlobal, mPickPanel); + panel->createPick(mPosGlobal); } - - LLRect rect = getRect(); - mPickPanel->reshape(rect.getWidth(), rect.getHeight()); - mPickPanel->setRect(rect); } else if (item == "add_to_favbar") { @@ -1050,17 +1031,6 @@ bool LLPanelPlaces::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_t return false; } -void LLPanelPlaces::togglePickPanel(BOOL visible) -{ - if (mPickPanel) - { - mPickPanel->setVisible(visible); - mPlaceProfile->setVisible(!visible); - updateVerbs(); - } - -} - void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) { if (!mPlaceProfile || !mLandmarkInfo) @@ -1309,15 +1279,11 @@ void LLPanelPlaces::updateVerbs() bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE; bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; - bool is_pick_panel_visible = false; - if(mPickPanel) - { - is_pick_panel_visible = mPickPanel->isInVisibleChain(); - } + bool have_3d_pos = ! mPosGlobal.isExactlyZero(); - mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); - mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); + mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); + mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); mSaveBtn->setVisible(isLandmarkEditModeOn); mCancelBtn->setVisible(isLandmarkEditModeOn); mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 3b87eb6cb9..e554099343 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -38,7 +38,6 @@ class LLLandmark; class LLPanelLandmarkInfo; class LLPanelPlaceProfile; -class LLPanelPickEdit; class LLPanelPlaceInfo; class LLPanelPlacesTab; class LLParcelSelection; @@ -95,7 +94,6 @@ private: void onOverflowButtonClicked(); void onOverflowMenuItemClicked(const LLSD& param); bool onOverflowMenuItemEnable(const LLSD& param); - void onCreateLandmarkButtonClicked(const LLUUID& folder_id); void onBackButtonClicked(); void onGearMenuClick(); void onSortingMenuClick(); @@ -103,9 +101,6 @@ private: void onRemoveButtonClicked(); bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept); - - void toggleMediaPanel(); - void togglePickPanel(BOOL visible); void togglePlaceInfoPanel(BOOL visible); /*virtual*/ void onVisibilityChange(BOOL new_visibility); @@ -122,7 +117,6 @@ private: LLPanelPlaceProfile* mPlaceProfile; LLPanelLandmarkInfo* mLandmarkInfo; - LLPanelPickEdit* mPickPanel; LLToggleableMenu* mPlaceMenu; LLToggleableMenu* mLandmarkMenu; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 5f13b223fb..f4eaa78f11 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llpanelprofile.cpp * @brief Profile panel implementation * -* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* +* Copyright (C) 2022, Linden Research, Inc. +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -27,32 +27,433 @@ #include "llviewerprecompiledheaders.h" #include "llpanelprofile.h" -#include "llagent.h" +// Common +#include "llavatarnamecache.h" +#include "llsdutil.h" +#include "llslurl.h" +#include "lldateutil.h" //ageFromDate + +// UI +#include "llavatariconctrl.h" +#include "llclipboard.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lllineeditor.h" +#include "llloadingindicator.h" +#include "llmenubutton.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltoggleablemenu.h" +#include "llgrouplist.h" +#include "llurlaction.h" + +// Image +#include "llimagej2c.h" + +// Newview +#include "llagent.h" //gAgent +#include "llagentpicksinfo.h" #include "llavataractions.h" -#include "llfloaterreg.h" +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" #include "llcommandhandler.h" -#include "llnotificationsutil.h" -#include "llpanelpicks.h" -#include "lltabcontainer.h" -#include "llviewercontrol.h" -#include "llviewernetwork.h" +#include "llfloaterprofiletexture.h" +#include "llfloaterreg.h" +#include "llfloaterreporter.h" +#include "llfilepicker.h" +#include "llfirstuse.h" +#include "llgroupactions.h" +#include "lllogchat.h" #include "llmutelist.h" +#include "llnotificationsutil.h" #include "llpanelblockedlist.h" +#include "llpanelprofileclassifieds.h" +#include "llpanelprofilepicks.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" //is_agent_mappable +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h" #include "llweb.h" -static const std::string PANEL_PICKS = "panel_picks"; -std::string getProfileURL(const std::string& agent_name) +static LLPanelInjector<LLPanelProfileSecondLife> t_panel_profile_secondlife("panel_profile_secondlife"); +static LLPanelInjector<LLPanelProfileWeb> t_panel_web("panel_profile_web"); +static LLPanelInjector<LLPanelProfilePicks> t_panel_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfileFirstLife> t_panel_firstlife("panel_profile_firstlife"); +static LLPanelInjector<LLPanelProfileNotes> t_panel_notes("panel_profile_notes"); +static LLPanelInjector<LLPanelProfile> t_panel_profile("panel_profile"); + +static const std::string PANEL_SECONDLIFE = "panel_profile_secondlife"; +static const std::string PANEL_WEB = "panel_profile_web"; +static const std::string PANEL_PICKS = "panel_profile_picks"; +static const std::string PANEL_CLASSIFIEDS = "panel_profile_classifieds"; +static const std::string PANEL_FIRSTLIFE = "panel_profile_firstlife"; +static const std::string PANEL_NOTES = "panel_profile_notes"; +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; +static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; + + +////////////////////////////////////////////////////////////////////////// + +void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) { - std::string url = "[WEB_PROFILE_URL][AGENT_NAME]"; - LLSD subs; - subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); - subs["AGENT_NAME"] = agent_name; - url = LLWeb::expandURLSubstitutions(url, subs); - LLStringUtil::toLower(url); - return url; + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("request_avatar_properties_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + std::string finalUrl = cap_url + "/" + agent_id.asString(); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Result: " << httpResults << LL_ENDL; + + if (!status + || !result.has("id") + || agent_id != result["id"].asUUID()) + { + LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; + return; + } + + LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", agent_id)); + if (!floater_profile) + { + // floater is dead, so panels are dead as well + return; + } + + LLPanel *panel = floater_profile->findChild<LLPanel>(PANEL_PROFILE_VIEW, TRUE); + LLPanelProfile *panel_profile = dynamic_cast<LLPanelProfile*>(panel); + if (!panel_profile) + { + LL_WARNS() << PANEL_PROFILE_VIEW << " not found" << LL_ENDL; + return; + } + + + // Avatar Data + + LLAvatarData *avatar_data = &panel_profile->mAvatarData; + std::string birth_date; + + avatar_data->agent_id = agent_id; + avatar_data->avatar_id = agent_id; + avatar_data->image_id = result["sl_image_id"].asUUID(); + avatar_data->fl_image_id = result["fl_image_id"].asUUID(); + avatar_data->partner_id = result["partner_id"].asUUID(); + avatar_data->about_text = result["sl_about_text"].asString(); + avatar_data->fl_about_text = result["fl_about_text"].asString(); + avatar_data->born_on = result["member_since"].asDate(); + avatar_data->profile_url = getProfileURL(agent_id.asString()); + + avatar_data->flags = 0; + + if (result["online"].asBoolean()) + { + avatar_data->flags |= AVATAR_ONLINE; + } + if (result["allow_publish"].asBoolean()) + { + avatar_data->flags |= AVATAR_ALLOW_PUBLISH; + } + if (result["identified"].asBoolean()) + { + avatar_data->flags |= AVATAR_IDENTIFIED; + } + if (result["transacted"].asBoolean()) + { + avatar_data->flags |= AVATAR_TRANSACTED; + } + + avatar_data->caption_index = 0; + if (result.has("charter_member")) // won't be present if "caption" is set + { + avatar_data->caption_index = result["charter_member"].asInteger(); + } + else if (result.has("caption")) + { + avatar_data->caption_text = result["caption"].asString(); + } + + panel = floater_profile->findChild<LLPanel>(PANEL_SECONDLIFE, TRUE); + LLPanelProfileSecondLife *panel_sl = dynamic_cast<LLPanelProfileSecondLife*>(panel); + if (panel_sl) + { + panel_sl->processProfileProperties(avatar_data); + } + + panel = floater_profile->findChild<LLPanel>(PANEL_WEB, TRUE); + LLPanelProfileWeb *panel_web = dynamic_cast<LLPanelProfileWeb*>(panel); + if (panel_web) + { + panel_web->setLoaded(); + } + + panel = floater_profile->findChild<LLPanel>(PANEL_FIRSTLIFE, TRUE); + LLPanelProfileFirstLife *panel_first = dynamic_cast<LLPanelProfileFirstLife*>(panel); + if (panel_first) + { + panel_first->processProperties(avatar_data); + } + + // Picks + + LLSD picks_array = result["picks"]; + LLAvatarPicks avatar_picks; + avatar_picks.agent_id = agent_id; // Not in use? + avatar_picks.target_id = agent_id; + + for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) + { + const LLSD& pick_data = *it; + avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); + } + + panel = floater_profile->findChild<LLPanel>(PANEL_PICKS, TRUE); + LLPanelProfilePicks *panel_picks = dynamic_cast<LLPanelProfilePicks*>(panel); + if (panel_picks) + { + // Refresh pick limit before processing + LLAgentPicksInfo::getInstance()->onServerRespond(&avatar_picks); + panel_picks->processProperties(&avatar_picks); + } + + // Groups + + LLSD groups_array = result["groups"]; + LLAvatarGroups avatar_groups; + avatar_groups.agent_id = agent_id; // Not in use? + avatar_groups.avatar_id = agent_id; // target_id + + for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) + { + const LLSD& group_info = *it; + LLAvatarGroups::LLGroupData group_data; + group_data.group_powers = 0; // Not in use? + group_data.group_title = group_info["name"].asString(); // Missing data, not in use? + group_data.group_id = group_info["id"].asUUID(); + group_data.group_name = group_info["name"].asString(); + group_data.group_insignia_id = group_info["image_id"].asUUID(); + + avatar_groups.group_list.push_back(group_data); + } + + if (panel_sl) + { + panel_sl->processGroupProperties(&avatar_groups); + } + + // Notes + LLAvatarNotes avatar_notes; + + avatar_notes.agent_id = agent_id; + avatar_notes.target_id = agent_id; + avatar_notes.notes = result["notes"].asString(); + + panel = floater_profile->findChild<LLPanel>(PANEL_NOTES, TRUE); + LLPanelProfileNotes *panel_notes = dynamic_cast<LLPanelProfileNotes*>(panel); + if (panel_notes) + { + panel_notes->processProperties(&avatar_notes); + } +} + +//TODO: changes take two minutes to propagate! +// Add some storage that holds updated data for two minutes +// for new instances to reuse the data +// Profile data is only relevant to won avatar, but notes +// are for everybody +void put_avatar_properties_coro(std::string cap_url, LLUUID agent_id, LLSD data) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + std::string finalUrl = cap_url + "/" + agent_id.asString(); + + LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("AvatarProperties") << "Failed to put agent information " << data << " for id " << agent_id << LL_ENDL; + return; + } + + LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Data: " << data << " Result: " << httpResults << LL_ENDL; +} + +LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle<LLPanel> *handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; + return LLUUID::null; + } + if (!result.has("uploader")) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; + return LLUUID::null; + } + std::string uploader_cap = result["uploader"].asString(); + if (uploader_cap.empty()) + { + LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL; + return LLUUID::null; + } + + // Upload the image + + LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); + LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); + S64 length; + + { + llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); + if (!instream.is_open()) + { + LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; + return LLUUID::null; + } + length = instream.tellg(); + } + + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! + uploaderhttpOpts->setFollowRedirects(true); + + result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); + + httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LL_WARNS("AvatarProperties") << result << LL_ENDL; + + if (!status) + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; + return LLUUID::null; + } + + if (result["state"].asString() != "complete") + { + if (result.has("message")) + { + LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; + } + else + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; + } + return LLUUID::null; + } + + return result["new_asset"].asUUID(); } +enum EProfileImageType +{ + PROFILE_IMAGE_SL, + PROFILE_IMAGE_FL, +}; + +void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image, LLHandle<LLPanel> *handle) +{ + LLSD data; + switch (type) + { + case PROFILE_IMAGE_SL: + data["profile-image-asset"] = "sl_image_id"; + break; + case PROFILE_IMAGE_FL: + data["profile-image-asset"] = "fl_image_id"; + break; + } + + LLUUID result = post_profile_image(cap_url, data, path_to_image, handle); + + // reset loading indicator + if (!handle->isDead()) + { + switch (type) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast<LLPanelProfileFirstLife*>(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + } + } + + // Cleanup + LLFile::remove(path_to_image); + delete handle; +} + +////////////////////////////////////////////////////////////////////////// +// LLProfileHandler + class LLProfileHandler : public LLCommandHandler { public: @@ -73,6 +474,10 @@ public: }; LLProfileHandler gProfileHandler; + +////////////////////////////////////////////////////////////////////////// +// LLAgentHandler + class LLAgentHandler : public LLCommandHandler { public: @@ -178,279 +583,2070 @@ public: } return true; } + + // reportAbuse is here due to convoluted avatar handling + // in LLScrollListCtrl and LLTextBase + if (verb == "reportAbuse" && web == NULL) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(avatar_id, &av_name)) + { + LLFloaterReporter::showFromAvatar(avatar_id, av_name.getCompleteName()); + } + else + { + LLFloaterReporter::showFromAvatar(avatar_id, "not avaliable"); + } + return true; + } return false; } }; LLAgentHandler gAgentHandler; -//-- LLPanelProfile::ChildStack begins ---------------------------------------- -LLPanelProfile::ChildStack::ChildStack() -: mParent(NULL) +///---------------------------------------------------------------------------- +/// LLFloaterProfilePermissions +///---------------------------------------------------------------------------- + +class LLFloaterProfilePermissions + : public LLFloater + , public LLFriendObserver { +public: + LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); + ~LLFloaterProfilePermissions(); + BOOL postBuild() override; + void onOpen(const LLSD& key) override; + void draw() override; + void changed(U32 mask) override; // LLFriendObserver + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } + + void onApplyRights(); + +private: + void fillRightsData(); + void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); + void confirmModifyRights(bool grant); + void onCommitSeeOnlineRights(); + void onCommitEditRights(); + void onCancel(); + + LLTextBase* mDescription; + LLCheckBoxCtrl* mOnlineStatus; + LLCheckBoxCtrl* mMapRights; + LLCheckBoxCtrl* mEditObjectRights; + LLButton* mOkBtn; + LLButton* mCancelBtn; + + LLUUID mAvatarID; + F32 mContextConeOpacity; + bool mHasUnsavedPermChanges; + LLHandle<LLView> mOwnerHandle; + + boost::signals2::connection mAvatarNameCacheConnection; +}; + +LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) + : LLFloater(LLSD()) + , mAvatarID(avatar_id) + , mContextConeOpacity(0.0f) + , mHasUnsavedPermChanges(false) + , mOwnerHandle(owner->getHandle()) +{ + buildFromFile("floater_profile_permissions.xml"); } -LLPanelProfile::ChildStack::~ChildStack() +LLFloaterProfilePermissions::~LLFloaterProfilePermissions() { - while (mStack.size() != 0) - { - view_list_t& top = mStack.back(); - for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) - { - LLView* viewp = *it; - if (viewp) - { - viewp->die(); - } - } - mStack.pop_back(); - } + mAvatarNameCacheConnection.disconnect(); + if (mAvatarID.notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); + } } -void LLPanelProfile::ChildStack::setParent(LLPanel* parent) +BOOL LLFloaterProfilePermissions::postBuild() { - llassert_always(parent != NULL); - mParent = parent; + mDescription = getChild<LLTextBase>("perm_description"); + mOnlineStatus = getChild<LLCheckBoxCtrl>("online_check"); + mMapRights = getChild<LLCheckBoxCtrl>("map_check"); + mEditObjectRights = getChild<LLCheckBoxCtrl>("objects_check"); + mOkBtn = getChild<LLButton>("perms_btn_ok"); + mCancelBtn = getChild<LLButton>("perms_btn_cancel"); + + mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); + mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); + mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); + mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); + mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); + + return TRUE; } -/// Save current parent's child views and remove them from the child list. -bool LLPanelProfile::ChildStack::push() +void LLFloaterProfilePermissions::onOpen(const LLSD& key) { - view_list_t vlist = *mParent->getChildList(); + if (LLAvatarActions::isFriend(mAvatarID)) + { + LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); + fillRightsData(); + } - for (view_list_t::const_iterator it = vlist.begin(); it != vlist.end(); ++it) - { - LLView* viewp = *it; - mParent->removeChild(viewp); - } + mCancelBtn->setFocus(true); - mStack.push_back(vlist); - dump(); - return true; + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2)); } -/// Restore saved children (adding them back to the child list). -bool LLPanelProfile::ChildStack::pop() +void LLFloaterProfilePermissions::draw() { - if (mStack.size() == 0) - { - LL_WARNS() << "Empty stack" << LL_ENDL; - llassert(mStack.size() == 0); - return false; - } + // drawFrustum + LLView *owner = mOwnerHandle.get(); + static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, owner); + LLFloater::draw(); +} - view_list_t& top = mStack.back(); - for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) - { - LLView* viewp = *it; - mParent->addChild(viewp); - } +void LLFloaterProfilePermissions::changed(U32 mask) +{ + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} - mStack.pop_back(); - dump(); - return true; +void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = av_name.getDisplayName(); + std::string descritpion = getString("description_string", args); + mDescription->setValue(descritpion); } -/// Temporarily add all saved children back. -void LLPanelProfile::ChildStack::preParentReshape() +void LLFloaterProfilePermissions::fillRightsData() { - mSavedStack = mStack; - while(mStack.size() > 0) - { - pop(); - } + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + // If true - we are viewing friend's profile, enable check boxes and set values. + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + + BOOL see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE; + mOnlineStatus->setValue(see_online); + mMapRights->setEnabled(see_online); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } } -/// Add the temporarily saved children back. -void LLPanelProfile::ChildStack::postParentReshape() +void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, + const LLSD& response) { - mStack = mSavedStack; - mSavedStack = stack_t(); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) // canceled + { + mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? FALSE : TRUE); + } + else + { + mHasUnsavedPermChanges = true; + } +} - for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it) - { - const view_list_t& vlist = (*stack_it); - for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) - { - LLView* viewp = *list_it; - LL_DEBUGS() << "removing " << viewp->getName() << LL_ENDL; - mParent->removeChild(viewp); - } - } +void LLFloaterProfilePermissions::confirmModifyRights(bool grant) +{ + LLSD args; + args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); + LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), + boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2)); } -void LLPanelProfile::ChildStack::dump() +void LLFloaterProfilePermissions::onCommitSeeOnlineRights() { - unsigned lvl = 0; - LL_DEBUGS() << "child stack dump:" << LL_ENDL; - for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it, ++lvl) - { - std::ostringstream dbg_line; - dbg_line << "lvl #" << lvl << ":"; - const view_list_t& vlist = (*stack_it); - for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) - { - dbg_line << " " << (*list_it)->getName(); - } - LL_DEBUGS() << dbg_line.str() << LL_ENDL; - } + bool see_online = mOnlineStatus->getValue().asBoolean(); + mMapRights->setEnabled(see_online); + if (see_online) + { + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } + } + else + { + mMapRights->setValue(FALSE); + } + mHasUnsavedPermChanges = true; } -//-- LLPanelProfile::ChildStack ends ------------------------------------------ +void LLFloaterProfilePermissions::onCommitEditRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); -LLPanelProfile::LLPanelProfile() - : LLPanel() - , mAvatarId(LLUUID::null) + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; + closeFloater(); + return; + } + + bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); + + // if modify objects checkbox clicked + if (buddy_relationship->isRightGrantedTo( + LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) + { + confirmModifyRights(allow_modify_objects); + } +} + +void LLFloaterProfilePermissions::onApplyRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; + return; + } + + S32 rights = 0; + + if (mOnlineStatus->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_ONLINE_STATUS; + } + if (mMapRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MAP_LOCATION; + } + if (mEditObjectRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + } + + LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); + + closeFloater(); +} + +void LLFloaterProfilePermissions::onCancel() { - mChildStack.setParent(this); + closeFloater(); } -BOOL LLPanelProfile::postBuild() +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileSecondLife + +LLPanelProfileSecondLife::LLPanelProfileSecondLife() + : LLPanelProfileTab() + , mAvatarNameCacheConnection() + , mHasUnsavedDescriptionChanges(false) + , mWaitingForImageUpload(false) + , mAllowPublish(false) +{ +} + +LLPanelProfileSecondLife::~LLPanelProfileSecondLife() +{ + if (getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + } + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +BOOL LLPanelProfileSecondLife::postBuild() +{ + mGroupList = getChild<LLGroupList>("group_list"); + mShowInSearchCombo = getChild<LLComboBox>("show_in_search"); + mSecondLifePic = getChild<LLIconCtrl>("2nd_life_pic"); + mSecondLifePicLayout = getChild<LLPanel>("image_panel"); + mDescriptionEdit = getChild<LLTextEditor>("sl_description_edit"); + mAgentActionMenuButton = getChild<LLMenuButton>("agent_actions_menu"); + mSaveDescriptionChanges = getChild<LLButton>("save_description_changes"); + mDiscardDescriptionChanges = getChild<LLButton>("discard_description_changes"); + mCanSeeOnlineIcon = getChild<LLIconCtrl>("can_see_online"); + mCantSeeOnlineIcon = getChild<LLIconCtrl>("cant_see_online"); + mCanSeeOnMapIcon = getChild<LLIconCtrl>("can_see_on_map"); + mCantSeeOnMapIcon = getChild<LLIconCtrl>("cant_see_on_map"); + mCanEditObjectsIcon = getChild<LLIconCtrl>("can_edit_objects"); + mCantEditObjectsIcon = getChild<LLIconCtrl>("cant_edit_objects"); + + mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); + mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); }); + mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); }); + mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); + mDiscardDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); + + return TRUE; +} + +void LLPanelProfileSecondLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); + + LLUUID avatar_id = getAvatarId(); + + BOOL own_profile = getSelfProfile(); + + mGroupList->setShowNone(!own_profile); + + childSetVisible("notes_panel", !own_profile); + childSetVisible("settings_panel", own_profile); + childSetVisible("about_buttons_panel", own_profile); + + if (own_profile) + { + // Group list control cannot toggle ForAgent loading + // Less than ideal, but viewing own profile via search is edge case + mGroupList->enableForAgent(false); + } + + // Init menu, menu needs to be created in scope of a registar to work correctly. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; + commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; + enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); + enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); + + if (own_profile) + { + mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + else + { + // Todo: use PeopleContextMenu instead? + mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + + mDescriptionEdit->setParseHTML(!own_profile); + + if (!own_profile) + { + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : TRUE); + updateOnlineStatus(); + fillRightsData(); + } + + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); +} + +void LLPanelProfileSecondLife::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("requestAgentUserInfoCoro", + boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); + } + else + { + LL_WARNS() << "Failed to update profile data, no cap found" << LL_ENDL; + } + } +} + +void LLPanelProfileSecondLife::refreshName() +{ + if (!mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); + } +} + +void LLPanelProfileSecondLife::resetData() +{ + resetLoading(); + + // Set default image and 1:1 dimensions for it + mSecondLifePic->setValue("Generic_Person_Large"); + mImageId = LLUUID::null; + + LLRect imageRect = mSecondLifePicLayout->getRect(); + mSecondLifePicLayout->reshape(imageRect.getHeight(), imageRect.getHeight()); + + setDescriptionText(LLStringUtil::null); + mGroups.clear(); + mGroupList->setGroups(mGroups); + + bool own_profile = getSelfProfile(); + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(!own_profile); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(!own_profile); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(!own_profile); + + mCanSeeOnlineIcon->setEnabled(false); + mCantSeeOnlineIcon->setEnabled(false); + mCanSeeOnMapIcon->setEnabled(false); + mCantSeeOnMapIcon->setEnabled(false); + mCanEditObjectsIcon->setEnabled(false); + mCantEditObjectsIcon->setEnabled(false); + + childSetVisible("partner_layout", FALSE); +} + +void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) +{ + LLUUID avatar_id = getAvatarId(); + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) + { + // Relies onto friend observer to get information about online status updates. + // Once SL-17506 gets implemented, condition might need to become: + // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) + processOnlineStatus(relationship != NULL, + gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), + (avatar_data->flags & AVATAR_ONLINE)); + } + + fillCommonData(avatar_data); + + fillPartnerData(avatar_data); + + fillAccountStatus(avatar_data); + + setLoaded(); +} + +void LLPanelProfileSecondLife::processGroupProperties(const LLAvatarGroups* avatar_groups) +{ + + LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); + const LLAvatarGroups::group_list_t::const_iterator it_end = avatar_groups->group_list.end(); + + for (; it_end != it; ++it) + { + LLAvatarGroups::LLGroupData group_data = *it; + mGroups[group_data.group_name] = group_data.group_id; + } + + mGroupList->setGroups(mGroups); +} + +void LLPanelProfileSecondLife::openGroupProfile() +{ + LLUUID group_id = mGroupList->getSelectedUUID(); + LLGroupActions::show(group_id); +} + +void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + getChild<LLUICtrl>("display_name")->setValue(av_name.getDisplayName()); + getChild<LLUICtrl>("user_name")->setValue(av_name.getAccountName()); +} + +void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) +{ + LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } + mWaitingForImageUpload = loading; +} + +void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mSecondLifePic->setValue(image_asset_id); + mImageId = image_asset_id; + + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(image_asset_id); + if (imagep->getFullHeight()) + { + onImageLoaded(true, imagep); + } + else + { + imagep->setLoadedCallback(onImageLoaded, + MAX_DISCARD_LEVEL, + FALSE, + FALSE, + new LLHandle<LLPanel>(getHandle()), + NULL, + FALSE); + } + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); + if (mImageId.notNull()) + { + texture_view->loadAsset(mImageId); + } + else + { + texture_view->resetAsset(); + } + } + + setProfileImageUploading(false); +} + +bool LLPanelProfileSecondLife::hasUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast<LLFloaterProfilePermissions*>(floater); + if (perm && perm->hasUnsavedChanges()) + { + return true; + } + } + // if floater + return mHasUnsavedDescriptionChanges; +} + +void LLPanelProfileSecondLife::commitUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast<LLFloaterProfilePermissions*>(floater); + if (perm && perm->hasUnsavedChanges()) + { + perm->onApplyRights(); + } + } + if (mHasUnsavedDescriptionChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) +{ + // Refresh avatar id in cache with new info to prevent re-requests + // and to make sure icons in text will be up to date + LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); + + fillAgeData(avatar_data->born_on); + + setDescriptionText(avatar_data->about_text); + + if (avatar_data->image_id.notNull()) + { + mSecondLifePic->setValue(avatar_data->image_id); + mImageId = avatar_data->image_id; + } + else + { + mSecondLifePic->setValue("Generic_Person_Large"); + mImageId = LLUUID::null; + } + + // Will be loaded as a LLViewerFetchedTexture::BOOST_UI due to mSecondLifePic + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(avatar_data->image_id); + if (imagep->getFullHeight()) + { + onImageLoaded(true, imagep); + } + else + { + imagep->setLoadedCallback(onImageLoaded, + MAX_DISCARD_LEVEL, + FALSE, + FALSE, + new LLHandle<LLPanel>(getHandle()), + NULL, + FALSE); + } + + if (getSelfProfile()) + { + mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; + mShowInSearchCombo->setValue((BOOL)mAllowPublish); + } +} + +void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) +{ + LLTextBox* partner_text_ctrl = getChild<LLTextBox>("partner_link"); + if (avatar_data->partner_id.notNull()) + { + childSetVisible("partner_layout", TRUE); + LLStringUtil::format_map_t args; + args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); + std::string partner_text = getString("partner_text", args); + partner_text_ctrl->setText(partner_text); + } + else + { + childSetVisible("partner_layout", FALSE); + } +} + +void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) +{ + LLStringUtil::format_map_t args; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + + std::string caption_text = getString("CaptionTextAcctInfo", args); + getChild<LLUICtrl>("account_info")->setValue(caption_text); +} + +void LLPanelProfileSecondLife::fillRightsData() +{ + if (getSelfProfile()) + { + return; + } + + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + // If true - we are viewing friend's profile, enable check boxes and set values. + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; + bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; + bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; + + mCanSeeOnlineIcon->setVisible(can_see_online); + mCantSeeOnlineIcon->setVisible(!can_see_online); + mCanSeeOnMapIcon->setVisible(can_see_on_map); + mCantSeeOnMapIcon->setVisible(!can_see_on_map); + mCanEditObjectsIcon->setVisible(can_edit_objects); + mCantEditObjectsIcon->setVisible(!can_edit_objects); + + mCanSeeOnlineIcon->setEnabled(true); + mCantSeeOnlineIcon->setEnabled(true); + mCanSeeOnMapIcon->setEnabled(true); + mCantSeeOnMapIcon->setEnabled(true); + mCanEditObjectsIcon->setEnabled(true); + mCantEditObjectsIcon->setEnabled(true); + } + else + { + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(false); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(false); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(false); + } +} + +void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) +{ + std::string name_and_date = getString("date_format"); + LLSD args_name; + args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); + LLStringUtil::format(name_and_date, args_name); + getChild<LLUICtrl>("sl_birth_date")->setValue(name_and_date); + + std::string register_date = getString("age_format"); + LLSD args_age; + args_age["[AGE]"] = LLDateUtil::ageFromDate(born_on, LLDate::now()); + LLStringUtil::format(register_date, args_age); + getChild<LLUICtrl>("user_age")->setValue(register_date); +} + +void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep) +{ + LLRect imageRect = mSecondLifePicLayout->getRect(); + if (!success || imagep->getFullWidth() == imagep->getFullHeight()) + { + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); + } + else + { + // assume 3:4, for sake of firestorm + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); + } +} + +//static +void LLPanelProfileSecondLife::onImageLoaded(BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata) +{ + if (!userdata) return; + + LLHandle<LLPanel>* handle = (LLHandle<LLPanel>*)userdata; + + if (!handle->isDead()) + { + LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get()); + if (panel) + { + panel->onImageLoaded(success, src_vi); + } + } + + if (final || !success) + { + delete handle; + } +} + +// virtual, called by LLAvatarTracker +void LLPanelProfileSecondLife::changed(U32 mask) +{ + updateOnlineStatus(); + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} + +// virtual, called by LLVoiceClient +void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : TRUE); +} + +void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) +{ + if (avatar_id.notNull()) + { + if (getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + + LLPanelProfileTab::setAvatarId(avatar_id); + + if (LLAvatarActions::isFriend(getAvatarId())) + { + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } + } +} + +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 +void LLPanelProfileSecondLife::updateOnlineStatus() +{ + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if (relationship != NULL) + { + // For friend let check if he allowed me to see his status + bool online = relationship->isOnline(); + bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); + processOnlineStatus(true, perm_granted, online); + } + else + { + childSetVisible("frind_layout", false); + childSetVisible("online_layout", false); + childSetVisible("offline_layout", false); + } +} + +void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) +{ + childSetVisible("frind_layout", is_friend); + childSetVisible("online_layout", online && show_online); + childSetVisible("offline_layout", !online && show_online); +} + +void LLPanelProfileSecondLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mShowInSearchCombo->setEnabled(TRUE); + mDescriptionEdit->setEnabled(TRUE); + } +} + + + +class LLProfileImagePicker : public LLFilePickerThread +{ +public: + LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle); + ~LLProfileImagePicker(); + void notify(const std::vector<std::string>& filenames) override; + +private: + LLHandle<LLPanel> *mHandle; + EProfileImageType mType; +}; + +LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle) + : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), + mHandle(handle), + mType(type) +{ +} + +LLProfileImagePicker::~LLProfileImagePicker() +{ + delete mHandle; +} + +void LLProfileImagePicker::notify(const std::vector<std::string>& filenames) +{ + if (mHandle->isDead()) + { + return; + } + if (filenames.empty()) + { + return; + } + std::string file_path = filenames[0]; + if (file_path.empty()) + { + return; + } + + // generate a temp texture file for coroutine + std::string temp_file = gDirUtilp->getTempFilename(); + U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); + const S32 MAX_DIM = 256; + if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) + { + //todo: image not supported notification + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", failed to open image" << LL_ENDL; + return; + } + + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + if (cap_url.empty()) + { + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL; + return; + } + + switch (mType) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast<LLPanelProfileFirstLife*>(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + } + + LLCoros::instance().launch("postAgentUserImageCoro", + boost::bind(post_profile_image_coro, cap_url, mType, temp_file, mHandle)); + + mHandle = nullptr; // transferred to post_profile_image_coro +} + +void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + // todo: consider moving this into LLAvatarActions::onCommit(name, id) + // and making all other flaoters, like people menu do the same + if (item_name == "im") + { + LLAvatarActions::startIM(agent_id); + } + else if (item_name == "offer_teleport") + { + LLAvatarActions::offerTeleport(agent_id); + } + else if (item_name == "request_teleport") + { + LLAvatarActions::teleportRequest(agent_id); + } + else if (item_name == "voice_call") + { + LLAvatarActions::startCall(agent_id); + } + else if (item_name == "chat_history") + { + LLAvatarActions::viewChatHistory(agent_id); + } + else if (item_name == "add_friend") + { + LLAvatarActions::requestFriendshipDialog(agent_id); + } + else if (item_name == "remove_friend") + { + LLAvatarActions::removeFriendDialog(agent_id); + } + else if (item_name == "invite_to_group") + { + LLAvatarActions::inviteToGroup(agent_id); + } + else if (item_name == "can_show_on_map") + { + LLAvatarActions::showOnMap(agent_id); + } + else if (item_name == "share") + { + LLAvatarActions::share(agent_id); + } + else if (item_name == "pay") + { + LLAvatarActions::pay(agent_id); + } + else if (item_name == "toggle_block_agent") + { + LLAvatarActions::toggleBlock(agent_id); + } + else if (item_name == "copy_user_id") + { + LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); + LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + } + else if (item_name == "agent_permissions") + { + onShowAgentPermissionsDialog(); + } + else if (item_name == "copy_display_name" + || item_name == "copy_username") + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getAvatarId(), &av_name)) + { + // shouldn't happen, option is supposed to be invisible while name is fetching + LL_WARNS() << "Failed to get agent data" << LL_ENDL; + return; + } + LLWString wstr; + if (item_name == "copy_display_name") + { + wstr = utf8str_to_wstring(av_name.getDisplayName(true)); + } + else if (item_name == "copy_username") + { + wstr = utf8str_to_wstring(av_name.getUserName()); + } + LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + } + else if (item_name == "edit_display_name") + { + LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2)); + LLFirstUse::setDisplayName(false); + } + else if (item_name == "edit_partner") + { + std::string url = "https://[GRID]/my/account/partners.php"; + LLSD subs; + url = LLWeb::expandURLSubstitutions(url, subs); + LLUrlAction::openURL(url); + } + else if (item_name == "upload_photo") + { + (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle<LLPanel>(getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } + else if (item_name == "change_photo") + { + onShowTexturePicker(); + } + else if (item_name == "remove_photo") + { + onCommitProfileImage(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } +} + +bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "offer_teleport" || item_name == "request_teleport") + { + return LLAvatarActions::canOfferTeleport(agent_id); + } + else if (item_name == "voice_call") + { + return mVoiceStatus; + } + else if (item_name == "chat_history") + { + return LLLogChat::isTranscriptExist(agent_id); + } + else if (item_name == "add_friend") + { + return !LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "remove_friend") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "can_show_on_map") + { + return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) + || gAgent.isGodlike(); + } + else if (item_name == "toggle_block_agent") + { + return LLAvatarActions::canBlock(agent_id); + } + else if (item_name == "agent_permissions") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "copy_display_name" + || item_name == "copy_username") + { + return !mAvatarNameCacheConnection.connected(); + } + else if (item_name == "upload_photo" + || item_name == "change_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + else if (item_name == "remove_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + return mImageId.notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + + return false; +} + +bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "toggle_block_agent") + { + return LLAvatarActions::isBlocked(agent_id); + } + return false; +} + +void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name) { - LLPanelPicks* panel_picks = findChild<LLPanelPicks>(PANEL_PICKS); - panel_picks->setProfilePanel(this); + if (av_name.getDisplayName().empty()) + { + // something is wrong, tell user to try again later + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); + return; + } - getTabContainer()[PANEL_PICKS] = panel_picks; + LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " + << LLDate(av_name.mNextUpdate) << LL_ENDL; + F64 now_secs = LLDate::now().secondsSinceEpoch(); - return TRUE; + if (now_secs < av_name.mNextUpdate) + { + // if the update time is more than a year in the future, it means updates have been blocked + // show a more general message + static const S32 YEAR = 60*60*24*365; + if (now_secs + YEAR < av_name.mNextUpdate) + { + LLNotificationsUtil::add("SetDisplayNameBlocked"); + return; + } + } + + LLFloaterReg::showInstance("display_name"); +} + +void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) +{ + mSaveDescriptionChanges->setEnabled(FALSE); + mDiscardDescriptionChanges->setEnabled(FALSE); + mHasUnsavedDescriptionChanges = false; + + mDescriptionText = text; + mDescriptionEdit->setValue(mDescriptionText); } -// virtual -void LLPanelProfile::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLPanelProfileSecondLife::onSetDescriptionDirty() { - // Temporarily add saved children back and reshape them. - mChildStack.preParentReshape(); - LLPanel::reshape(width, height, called_from_parent); - mChildStack.postParentReshape(); + mSaveDescriptionChanges->setEnabled(TRUE); + mDiscardDescriptionChanges->setEnabled(TRUE); + mHasUnsavedDescriptionChanges = true; +} + +void LLPanelProfileSecondLife::onShowInSearchCallback() +{ + S32 value = mShowInSearchCombo->getValue().asInteger(); + if (mAllowPublish == (bool)value) + { + return; + } + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + mAllowPublish = value; + LLSD data; + data["allow_publish"] = mAllowPublish; + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), data)); + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } +} + +void LLPanelProfileSecondLife::onSaveDescriptionChanges() +{ + mDescriptionText = mDescriptionEdit->getValue().asString(); + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("sl_about_text", mDescriptionText))); + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } + + mSaveDescriptionChanges->setEnabled(FALSE); + mDiscardDescriptionChanges->setEnabled(FALSE); + mHasUnsavedDescriptionChanges = false; +} + +void LLPanelProfileSecondLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mDescriptionText); +} + +void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); + mFloaterPermissionsHandle = perms->getHandle(); + perms->openFloater(); + perms->setVisibleAndFrontmost(TRUE); + + parent_floater->addDependentFloater(mFloaterPermissionsHandle); + } + } + else // already open + { + floater->setMinimized(FALSE); + floater->setVisibleAndFrontmost(TRUE); + } +} + +void LLPanelProfileSecondLife::onShowAgentProfileTexture() +{ + if (!getIsLoaded()) + { + return; + } + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); + mFloaterProfileTextureHandle = texture_view->getHandle(); + if (mImageId.notNull()) + { + texture_view->loadAsset(mImageId); + } + else + { + texture_view->resetAsset(); + } + texture_view->openFloater(); + texture_view->setVisibleAndFrontmost(TRUE); + + parent_floater->addDependentFloater(mFloaterProfileTextureHandle); + } + } + else // already open + { + LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); + texture_view->setMinimized(FALSE); + texture_view->setVisibleAndFrontmost(TRUE); + if (mImageId.notNull()) + { + texture_view->loadAsset(mImageId); + } + else + { + texture_view->resetAsset(); + } + } +} + +void LLPanelProfileSecondLife::onShowTexturePicker() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mImageId, + LLUUID::null, + mImageId, + FALSE, + FALSE, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + PERM_NONE, + FALSE, + NULL); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + LLUUID image_asset_id; + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); + if (floaterp) + { + if (id.notNull()) + { + image_asset_id = id; + } + else + { + image_asset_id = floaterp->getAssetID(); + } + } + + onCommitProfileImage(image_asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(FALSE); + texture_floaterp->setBakeTextureEnabled(FALSE); + texture_floaterp->setCanApply(false, true); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(TRUE); + } + } + else + { + floaterp->setMinimized(FALSE); + floaterp->setVisibleAndFrontmost(TRUE); + } +} + +void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) +{ + if (mImageId == id) + { + return; + } + + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLSD params; + params["sl_image_id"] = id; + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params)); + + mImageId = id; + if (mImageId == LLUUID::null) + { + mSecondLifePic->setValue("Generic_Person_Large"); + } + else + { + mSecondLifePic->setValue(mImageId); + } + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); + if (mImageId == LLUUID::null) + { + texture_view->resetAsset(); + } + else + { + texture_view->loadAsset(mImageId); + } + } + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileWeb + +LLPanelProfileWeb::LLPanelProfileWeb() + : LLPanelProfileTab() + , mWebBrowser(NULL) + , mAvatarNameCacheConnection() +{ +} + +LLPanelProfileWeb::~LLPanelProfileWeb() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +void LLPanelProfileWeb::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); + + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLPanelProfileWeb::postBuild() +{ + mWebBrowser = getChild<LLMediaCtrl>("profile_html"); + mWebBrowser->addObserver(this); + mWebBrowser->setHomePageUrl("about:blank"); + + return TRUE; +} + +void LLPanelProfileWeb::resetData() +{ + mWebBrowser->navigateHome(); +} + +void LLPanelProfileWeb::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) + { + setIsLoading(); + + mWebBrowser->setVisible(TRUE); + mPerformanceTimer.start(); + mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); + } +} + +void LLPanelProfileWeb::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + std::string username = av_name.getAccountName(); + if (username.empty()) + { + username = LLCacheName::buildUsername(av_name.getDisplayName()); + } + else + { + LLStringUtil::replaceChar(username, ' ', '.'); + } + + mURLWebProfile = getProfileURL(username, true); + if (mURLWebProfile.empty()) + { + return; + } + + //if the tab was opened before name was resolved, load the panel now + updateData(); +} + +void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) +{ + if (!mURLHome.empty()) + { + LLSD::String valstr = ctrl->getValue().asString(); + if (valstr.empty()) + { + mWebBrowser->setVisible(TRUE); + mPerformanceTimer.start(); + mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); + } + else if (valstr == "popout") + { + // open in viewer's browser, new window + LLWeb::loadURLInternal(mURLHome); + } + else if (valstr == "external") + { + // open in external browser + LLWeb::loadURLExternal(mURLHome); + } + } +} + +void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + switch(event) + { + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + childSetValue("status_text", LLSD( self->getStatusText() ) ); + break; + + case MEDIA_EVENT_NAVIGATE_BEGIN: + { + if (mFirstNavigate) + { + mFirstNavigate = false; + } + else + { + mPerformanceTimer.start(); + } + } + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + { + LLStringUtil::format_map_t args; + args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); + childSetValue("status_text", LLSD( getString("LoadTime", args)) ); + } + break; + + default: + // Having a default case makes the compiler happy. + break; + } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileFirstLife::LLPanelProfileFirstLife() + : LLPanelProfileTab() + , mHasUnsavedChanges(false) +{ +} + +LLPanelProfileFirstLife::~LLPanelProfileFirstLife() +{ +} + +BOOL LLPanelProfileFirstLife::postBuild() +{ + mDescriptionEdit = getChild<LLTextEditor>("fl_description_edit"); + mPicture = getChild<LLIconCtrl>("real_world_pic"); + + mUploadPhoto = getChild<LLButton>("fl_upload_image"); + mChangePhoto = getChild<LLButton>("fl_change_image"); + mRemovePhoto = getChild<LLButton>("fl_remove_image"); + mSaveChanges = getChild<LLButton>("fl_save_changes"); + mDiscardChanges = getChild<LLButton>("fl_discard_changes"); + + mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); + mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); + mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + return TRUE; +} + +void LLPanelProfileFirstLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + if (!getSelfProfile()) + { + // Otherwise as the only focusable element it will be selected + mDescriptionEdit->setTabStop(FALSE); + } + + resetData(); +} + +void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) +{ + mUploadPhoto->setEnabled(!loading); + mChangePhoto->setEnabled(!loading); + mRemovePhoto->setEnabled(!loading && mImageId.notNull()); + + LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } +} + +void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mPicture->setValue(image_asset_id); + mImageId = image_asset_id; + setProfileImageUploading(false); +} + +void LLPanelProfileFirstLife::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileFirstLife::onUploadPhoto() +{ + (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle<LLPanel>(getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onChangePhoto() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mImageId, + LLUUID::null, + mImageId, + FALSE, + FALSE, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + PERM_NONE, + FALSE, + NULL); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + LLUUID image_asset_id; + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); + if (floaterp) + { + if (id.notNull()) + { + image_asset_id = id; + } + else + { + image_asset_id = floaterp->getAssetID(); + } + } + + onCommitPhoto(image_asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(FALSE); + texture_floaterp->setCanApply(false, true); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(TRUE); + } + } + else + { + floaterp->setMinimized(FALSE); + floaterp->setVisibleAndFrontmost(TRUE); + } +} + +void LLPanelProfileFirstLife::onRemovePhoto() +{ + onCommitPhoto(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) +{ + if (mImageId == id) + { + return; + } + + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLSD params; + params["fl_image_id"] = id; + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params)); + + mImageId = id; + if (mImageId.notNull()) + { + mPicture->setValue(mImageId); + } + else + { + mPicture->setValue("Generic_Person_Large"); + } + + mRemovePhoto->setEnabled(mImageId.notNull()); + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } +} + +void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) +{ + mSaveChanges->setEnabled(FALSE); + mDiscardChanges->setEnabled(FALSE); + mHasUnsavedChanges = false; + + mCurrentDescription = text; + mDescriptionEdit->setValue(mCurrentDescription); +} + +void LLPanelProfileFirstLife::onSetDescriptionDirty() +{ + mSaveChanges->setEnabled(TRUE); + mDiscardChanges->setEnabled(TRUE); + mHasUnsavedChanges = true; +} + +void LLPanelProfileFirstLife::onSaveDescriptionChanges() +{ + mCurrentDescription = mDescriptionEdit->getValue().asString(); + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("fl_about_text", mCurrentDescription))); + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } + + mSaveChanges->setEnabled(FALSE); + mDiscardChanges->setEnabled(FALSE); + mHasUnsavedChanges = false; +} + +void LLPanelProfileFirstLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mCurrentDescription); +} + +void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) +{ + setDescriptionText(avatar_data->fl_about_text); + + mImageId = avatar_data->fl_image_id; + + if (mImageId.notNull()) + { + mPicture->setValue(mImageId); + } + else + { + mPicture->setValue("Generic_Person_Large"); + } + + setLoaded(); +} + +void LLPanelProfileFirstLife::resetData() +{ + setDescriptionText(std::string()); + mPicture->setValue("Generic_Person_Large"); + mImageId = LLUUID::null; + + mUploadPhoto->setVisible(getSelfProfile()); + mChangePhoto->setVisible(getSelfProfile()); + mRemovePhoto->setVisible(getSelfProfile()); + mSaveChanges->setVisible(getSelfProfile()); + mDiscardChanges->setVisible(getSelfProfile()); +} + +void LLPanelProfileFirstLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mDescriptionEdit->setEnabled(TRUE); + mPicture->setEnabled(TRUE); + mRemovePhoto->setEnabled(mImageId.notNull()); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileNotes::LLPanelProfileNotes() +: LLPanelProfileTab() + , mHasUnsavedChanges(false) +{ + +} + +LLPanelProfileNotes::~LLPanelProfileNotes() +{ +} + +void LLPanelProfileNotes::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("requestAgentUserInfoCoro", + boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); + } + } +} + +void LLPanelProfileNotes::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveNotesChanges(); + } +} + +BOOL LLPanelProfileNotes::postBuild() +{ + mNotesEditor = getChild<LLTextEditor>("notes_edit"); + mSaveChanges = getChild<LLButton>("notes_save_changes"); + mDiscardChanges = getChild<LLButton>("notes_discard_changes"); + + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); + mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); + + return TRUE; +} + +void LLPanelProfileNotes::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); +} + +void LLPanelProfileNotes::setNotesText(const std::string &text) +{ + mSaveChanges->setEnabled(FALSE); + mDiscardChanges->setEnabled(FALSE); + mHasUnsavedChanges = false; + + mCurrentNotes = text; + mNotesEditor->setValue(mCurrentNotes); +} + +void LLPanelProfileNotes::onSetNotesDirty() +{ + mSaveChanges->setEnabled(TRUE); + mDiscardChanges->setEnabled(TRUE); + mHasUnsavedChanges = true; +} + +void LLPanelProfileNotes::onSaveNotesChanges() +{ + mCurrentNotes = mNotesEditor->getValue().asString(); + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("notes", mCurrentNotes))); + } + else + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + } + + mSaveChanges->setEnabled(FALSE); + mDiscardChanges->setEnabled(FALSE); + mHasUnsavedChanges = false; +} + +void LLPanelProfileNotes::onDiscardNotesChanges() +{ + setNotesText(mCurrentNotes); +} + +void LLPanelProfileNotes::processProperties(LLAvatarNotes* avatar_notes) +{ + setNotesText(avatar_notes->notes); + mNotesEditor->setEnabled(TRUE); + setLoaded(); +} + +void LLPanelProfileNotes::resetData() +{ + resetLoading(); + setNotesText(std::string()); +} + +void LLPanelProfileNotes::setAvatarId(const LLUUID& avatar_id) +{ + if (avatar_id.notNull()) + { + LLPanelProfileTab::setAvatarId(avatar_id); + } +} + + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfile + +LLPanelProfile::LLPanelProfile() + : LLPanelProfileTab() +{ +} + +LLPanelProfile::~LLPanelProfile() +{ +} + +BOOL LLPanelProfile::postBuild() +{ + return TRUE; +} + +void LLPanelProfile::onTabChange() +{ + LLPanelProfileTab* active_panel = dynamic_cast<LLPanelProfileTab*>(mTabContainer->getCurrentPanel()); + if (active_panel) + { + active_panel->updateData(); + } } void LLPanelProfile::onOpen(const LLSD& key) { - getTabContainer()[PANEL_PICKS]->onOpen(getAvatarId()); + LLUUID avatar_id = key["id"].asUUID(); - // support commands to open further pieces of UI - if (key.has("show_tab_panel")) - { - std::string panel = key["show_tab_panel"].asString(); - if (panel == "create_classified") - { - LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); - if (picks) - { - picks->createNewClassified(); - } - } - else if (panel == "classified_details") - { - LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); - if (picks) - { - LLSD params = key; - params.erase("show_tab_panel"); - params.erase("open_tab_name"); - picks->openClassifiedInfo(params); - } - } - else if (panel == "edit_classified") - { - LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); - if (picks) - { - LLSD params = key; - params.erase("show_tab_panel"); - params.erase("open_tab_name"); - picks->openClassifiedEdit(params); - } - } - else if (panel == "create_pick") - { - LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); - if (picks) - { - picks->createNewPick(); - } - } - else if (panel == "edit_pick") - { - LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); - if (picks) - { - LLSD params = key; - params.erase("show_tab_panel"); - params.erase("open_tab_name"); - picks->openPickEdit(params); - } - } - } + // Don't reload the same profile + if (getAvatarId() == avatar_id) + { + return; + } + + LLPanelProfileTab::onOpen(avatar_id); + + mTabContainer = getChild<LLTabContainer>("panel_profile_tabs"); + mPanelSecondlife = findChild<LLPanelProfileSecondLife>(PANEL_SECONDLIFE); + mPanelWeb = findChild<LLPanelProfileWeb>(PANEL_WEB); + mPanelPicks = findChild<LLPanelProfilePicks>(PANEL_PICKS); + mPanelClassifieds = findChild<LLPanelProfileClassifieds>(PANEL_CLASSIFIEDS); + mPanelFirstlife = findChild<LLPanelProfileFirstLife>(PANEL_FIRSTLIFE); + mPanelNotes = findChild<LLPanelProfileNotes>(PANEL_NOTES); + + mPanelSecondlife->onOpen(avatar_id); + mPanelWeb->onOpen(avatar_id); + mPanelPicks->onOpen(avatar_id); + mPanelClassifieds->onOpen(avatar_id); + mPanelFirstlife->onOpen(avatar_id); + mPanelNotes->onOpen(avatar_id); + + // Always request the base profile info + resetLoading(); + updateData(); + + // Some tabs only request data when opened + mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); } -void LLPanelProfile::onTabSelected(const LLSD& param) +void LLPanelProfile::updateData() { - std::string tab_name = param.asString(); - if (NULL != getTabContainer()[tab_name]) - { - getTabContainer()[tab_name]->onOpen(getAvatarId()); - } + LLUUID avatar_id = getAvatarId(); + // Todo: getIsloading functionality needs to be expanded to + // include 'inited' or 'data_provided' state to not rerequest + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + mPanelSecondlife->setIsLoading(); + mPanelPicks->setIsLoading(); + mPanelFirstlife->setIsLoading(); + mPanelNotes->setIsLoading(); + + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + if (!cap_url.empty()) + { + LLCoros::instance().launch("requestAgentUserInfoCoro", + boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); + } + } } -void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params) +void LLPanelProfile::refreshName() { - // Hide currently visible panel (STORM-690). - mChildStack.push(); + mPanelSecondlife->refreshName(); +} - // Add the panel or bring it to front. - if (panel->getParent() != this) - { - addChild(panel); - } - else - { - sendChildToFront(panel); - } +void LLPanelProfile::createPick(const LLPickData &data) +{ + mTabContainer->selectTabPanel(mPanelPicks); + mPanelPicks->createPick(data); +} - panel->setVisible(TRUE); - panel->setFocus(TRUE); // prevent losing focus by the floater - panel->onOpen(params); +void LLPanelProfile::showPick(const LLUUID& pick_id) +{ + if (pick_id.notNull()) + { + mPanelPicks->selectPick(pick_id); + } + mTabContainer->selectTabPanel(mPanelPicks); +} - LLRect new_rect = getRect(); - panel->reshape(new_rect.getWidth(), new_rect.getHeight()); - new_rect.setLeftTopAndSize(0, new_rect.getHeight(), new_rect.getWidth(), new_rect.getHeight()); - panel->setRect(new_rect); +bool LLPanelProfile::isPickTabSelected() +{ + return (mTabContainer->getCurrentPanel() == mPanelPicks); } -void LLPanelProfile::closePanel(LLPanel* panel) +bool LLPanelProfile::isNotesTabSelected() { - panel->setVisible(FALSE); + return (mTabContainer->getCurrentPanel() == mPanelNotes); +} - if (panel->getParent() == this) - { - removeChild(panel); +bool LLPanelProfile::hasUnsavedChanges() +{ + return mPanelSecondlife->hasUnsavedChanges() + || mPanelPicks->hasUnsavedChanges() + || mPanelClassifieds->hasUnsavedChanges() + || mPanelFirstlife->hasUnsavedChanges() + || mPanelNotes->hasUnsavedChanges(); +} - // Make the underlying panel visible. - mChildStack.pop(); +bool LLPanelProfile::hasUnpublishedClassifieds() +{ + return mPanelClassifieds->hasNewClassifieds(); +} - // Prevent losing focus by the floater - const child_list_t* child_list = getChildList(); - if (child_list->size() > 0) - { - child_list->front()->setFocus(TRUE); - } - else - { - LL_WARNS() << "No underlying panel to focus." << LL_ENDL; - } - } +void LLPanelProfile::commitUnsavedChanges() +{ + mPanelSecondlife->commitUnsavedChanges(); + mPanelPicks->commitUnsavedChanges(); + mPanelClassifieds->commitUnsavedChanges(); + mPanelFirstlife->commitUnsavedChanges(); + mPanelNotes->commitUnsavedChanges(); } -S32 LLPanelProfile::notifyParent(const LLSD& info) +void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) { - std::string action = info["action"]; - // lets update Picks list after Pick was saved - if("save_new_pick" == action) - { - onOpen(info); - return 1; - } + if (classified_id.notNull()) + { + mPanelClassifieds->selectClassified(classified_id, edit); + } + mTabContainer->selectTabPanel(mPanelClassifieds); +} - return LLPanel::notifyParent(info); +void LLPanelProfile::createClassified() +{ + mPanelClassifieds->createClassified(); + mTabContainer->selectTabPanel(mPanelClassifieds); } + diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index d97f60ed22..d32bb943bd 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -1,25 +1,25 @@ -/** +/** * @file llpanelprofile.h * @brief Profile panel * -* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* +* Copyright (C) 2022, Linden Research, Inc. +* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* +* * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -27,76 +27,383 @@ #ifndef LL_LLPANELPROFILE_H #define LL_LLPANELPROFILE_H +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" +#include "llfloater.h" #include "llpanel.h" #include "llpanelavatar.h" +#include "llmediactrl.h" +#include "llvoiceclient.h" + +// class LLPanelProfileClassifieds; +// class LLTabContainer; +// class LLPanelProfileSecondLife; +// class LLPanelProfileWeb; +// class LLPanelProfilePicks; +// class LLPanelProfileFirstLife; +// class LLPanelProfileNotes; + +class LLAvatarName; +class LLButton; +class LLCheckBoxCtrl; +class LLComboBox; +class LLIconCtrl; class LLTabContainer; +class LLTextBox; +class LLTextureCtrl; +class LLMediaCtrl; +class LLGroupList; +class LLTextBase; +class LLMenuButton; +class LLLineEditor; +class LLTextEditor; +class LLPanelProfileClassifieds; +class LLPanelProfilePicks; +class LLViewerFetchedTexture; -std::string getProfileURL(const std::string& agent_name); /** -* Base class for Profile View and My Profile. +* Panel for displaying Avatar's second life related info. */ -class LLPanelProfile : public LLPanel +class LLPanelProfileSecondLife + : public LLPanelProfileTab + , public LLFriendObserver + , public LLVoiceClientStatusObserver { - LOG_CLASS(LLPanelProfile); +public: + LLPanelProfileSecondLife(); + /*virtual*/ ~LLPanelProfileSecondLife(); + + void onOpen(const LLSD& key) override; + + /** + * LLFriendObserver trigger + */ + void changed(U32 mask) override; + + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + void onChange(EStatusType status, const std::string &channelURI, bool proximal) override; + + void setAvatarId(const LLUUID& avatar_id) override; + + BOOL postBuild() override; + + void resetData() override; + + /** + * Sends update data request to server. + */ + void updateData() override; + void refreshName(); + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + + void setProfileImageUploading(bool loading); + void setProfileImageUploaded(const LLUUID &image_asset_id); + + bool hasUnsavedChanges() override; + void commitUnsavedChanges() override; + + friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +protected: + /** + * Process profile related data received from server. + */ + void processProfileProperties(const LLAvatarData* avatar_data); + + /** + * Processes group related data received from server. + */ + void processGroupProperties(const LLAvatarGroups* avatar_groups); + + /** + * Fills common for Avatar profile and My Profile fields. + */ + void fillCommonData(const LLAvatarData* avatar_data); + + /** + * Fills partner data. + */ + void fillPartnerData(const LLAvatarData* avatar_data); + /** + * Fills account status. + */ + void fillAccountStatus(const LLAvatarData* avatar_data); + + /** + * Sets permissions specific icon + */ + void fillRightsData(); + + /** + * Fills user name, display name, age. + */ + void fillAgeData(const LLDate &born_on); + + void onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep); + static void onImageLoaded(BOOL success, + LLViewerFetchedTexture *src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata); + + /** + * Displays avatar's online status if possible. + * + * Requirements from EXT-3880: + * For friends: + * - Online when online and privacy settings allow to show + * - Offline when offline and privacy settings allow to show + * - Else: nothing + * For other avatars: + * - Online when online and was not set in Preferences/"Only Friends & Groups can see when I am online" + * - Else: Offline + */ + void updateOnlineStatus(); + void processOnlineStatus(bool is_friend, bool show_online, bool online); + +private: + void setLoaded() override; + void onCommitMenu(const LLSD& userdata); + bool onEnableMenu(const LLSD& userdata); + bool onCheckMenu(const LLSD& userdata); + void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name); + + void setDescriptionText(const std::string &text); + void onSetDescriptionDirty(); + void onShowInSearchCallback(); + void onSaveDescriptionChanges(); + void onDiscardDescriptionChanges(); + void onShowAgentPermissionsDialog(); + void onShowAgentProfileTexture(); + void onShowTexturePicker(); + void onCommitProfileImage(const LLUUID& id); + +private: + typedef std::map<std::string, LLUUID> group_map_t; + group_map_t mGroups; + void openGroupProfile(); + + LLGroupList* mGroupList; + LLComboBox* mShowInSearchCombo; + LLIconCtrl* mSecondLifePic; + LLPanel* mSecondLifePicLayout; + LLTextEditor* mDescriptionEdit; + LLMenuButton* mAgentActionMenuButton; + LLButton* mSaveDescriptionChanges; + LLButton* mDiscardDescriptionChanges; + LLIconCtrl* mCanSeeOnlineIcon; + LLIconCtrl* mCantSeeOnlineIcon; + LLIconCtrl* mCanSeeOnMapIcon; + LLIconCtrl* mCantSeeOnMapIcon; + LLIconCtrl* mCanEditObjectsIcon; + LLIconCtrl* mCantEditObjectsIcon; + + LLHandle<LLFloater> mFloaterPermissionsHandle; + LLHandle<LLFloater> mFloaterProfileTextureHandle; + LLHandle<LLFloater> mFloaterTexturePickerHandle; + + bool mHasUnsavedDescriptionChanges; + bool mVoiceStatus; + bool mWaitingForImageUpload; + bool mAllowPublish; + std::string mDescriptionText; + LLUUID mImageId; + + boost::signals2::connection mAvatarNameCacheConnection; +}; + + +/** +* Panel for displaying Avatar's web profile and home page. +*/ +class LLPanelProfileWeb + : public LLPanelProfileTab + , public LLViewerMediaObserver +{ public: - /*virtual*/ BOOL postBuild(); - /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void onOpen(const LLSD& key); + LLPanelProfileWeb(); + /*virtual*/ ~LLPanelProfileWeb(); + + void onOpen(const LLSD& key) override; + + BOOL postBuild() override; - virtual void openPanel(LLPanel* panel, const LLSD& params); + void resetData() override; - virtual void closePanel(LLPanel* panel); + /** + * Loads web profile. + */ + void updateData() override; - S32 notifyParent(const LLSD& info); + void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + + friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); protected: + void onCommitLoad(LLUICtrl* ctrl); - LLPanelProfile(); +private: + std::string mURLHome; + std::string mURLWebProfile; + LLMediaCtrl* mWebBrowser; - virtual void onTabSelected(const LLSD& param); + LLFrameTimer mPerformanceTimer; + bool mFirstNavigate; - const LLUUID& getAvatarId() { return mAvatarId; } + boost::signals2::connection mAvatarNameCacheConnection; +}; + +/** +* Panel for displaying Avatar's first life related info. +*/ +class LLPanelProfileFirstLife + : public LLPanelProfileTab +{ +public: + LLPanelProfileFirstLife(); + /*virtual*/ ~LLPanelProfileFirstLife(); + + void onOpen(const LLSD& key) override; + + BOOL postBuild() override; + + void processProperties(const LLAvatarData* avatar_data); + + void resetData() override; + + void setProfileImageUploading(bool loading); + void setProfileImageUploaded(const LLUUID &image_asset_id); + + bool hasUnsavedChanges() override { return mHasUnsavedChanges; } + void commitUnsavedChanges() override; + + friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +protected: + void setLoaded() override; + + void onUploadPhoto(); + void onChangePhoto(); + void onRemovePhoto(); + void onCommitPhoto(const LLUUID& id); + void setDescriptionText(const std::string &text); + void onSetDescriptionDirty(); + void onSaveDescriptionChanges(); + void onDiscardDescriptionChanges(); + + LLTextEditor* mDescriptionEdit; + LLIconCtrl* mPicture; + LLButton* mUploadPhoto; + LLButton* mChangePhoto; + LLButton* mRemovePhoto; + LLButton* mSaveChanges; + LLButton* mDiscardChanges; + + LLHandle<LLFloater> mFloaterTexturePickerHandle; + + std::string mCurrentDescription; + LLUUID mImageId; + bool mHasUnsavedChanges; +}; + +/** + * Panel for displaying Avatar's notes and modifying friend's rights. + */ +class LLPanelProfileNotes + : public LLPanelProfileTab +{ +public: + LLPanelProfileNotes(); + /*virtual*/ ~LLPanelProfileNotes(); - void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } + void setAvatarId(const LLUUID& avatar_id) override; - typedef std::map<std::string, LLPanelProfileTab*> profile_tabs_t; + void onOpen(const LLSD& key) override; - profile_tabs_t& getTabContainer() { return mTabContainer; } + BOOL postBuild() override; + + void processProperties(LLAvatarNotes* avatar_notes); + + void resetData() override; + + void updateData() override; + + bool hasUnsavedChanges() override { return mHasUnsavedChanges; } + void commitUnsavedChanges() override; + +protected: + void setNotesText(const std::string &text); + void onSetNotesDirty(); + void onSaveNotesChanges(); + void onDiscardNotesChanges(); + + LLTextEditor* mNotesEditor; + LLButton* mSaveChanges; + LLButton* mDiscardChanges; + + std::string mCurrentNotes; + bool mHasUnsavedChanges; +}; + + +/** +* Container panel for the profile tabs +*/ +class LLPanelProfile + : public LLPanelProfileTab +{ +public: + LLPanelProfile(); + /*virtual*/ ~LLPanelProfile(); + + BOOL postBuild() override; + + void updateData() override; + void refreshName(); + + void onOpen(const LLSD& key) override; + + void createPick(const LLPickData &data); + void showPick(const LLUUID& pick_id = LLUUID::null); + bool isPickTabSelected(); + bool isNotesTabSelected(); + bool hasUnsavedChanges() override; + bool hasUnpublishedClassifieds(); + void commitUnsavedChanges() override; + + void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); + void createClassified(); + + LLAvatarData getAvatarData() { return mAvatarData; }; + + friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); private: + void onTabChange(); + + LLPanelProfileSecondLife* mPanelSecondlife; + LLPanelProfileWeb* mPanelWeb; + LLPanelProfilePicks* mPanelPicks; + LLPanelProfileClassifieds* mPanelClassifieds; + LLPanelProfileFirstLife* mPanelFirstlife; + LLPanelProfileNotes* mPanelNotes; + LLTabContainer* mTabContainer; - //-- ChildStack begins ---------------------------------------------------- - class ChildStack - { - LOG_CLASS(LLPanelProfile::ChildStack); - public: - ChildStack(); - ~ChildStack(); - void setParent(LLPanel* parent); - - bool push(); - bool pop(); - void preParentReshape(); - void postParentReshape(); - - private: - void dump(); - - typedef LLView::child_list_t view_list_t; - typedef std::list<view_list_t> stack_t; - - stack_t mStack; - stack_t mSavedStack; - LLPanel* mParent; - }; - //-- ChildStack ends ------------------------------------------------------ - - profile_tabs_t mTabContainer; - ChildStack mChildStack; - LLUUID mAvatarId; + // Todo: due to server taking minutes to update this needs a more long term storage + // to reuse recently saved values if user opens floater again + // Storage implementation depends onto how a cap will be implemented, if cap will be + // enought to fully update LLAvatarPropertiesProcessor, then this storage can be + // implemented there. + LLAvatarData mAvatarData; }; #endif //LL_LLPANELPROFILE_H diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp new file mode 100644 index 0000000000..a3913ddc49 --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -0,0 +1,1513 @@ +/** + * @file llpanelprofileclassifieds.cpp + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelprofileclassifieds.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedflags.h" +#include "llcombobox.h" +#include "llcommandhandler.h" // for classified HTML detail page click tracking +#include "llcorehttputil.h" +#include "lldispatcher.h" +#include "llfloaterclassified.h" +#include "llfloaterreg.h" +#include "llfloatersidepanelcontainer.h" +#include "llfloaterworldmap.h" +#include "lliconctrl.h" +#include "lllineeditor.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llparcel.h" +#include "llregistry.h" +#include "llscrollcontainer.h" +#include "llstartup.h" +#include "llstatusbar.h" +#include "lltabcontainer.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewertexture.h" +#include "llviewertexture.h" + + +//*TODO: verify this limit +const S32 MAX_AVATAR_CLASSIFIEDS = 100; + +const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ +const S32 DEFAULT_EDIT_CLASSIFIED_SCROLL_HEIGHT = 530; + +//static +LLPanelProfileClassified::panel_list_t LLPanelProfileClassified::sAllPanels; + +static LLPanelInjector<LLPanelProfileClassifieds> t_panel_profile_classifieds("panel_profile_classifieds"); +static LLPanelInjector<LLPanelProfileClassified> t_panel_profile_classified("panel_profile_classified"); + +class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesObserver +{ +public: + // throttle calls from untrusted browsers + LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} + + std::set<LLUUID> mClassifiedIds; + std::string mRequestVerb; + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + if (LLStartUp::getStartupState() < STATE_STARTED) + { + return true; + } + + if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds")) + { + LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + + // handle app/classified/create urls first + if (params.size() == 1 && params[0].asString() == "create") + { + LLAvatarActions::createClassified(); + return true; + } + + // then handle the general app/classified/{UUID}/{CMD} urls + if (params.size() < 2) + { + return false; + } + + // get the ID for the classified + LLUUID classified_id; + if (!classified_id.set(params[0], FALSE)) + { + return false; + } + + // show the classified in the side tray. + // need to ask the server for more info first though... + const std::string verb = params[1].asString(); + if (verb == "about") + { + mRequestVerb = verb; + mClassifiedIds.insert(classified_id); + LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); + return true; + } + else if (verb == "edit") + { + LLAvatarActions::showClassified(gAgent.getID(), classified_id, true); + return true; + } + + return false; + } + + void openClassified(LLAvatarClassifiedInfo* c_info) + { + if (mRequestVerb == "about") + { + if (c_info->creator_id == gAgent.getID()) + { + LLAvatarActions::showClassified(gAgent.getID(), c_info->classified_id, false); + } + else + { + LLSD params; + params["id"] = c_info->creator_id; + params["classified_id"] = c_info->classified_id; + params["classified_creator_id"] = c_info->creator_id; + params["classified_snapshot_id"] = c_info->snapshot_id; + params["classified_name"] = c_info->name; + params["classified_desc"] = c_info->description; + params["from_search"] = true; + + LLFloaterClassified* floaterp = LLFloaterReg::getTypedInstance<LLFloaterClassified>("classified", params); + if (floaterp) + { + floaterp->openFloater(params); + floaterp->setVisibleAndFrontmost(); + } + } + } + } + + void processProperties(void* data, EAvatarProcessorType type) + { + if (APT_CLASSIFIED_INFO != type) + { + return; + } + + // is this the classified that we asked for? + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) + { + return; + } + + // open the detail side tray for this classified + openClassified(c_info); + + // remove our observer now that we're done + mClassifiedIds.erase(c_info->classified_id); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); + } +}; +LLClassifiedHandler gClassifiedHandler; + +////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassifieds +//----------------------------------------------------------------------------- + +LLPanelProfileClassifieds::LLPanelProfileClassifieds() + : LLPanelProfilePropertiesProcessorTab() + , mClassifiedToSelectOnLoad(LLUUID::null) + , mClassifiedEditOnLoad(false) + , mSheduledClassifiedCreation(false) +{ +} + +LLPanelProfileClassifieds::~LLPanelProfileClassifieds() +{ +} + +void LLPanelProfileClassifieds::onOpen(const LLSD& key) +{ + LLPanelProfilePropertiesProcessorTab::onOpen(key); + + resetData(); + + bool own_profile = getSelfProfile(); + if (own_profile) + { + mNewButton->setVisible(TRUE); + mNewButton->setEnabled(FALSE); + + mDeleteButton->setVisible(TRUE); + mDeleteButton->setEnabled(FALSE); + } + + childSetVisible("buttons_header", own_profile); + +} + +void LLPanelProfileClassifieds::selectClassified(const LLUUID& classified_id, bool edit) +{ + if (getIsLoaded()) + { + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); + if (classified_panel) + { + if (classified_panel->getClassifiedId() == classified_id) + { + mTabContainer->selectTabPanel(classified_panel); + if (edit) + { + classified_panel->setEditMode(TRUE); + } + break; + } + } + } + } + else + { + mClassifiedToSelectOnLoad = classified_id; + mClassifiedEditOnLoad = edit; + } +} + +void LLPanelProfileClassifieds::createClassified() +{ + if (getIsLoaded()) + { + mNoItemsLabel->setVisible(FALSE); + LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + classified_panel->onOpen(LLSD()); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(classified_panel). + select_tab(true). + label(classified_panel->getClassifiedName())); + updateButtons(); + } + else + { + mSheduledClassifiedCreation = true; + } +} + +BOOL LLPanelProfileClassifieds::postBuild() +{ + mTabContainer = getChild<LLTabContainer>("tab_classifieds"); + mNoItemsLabel = getChild<LLUICtrl>("classifieds_panel_text"); + mNewButton = getChild<LLButton>("new_btn"); + mDeleteButton = getChild<LLButton>("delete_btn"); + + mNewButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickNewBtn, this)); + mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickDelete, this)); + + return TRUE; +} + +void LLPanelProfileClassifieds::onClickNewBtn() +{ + mNoItemsLabel->setVisible(FALSE); + LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + classified_panel->onOpen(LLSD()); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(classified_panel). + select_tab(true). + label(classified_panel->getClassifiedName())); + updateButtons(); +} + +void LLPanelProfileClassifieds::onClickDelete() +{ + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getCurrentPanel()); + if (classified_panel) + { + LLUUID classified_id = classified_panel->getClassifiedId(); + LLSD args; + args["CLASSIFIED"] = classified_panel->getClassifiedName(); + LLSD payload; + payload["classified_id"] = classified_id; + payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); + LLNotificationsUtil::add("ProfileDeleteClassified", args, payload, + boost::bind(&LLPanelProfileClassifieds::callbackDeleteClassified, this, _1, _2)); + } +} + +void LLPanelProfileClassifieds::callbackDeleteClassified(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + LLUUID classified_id = notification["payload"]["classified_id"].asUUID(); + S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); + if (classified_panel && classified_panel->getClassifiedId() == classified_id) + { + mTabContainer->removeTabPanel(classified_panel); + } + + if (classified_id.notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedDelete(classified_id); + } + + updateButtons(); + + BOOL no_data = !mTabContainer->getTabCount(); + mNoItemsLabel->setVisible(no_data); + } +} + +void LLPanelProfileClassifieds::processProperties(void* data, EAvatarProcessorType type) +{ + if ((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) + { + LLUUID avatar_id = getAvatarId(); + + LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); + if (c_info && getAvatarId() == c_info->target_id) + { + // do not clear classified list in case we will receive two or more data packets. + // list has been cleared in updateData(). (fix for EXT-6436) + LLUUID selected_id = mClassifiedToSelectOnLoad; + bool has_selection = false; + + LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); + for (; c_info->classifieds_list.end() != it; ++it) + { + LLAvatarClassifieds::classified_data c_data = *it; + + LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + + LLSD params; + params["classified_creator_id"] = avatar_id; + params["classified_id"] = c_data.classified_id; + params["classified_name"] = c_data.name; + params["from_search"] = (selected_id == c_data.classified_id); //SLURL handling and stats tracking + params["edit"] = (selected_id == c_data.classified_id) && mClassifiedEditOnLoad; + classified_panel->onOpen(params); + + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(classified_panel). + select_tab(selected_id == c_data.classified_id). + label(c_data.name)); + + if (selected_id == c_data.classified_id) + { + has_selection = true; + } + } + + if (mSheduledClassifiedCreation) + { + LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + classified_panel->onOpen(LLSD()); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(classified_panel). + select_tab(!has_selection). + label(classified_panel->getClassifiedName())); + has_selection = true; + } + + // reset 'do on load' values + mClassifiedToSelectOnLoad = LLUUID::null; + mClassifiedEditOnLoad = false; + mSheduledClassifiedCreation = false; + + // set even if not visible, user might delete own + // calassified and this string will need to be shown + if (getSelfProfile()) + { + mNoItemsLabel->setValue(LLTrans::getString("NoClassifiedsText")); + } + else + { + mNoItemsLabel->setValue(LLTrans::getString("NoAvatarClassifiedsText")); + } + + bool has_data = mTabContainer->getTabCount() > 0; + mNoItemsLabel->setVisible(!has_data); + if (has_data && !has_selection) + { + mTabContainer->selectFirstTab(); + } + + setLoaded(); + updateButtons(); + } + } +} + +void LLPanelProfileClassifieds::resetData() +{ + resetLoading(); + mTabContainer->deleteAllTabs(); +} + +void LLPanelProfileClassifieds::updateButtons() +{ + if (getSelfProfile()) + { + mNewButton->setEnabled(canAddNewClassified()); + mDeleteButton->setEnabled(canDeleteClassified()); + } +} + +void LLPanelProfileClassifieds::updateData() +{ + // Send picks request only once + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); + mNoItemsLabel->setVisible(TRUE); + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(avatar_id); + } +} + +bool LLPanelProfileClassifieds::hasNewClassifieds() +{ + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); + if (classified_panel && classified_panel->isNew()) + { + return true; + } + } + return false; +} + +bool LLPanelProfileClassifieds::hasUnsavedChanges() +{ + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); + if (classified_panel && classified_panel->isDirty()) // includes 'new' + { + return true; + } + } + return false; +} + +bool LLPanelProfileClassifieds::canAddNewClassified() +{ + return (mTabContainer->getTabCount() < MAX_AVATAR_CLASSIFIEDS); +} + +bool LLPanelProfileClassifieds::canDeleteClassified() +{ + return (mTabContainer->getTabCount() > 0); +} + +void LLPanelProfileClassifieds::commitUnsavedChanges() +{ + if (getIsLoaded()) + { + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); + if (classified_panel && classified_panel->isDirty() && !classified_panel->isNew()) + { + classified_panel->doSave(); + } + } + } +} +//----------------------------------------------------------------------------- +// LLDispatchClassifiedClickThrough +//----------------------------------------------------------------------------- + +// "classifiedclickthrough" +// strings[0] = classified_id +// strings[1] = teleport_clicks +// strings[2] = map_clicks +// strings[3] = profile_clicks +class LLDispatchClassifiedClickThrough : public LLDispatchHandler +{ +public: + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) + { + if (strings.size() != 4) return false; + LLUUID classified_id(strings[0]); + S32 teleport_clicks = atoi(strings[1].c_str()); + S32 map_clicks = atoi(strings[2].c_str()); + S32 profile_clicks = atoi(strings[3].c_str()); + + LLPanelProfileClassified::setClickThrough( + classified_id, teleport_clicks, map_clicks, profile_clicks, false); + + return true; + } +}; +static LLDispatchClassifiedClickThrough sClassifiedClickThrough; + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassified +//----------------------------------------------------------------------------- + +static const S32 CB_ITEM_MATURE = 0; +static const S32 CB_ITEM_PG = 1; + +LLPanelProfileClassified::LLPanelProfileClassified() + : LLPanelProfilePropertiesProcessorTab() + , mInfoLoaded(false) + , mTeleportClicksOld(0) + , mMapClicksOld(0) + , mProfileClicksOld(0) + , mTeleportClicksNew(0) + , mMapClicksNew(0) + , mProfileClicksNew(0) + , mPriceForListing(0) + , mSnapshotCtrl(NULL) + , mPublishFloater(NULL) + , mIsNew(false) + , mIsNewWithErrors(false) + , mCanClose(false) + , mEditMode(false) + , mEditOnLoad(false) +{ + sAllPanels.push_back(this); +} + +LLPanelProfileClassified::~LLPanelProfileClassified() +{ + sAllPanels.remove(this); + gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler +} + +//static +LLPanelProfileClassified* LLPanelProfileClassified::create() +{ + LLPanelProfileClassified* panel = new LLPanelProfileClassified(); + panel->buildFromFile("panel_profile_classified.xml"); + return panel; +} + +BOOL LLPanelProfileClassified::postBuild() +{ + mScrollContainer = getChild<LLScrollContainer>("profile_scroll"); + mInfoPanel = getChild<LLView>("info_panel"); + mInfoScroll = getChild<LLPanel>("info_scroll_content_panel"); + mEditPanel = getChild<LLPanel>("edit_panel"); + + mSnapshotCtrl = getChild<LLTextureCtrl>("classified_snapshot"); + mEditIcon = getChild<LLUICtrl>("edit_icon"); + + //info + mClassifiedNameText = getChild<LLUICtrl>("classified_name"); + mClassifiedDescText = getChild<LLTextEditor>("classified_desc"); + mLocationText = getChild<LLUICtrl>("classified_location"); + mCategoryText = getChild<LLUICtrl>("category"); + mContentTypeText = getChild<LLUICtrl>("content_type"); + mContentTypeM = getChild<LLIconCtrl>("content_type_moderate"); + mContentTypeG = getChild<LLIconCtrl>("content_type_general"); + mPriceText = getChild<LLUICtrl>("price_for_listing"); + mAutoRenewText = getChild<LLUICtrl>("auto_renew"); + + mMapButton = getChild<LLButton>("show_on_map_btn"); + mTeleportButton = getChild<LLButton>("teleport_btn"); + mEditButton = getChild<LLButton>("edit_btn"); + + //edit + mClassifiedNameEdit = getChild<LLLineEditor>("classified_name_edit"); + mClassifiedDescEdit = getChild<LLTextEditor>("classified_desc_edit"); + mLocationEdit = getChild<LLUICtrl>("classified_location_edit"); + mCategoryCombo = getChild<LLComboBox>("category_edit"); + mContentTypeCombo = getChild<LLComboBox>("content_type_edit"); + mAutoRenewEdit = getChild<LLUICtrl>("auto_renew_edit"); + + mSaveButton = getChild<LLButton>("save_changes_btn"); + mSetLocationButton = getChild<LLButton>("set_to_curr_location_btn"); + mCancelButton = getChild<LLButton>("cancel_btn"); + + mUtilityBtnCnt = getChild<LLPanel>("util_buttons_lp"); + mPublishBtnsCnt = getChild<LLPanel>("publish_layout_panel"); + mCancelBtnCnt = getChild<LLPanel>("cancel_btn_lp"); + mSaveBtnCnt = getChild<LLPanel>("save_btn_lp"); + + mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelProfileClassified::onTextureSelected, this)); + mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseEnter, this)); + mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseLeave, this)); + mEditIcon->setVisible(false); + + mMapButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onMapClick, this)); + mTeleportButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onTeleportClick, this)); + mEditButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onEditClick, this)); + mSaveButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSaveClick, this)); + mSetLocationButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSetLocationClick, this)); + mCancelButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onCancelClick, this)); + + LLClassifiedInfo::cat_map::iterator iter; + for (iter = LLClassifiedInfo::sCategories.begin(); + iter != LLClassifiedInfo::sCategories.end(); + iter++) + { + mCategoryCombo->add(LLTrans::getString(iter->second)); + } + + mClassifiedNameEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this), NULL); + mClassifiedDescEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + mCategoryCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + mContentTypeCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + mAutoRenewEdit->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + + return TRUE; +} + +void LLPanelProfileClassified::onOpen(const LLSD& key) +{ + mIsNew = key.isUndefined(); + + resetData(); + resetControls(); + scrollToTop(); + + // classified is not created yet + bool is_new = isNew() || isNewWithErrors(); + + if(is_new) + { + LLPanelProfilePropertiesProcessorTab::setAvatarId(gAgent.getID()); + + setPosGlobal(gAgent.getPositionGlobal()); + + LLUUID snapshot_id = LLUUID::null; + std::string desc; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(parcel) + { + desc = parcel->getDesc(); + snapshot_id = parcel->getSnapshotID(); + } + + std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + setClassifiedName(makeClassifiedName()); + setDescription(desc); + setSnapshotId(snapshot_id); + setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + // server will set valid parcel id + setParcelId(LLUUID::null); + + mSaveButton->setLabelArg("[LABEL]", getString("publish_label")); + + setEditMode(TRUE); + enableSave(true); + enableEditing(true); + resetDirty(); + setInfoLoaded(false); + } + else + { + LLUUID avatar_id = key["classified_creator_id"]; + if(avatar_id.isNull()) + { + return; + } + LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + + setClassifiedId(key["classified_id"]); + setClassifiedName(key["classified_name"]); + setFromSearch(key["from_search"]); + mEditOnLoad = key["edit"]; + + LL_INFOS() << "Opening classified [" << getClassifiedName() << "] (" << getClassifiedId() << ")" << LL_ENDL; + + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + + gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); + + if (gAgent.getRegion()) + { + // While we're at it let's get the stats from the new table if that + // capability exists. + std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); + if (!url.empty()) + { + LL_INFOS() << "Classified stat request via capability" << LL_ENDL; + LLSD body; + LLUUID classifiedId = getClassifiedId(); + body["classified_id"] = classifiedId; + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, + boost::bind(&LLPanelProfileClassified::handleSearchStatResponse, classifiedId, _1)); + } + } + // Update classified click stats. + // *TODO: Should we do this when opening not from search? + if (!fromSearch() ) + { + sendClickMessage("profile"); + } + + setInfoLoaded(false); + } + + + bool is_self = getSelfProfile(); + getChildView("auto_renew_layout_panel")->setVisible(is_self); + getChildView("clickthrough_layout_panel")->setVisible(is_self); + + updateButtons(); +} + +void LLPanelProfileClassified::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_CLASSIFIED_INFO != type) + { + return; + } + + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if(c_info && getClassifiedId() == c_info->classified_id) + { + // see LLPanelProfileClassified::sendUpdate() for notes + if (mIsNewWithErrors) + { + // We just published it + setEditMode(FALSE); + } + mIsNewWithErrors = false; + mIsNew = false; + + setClassifiedName(c_info->name); + setDescription(c_info->description); + setSnapshotId(c_info->snapshot_id); + setParcelId(c_info->parcel_id); + setPosGlobal(c_info->pos_global); + setSimName(c_info->sim_name); + + setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); + + mCategoryText->setValue(LLClassifiedInfo::sCategories[c_info->category]); + // *HACK see LLPanelProfileClassified::sendUpdate() + setCategory(c_info->category - 1); + + bool mature = is_cf_mature(c_info->flags); + setContentType(mature); + + bool auto_renew = is_cf_auto_renew(c_info->flags); + std::string auto_renew_str = auto_renew ? getString("auto_renew_on") : getString("auto_renew_off"); + mAutoRenewText->setValue(auto_renew_str); + mAutoRenewEdit->setValue(auto_renew); + + static LLUIString price_str = getString("l$_price"); + price_str.setArg("[PRICE]", llformat("%d", c_info->price_for_listing)); + mPriceText->setValue(LLSD(price_str)); + + static std::string date_fmt = getString("date_fmt"); + std::string date_str = date_fmt; + LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date)); + getChild<LLUICtrl>("creation_date")->setValue(date_str); + + resetDirty(); + setInfoLoaded(true); + enableSave(false); + enableEditing(true); + + // for just created classified - in case user opened edit panel before processProperties() callback + mSaveButton->setLabelArg("[LABEL]", getString("save_label")); + + setLoaded(); + updateButtons(); + + if (mEditOnLoad) + { + setEditMode(TRUE); + } + } + +} + +void LLPanelProfileClassified::setEditMode(BOOL edit_mode) +{ + mEditMode = edit_mode; + + mInfoPanel->setVisible(!edit_mode); + mEditPanel->setVisible(edit_mode); + + // snapshot control is common between info and edit, + // enable it only when in edit mode + mSnapshotCtrl->setEnabled(edit_mode); + + scrollToTop(); + updateButtons(); + updateInfoRect(); +} + +void LLPanelProfileClassified::updateButtons() +{ + bool edit_mode = getEditMode(); + mUtilityBtnCnt->setVisible(!edit_mode); + + // cancel button should either delete unpublished + // classified or not be there at all + mCancelBtnCnt->setVisible(edit_mode && !mIsNew); + mPublishBtnsCnt->setVisible(edit_mode); + mSaveBtnCnt->setVisible(edit_mode); + mEditButton->setVisible(!edit_mode && getSelfProfile()); +} + +void LLPanelProfileClassified::updateInfoRect() +{ + if (getEditMode()) + { + // info_scroll_content_panel contains both info and edit panel + // info panel can be very large and scroll bar will carry over. + // Resize info panel to prevent scroll carry over when in edit mode. + mInfoScroll->reshape(mInfoScroll->getRect().getWidth(), DEFAULT_EDIT_CLASSIFIED_SCROLL_HEIGHT, FALSE); + } + else + { + // Adjust text height to make description scrollable. + S32 new_height = mClassifiedDescText->getTextBoundingRect().getHeight(); + LLRect visible_rect = mClassifiedDescText->getVisibleDocumentRect(); + S32 delta_height = new_height - visible_rect.getHeight() + 5; + + LLRect rect = mInfoScroll->getRect(); + mInfoScroll->reshape(rect.getWidth(), rect.getHeight() + delta_height, FALSE); + } +} + +void LLPanelProfileClassified::enableEditing(bool enable) +{ + mEditButton->setEnabled(enable); + mClassifiedNameEdit->setEnabled(enable); + mClassifiedDescEdit->setEnabled(enable); + mSetLocationButton->setEnabled(enable); + mCategoryCombo->setEnabled(enable); + mContentTypeCombo->setEnabled(enable); + mAutoRenewEdit->setEnabled(enable); +} + +void LLPanelProfileClassified::resetControls() +{ + updateButtons(); + + mCategoryCombo->setCurrentByIndex(0); + mContentTypeCombo->setCurrentByIndex(0); + mAutoRenewEdit->setValue(false); + mPriceForListing = MINIMUM_PRICE_FOR_LISTING; +} + +void LLPanelProfileClassified::onEditClick() +{ + setEditMode(TRUE); +} + +void LLPanelProfileClassified::onCancelClick() +{ + if (isNew()) + { + mClassifiedNameEdit->setValue(mClassifiedNameText->getValue()); + mClassifiedDescEdit->setValue(mClassifiedDescText->getValue()); + mLocationEdit->setValue(mLocationText->getValue()); + mCategoryCombo->setCurrentByIndex(0); + mContentTypeCombo->setCurrentByIndex(0); + mAutoRenewEdit->setValue(false); + mPriceForListing = MINIMUM_PRICE_FOR_LISTING; + } + else + { + // Reload data to undo changes to forms + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + } + + setInfoLoaded(false); + + setEditMode(FALSE); +} + +void LLPanelProfileClassified::onSaveClick() +{ + mCanClose = false; + + if(!isValidName()) + { + notifyInvalidName(); + return; + } + if(isNew() || isNewWithErrors()) + { + if(gStatusBar->getBalance() < getPriceForListing()) + { + LLNotificationsUtil::add("ClassifiedInsufficientFunds"); + return; + } + + mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( + "publish_classified", LLSD()); + + if(!mPublishFloater) + { + mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( + "publish_classified", LLSD()); + + mPublishFloater->setPublishClickedCallback(boost::bind + (&LLPanelProfileClassified::onPublishFloaterPublishClicked, this)); + } + + // set spinner value before it has focus or value wont be set + mPublishFloater->setPrice(getPriceForListing()); + mPublishFloater->openFloater(mPublishFloater->getKey()); + mPublishFloater->center(); + } + else + { + doSave(); + } +} + +/*static*/ +void LLPanelProfileClassified::handleSearchStatResponse(LLUUID classifiedId, LLSD result) +{ + S32 teleport = result["teleport_clicks"].asInteger(); + S32 map = result["map_clicks"].asInteger(); + S32 profile = result["profile_clicks"].asInteger(); + S32 search_teleport = result["search_teleport_clicks"].asInteger(); + S32 search_map = result["search_map_clicks"].asInteger(); + S32 search_profile = result["search_profile_clicks"].asInteger(); + + LLPanelProfileClassified::setClickThrough(classifiedId, + teleport + search_teleport, + map + search_map, + profile + search_profile, + true); +} + +void LLPanelProfileClassified::resetData() +{ + setClassifiedName(LLStringUtil::null); + setDescription(LLStringUtil::null); + setClassifiedLocation(LLStringUtil::null); + setClassifiedId(LLUUID::null); + setSnapshotId(LLUUID::null); + setPosGlobal(LLVector3d::zero); + setParcelId(LLUUID::null); + setSimName(LLStringUtil::null); + setFromSearch(false); + + // reset click stats + mTeleportClicksOld = 0; + mMapClicksOld = 0; + mProfileClicksOld = 0; + mTeleportClicksNew = 0; + mMapClicksNew = 0; + mProfileClicksNew = 0; + + mPriceForListing = MINIMUM_PRICE_FOR_LISTING; + + mCategoryText->setValue(LLStringUtil::null); + mContentTypeText->setValue(LLStringUtil::null); + getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null); + mEditButton->setValue(LLStringUtil::null); + getChild<LLUICtrl>("creation_date")->setValue(LLStringUtil::null); + mContentTypeM->setVisible(FALSE); + mContentTypeG->setVisible(FALSE); +} + +void LLPanelProfileClassified::setClassifiedName(const std::string& name) +{ + mClassifiedNameText->setValue(name); + mClassifiedNameEdit->setValue(name); +} + +std::string LLPanelProfileClassified::getClassifiedName() +{ + return mClassifiedNameEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setDescription(const std::string& desc) +{ + mClassifiedDescText->setValue(desc); + mClassifiedDescEdit->setValue(desc); + + updateInfoRect(); +} + +std::string LLPanelProfileClassified::getDescription() +{ + return mClassifiedDescEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setClassifiedLocation(const std::string& location) +{ + mLocationText->setValue(location); + mLocationEdit->setValue(location); +} + +std::string LLPanelProfileClassified::getClassifiedLocation() +{ + return mLocationText->getValue().asString(); +} + +void LLPanelProfileClassified::setSnapshotId(const LLUUID& id) +{ + mSnapshotCtrl->setValue(id); +} + +LLUUID LLPanelProfileClassified::getSnapshotId() +{ + return mSnapshotCtrl->getValue().asUUID(); +} + +// static +void LLPanelProfileClassified::setClickThrough( + const LLUUID& classified_id, + S32 teleport, + S32 map, + S32 profile, + bool from_new_table) +{ + LL_INFOS() << "Click-through data for classified " << classified_id << " arrived: [" + << teleport << ", " << map << ", " << profile << "] (" + << (from_new_table ? "new" : "old") << ")" << LL_ENDL; + + for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) + { + LLPanelProfileClassified* self = *iter; + if (self->getClassifiedId() != classified_id) + { + continue; + } + + // *HACK: Skip LLPanelProfileClassified instances: they don't display clicks data. + // Those instances should not be in the list at all. + if (typeid(*self) != typeid(LLPanelProfileClassified)) + { + continue; + } + + LL_INFOS() << "Updating classified info panel" << LL_ENDL; + + // We need to check to see if the data came from the new stat_table + // or the old classified table. We also need to cache the data from + // the two separate sources so as to display the aggregate totals. + + if (from_new_table) + { + self->mTeleportClicksNew = teleport; + self->mMapClicksNew = map; + self->mProfileClicksNew = profile; + } + else + { + self->mTeleportClicksOld = teleport; + self->mMapClicksOld = map; + self->mProfileClicksOld = profile; + } + + static LLUIString ct_str = self->getString("click_through_text_fmt"); + + ct_str.setArg("[TELEPORT]", llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld)); + ct_str.setArg("[MAP]", llformat("%d", self->mMapClicksNew + self->mMapClicksOld)); + ct_str.setArg("[PROFILE]", llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld)); + + self->getChild<LLUICtrl>("click_through_text")->setValue(ct_str.getString()); + // *HACK: remove this when there is enough room for click stats in the info panel + self->getChildView("click_through_text")->setToolTip(ct_str.getString()); + + LL_INFOS() << "teleport: " << llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld) + << ", map: " << llformat("%d", self->mMapClicksNew + self->mMapClicksOld) + << ", profile: " << llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld) + << LL_ENDL; + } +} + +// static +std::string LLPanelProfileClassified::createLocationText( + const std::string& original_name, + const std::string& sim_name, + const LLVector3d& pos_global) +{ + std::string location_text; + + location_text.append(original_name); + + if (!sim_name.empty()) + { + if (!location_text.empty()) + location_text.append(", "); + location_text.append(sim_name); + } + + if (!location_text.empty()) + location_text.append(" "); + + if (!pos_global.isNull()) + { + S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; + S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; + S32 region_z = ll_round((F32)pos_global.mdV[VZ]); + location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); + } + + return location_text; +} + +void LLPanelProfileClassified::scrollToTop() +{ + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } +} + +//info +// static +// *TODO: move out of the panel +void LLPanelProfileClassified::sendClickMessage( + const std::string& type, + bool from_search, + const LLUUID& classified_id, + const LLUUID& parcel_id, + const LLVector3d& global_pos, + const std::string& sim_name) +{ + if (gAgent.getRegion()) + { + // You're allowed to click on your own ads to reassure yourself + // that the system is working. + LLSD body; + body["type"] = type; + body["from_search"] = from_search; + body["classified_id"] = classified_id; + body["parcel_id"] = parcel_id; + body["dest_pos_global"] = global_pos.getValue(); + body["region_name"] = sim_name; + + std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); + LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; + LL_INFOS() << "body: [" << body << "]" << LL_ENDL; + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, + "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); + } +} + +void LLPanelProfileClassified::sendClickMessage(const std::string& type) +{ + sendClickMessage( + type, + fromSearch(), + getClassifiedId(), + getParcelId(), + getPosGlobal(), + getSimName()); +} + +void LLPanelProfileClassified::onMapClick() +{ + sendClickMessage("map"); + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfileClassified::onTeleportClick() +{ + if (!getPosGlobal().isExactlyZero()) + { + sendClickMessage("teleport"); + gAgent.teleportViaLocation(getPosGlobal()); + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + } +} + +BOOL LLPanelProfileClassified::isDirty() const +{ + if(mIsNew) + { + return TRUE; + } + + BOOL dirty = false; + dirty |= mSnapshotCtrl->isDirty(); + dirty |= mClassifiedNameEdit->isDirty(); + dirty |= mClassifiedDescEdit->isDirty(); + dirty |= mCategoryCombo->isDirty(); + dirty |= mContentTypeCombo->isDirty(); + dirty |= mAutoRenewEdit->isDirty(); + + return dirty; +} + +void LLPanelProfileClassified::resetDirty() +{ + mSnapshotCtrl->resetDirty(); + mClassifiedNameEdit->resetDirty(); + + // call blockUndo() to really reset dirty(and make isDirty work as intended) + mClassifiedDescEdit->blockUndo(); + mClassifiedDescEdit->resetDirty(); + + mCategoryCombo->resetDirty(); + mContentTypeCombo->resetDirty(); + mAutoRenewEdit->resetDirty(); +} + +bool LLPanelProfileClassified::canClose() +{ + return mCanClose; +} + +U32 LLPanelProfileClassified::getContentType() +{ + return mContentTypeCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setContentType(bool mature) +{ + static std::string mature_str = getString("type_mature"); + static std::string pg_str = getString("type_pg"); + mContentTypeText->setValue(mature ? mature_str : pg_str); + mContentTypeM->setVisible(mature); + mContentTypeG->setVisible(!mature); + mContentTypeCombo->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG); + mContentTypeCombo->resetDirty(); +} + +bool LLPanelProfileClassified::getAutoRenew() +{ + return mAutoRenewEdit->getValue().asBoolean(); +} + +void LLPanelProfileClassified::sendUpdate() +{ + LLAvatarClassifiedInfo c_data; + + if(getClassifiedId().isNull()) + { + setClassifiedId(LLUUID::generateNewID()); + } + + c_data.agent_id = gAgent.getID(); + c_data.classified_id = getClassifiedId(); + // *HACK + // Categories on server start with 1 while combo-box index starts with 0 + c_data.category = getCategory() + 1; + c_data.name = getClassifiedName(); + c_data.description = getDescription(); + c_data.parcel_id = getParcelId(); + c_data.snapshot_id = getSnapshotId(); + c_data.pos_global = getPosGlobal(); + c_data.flags = getFlags(); + c_data.price_for_listing = getPriceForListing(); + + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); + + if(isNew()) + { + // Lets assume there will be some error. + // Successful sendClassifiedInfoUpdate will trigger processProperties and + // let us know there was no error. + mIsNewWithErrors = true; + } +} + +U32 LLPanelProfileClassified::getCategory() +{ + return mCategoryCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setCategory(U32 category) +{ + mCategoryCombo->setCurrentByIndex(category); + mCategoryCombo->resetDirty(); +} + +U8 LLPanelProfileClassified::getFlags() +{ + bool auto_renew = mAutoRenewEdit->getValue().asBoolean(); + + bool mature = mContentTypeCombo->getCurrentIndex() == CB_ITEM_MATURE; + + return pack_classified_flags_request(auto_renew, false, mature, false); +} + +void LLPanelProfileClassified::enableSave(bool enable) +{ + mSaveButton->setEnabled(enable); +} + +std::string LLPanelProfileClassified::makeClassifiedName() +{ + std::string name; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(parcel) + { + name = parcel->getName(); + } + + if(!name.empty()) + { + return name; + } + + LLViewerRegion* region = gAgent.getRegion(); + if(region) + { + name = region->getName(); + } + + return name; +} + +void LLPanelProfileClassified::onSetLocationClick() +{ + setPosGlobal(gAgent.getPositionGlobal()); + setParcelId(LLUUID::null); + + std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + + // mark classified as dirty + setValue(LLSD()); + + onChange(); +} + +void LLPanelProfileClassified::onChange() +{ + enableSave(isDirty()); +} + +void LLPanelProfileClassified::doSave() +{ + //*TODO: Fix all of this + + mCanClose = true; + sendUpdate(); + updateTabLabel(getClassifiedName()); + resetDirty(); + + if (!canClose()) + { + return; + } + + if (!isNew() && !isNewWithErrors()) + { + setEditMode(FALSE); + return; + } + + updateButtons(); +} + +void LLPanelProfileClassified::onPublishFloaterPublishClicked() +{ + setPriceForListing(mPublishFloater->getPrice()); + + doSave(); +} + +std::string LLPanelProfileClassified::getLocationNotice() +{ + static std::string location_notice = getString("location_notice"); + return location_notice; +} + +bool LLPanelProfileClassified::isValidName() +{ + std::string name = getClassifiedName(); + if (name.empty()) + { + return false; + } + if (!isalnum(name[0])) + { + return false; + } + + return true; +} + +void LLPanelProfileClassified::notifyInvalidName() +{ + std::string name = getClassifiedName(); + if (name.empty()) + { + LLNotificationsUtil::add("BlankClassifiedName"); + } + else if (!isalnum(name[0])) + { + LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); + } +} + +void LLPanelProfileClassified::onTexturePickerMouseEnter() +{ + mEditIcon->setVisible(TRUE); +} + +void LLPanelProfileClassified::onTexturePickerMouseLeave() +{ + mEditIcon->setVisible(FALSE); +} + +void LLPanelProfileClassified::onTextureSelected() +{ + setSnapshotId(mSnapshotCtrl->getValue().asUUID()); + onChange(); +} + +void LLPanelProfileClassified::updateTabLabel(const std::string& title) +{ + setLabel(title); + LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); + if (parent) + { + parent->setCurrentTabName(title); + } +} + + +//----------------------------------------------------------------------------- +// LLPublishClassifiedFloater +//----------------------------------------------------------------------------- + +LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) + : LLFloater(key) +{ +} + +LLPublishClassifiedFloater::~LLPublishClassifiedFloater() +{ +} + +BOOL LLPublishClassifiedFloater::postBuild() +{ + LLFloater::postBuild(); + + childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); + childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); + + return TRUE; +} + +void LLPublishClassifiedFloater::setPrice(S32 price) +{ + getChild<LLUICtrl>("price_for_listing")->setValue(price); +} + +S32 LLPublishClassifiedFloater::getPrice() +{ + return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); +} + +void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) +{ + getChild<LLButton>("publish_btn")->setClickedCallback(cb); +} + +void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) +{ + getChild<LLButton>("cancel_btn")->setClickedCallback(cb); +} diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h new file mode 100644 index 0000000000..912819e86b --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.h @@ -0,0 +1,340 @@ +/** + * @file llpanelprofileclassifieds.h + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PANELPROFILECLASSIFIEDS_H +#define LL_PANELPROFILECLASSIFIEDS_H + +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedinfo.h" +#include "llfloater.h" +#include "llpanel.h" +#include "llpanelavatar.h" +#include "llrect.h" +#include "lluuid.h" +#include "v3dmath.h" +#include "llcoros.h" +#include "lleventcoro.h" + +class LLCheckBoxCtrl; +class LLLineEditor; +class LLMediaCtrl; +class LLScrollContainer; +class LLTabContainer; +class LLTextEditor; +class LLTextureCtrl; +class LLUICtrl; + + +class LLPublishClassifiedFloater : public LLFloater +{ +public: + LLPublishClassifiedFloater(const LLSD& key); + virtual ~LLPublishClassifiedFloater(); + + BOOL postBuild() override; + + void setPrice(S32 price); + S32 getPrice(); + + void setPublishClickedCallback(const commit_signal_t::slot_type& cb); + void setCancelClickedCallback(const commit_signal_t::slot_type& cb); +}; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfileClassifieds + : public LLPanelProfilePropertiesProcessorTab +{ +public: + LLPanelProfileClassifieds(); + /*virtual*/ ~LLPanelProfileClassifieds(); + + BOOL postBuild() override; + + void onOpen(const LLSD& key) override; + + void selectClassified(const LLUUID& classified_id, bool edit); + + void createClassified(); + + void processProperties(void* data, EAvatarProcessorType type) override; + + void resetData() override; + + void updateButtons(); + + void updateData() override; + + bool hasNewClassifieds(); + bool hasUnsavedChanges() override; + // commits changes to existing classifieds, but does not publish new classified! + void commitUnsavedChanges() override; + +private: + void onClickNewBtn(); + void onClickDelete(); + void callbackDeleteClassified(const LLSD& notification, const LLSD& response); + + bool canAddNewClassified(); + bool canDeleteClassified(); + + LLTabContainer* mTabContainer; + LLUICtrl* mNoItemsLabel; + LLButton* mNewButton; + LLButton* mDeleteButton; + + LLUUID mClassifiedToSelectOnLoad; + bool mClassifiedEditOnLoad; + bool mSheduledClassifiedCreation; +}; + + +class LLPanelProfileClassified + : public LLPanelProfilePropertiesProcessorTab +{ +public: + + static LLPanelProfileClassified* create(); + + LLPanelProfileClassified(); + + /*virtual*/ ~LLPanelProfileClassified(); + + BOOL postBuild() override; + + void onOpen(const LLSD& key) override; + + void processProperties(void* data, EAvatarProcessorType type) override; + + void setSnapshotId(const LLUUID& id); + + LLUUID getSnapshotId(); + + void setClassifiedId(const LLUUID& id) { mClassifiedId = id; } + + LLUUID& getClassifiedId() { return mClassifiedId; } + + void setClassifiedName(const std::string& name); + + std::string getClassifiedName(); + + void setDescription(const std::string& desc); + + std::string getDescription(); + + void setClassifiedLocation(const std::string& location); + + std::string getClassifiedLocation(); + + void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + + LLVector3d& getPosGlobal() { return mPosGlobal; } + + void setParcelId(const LLUUID& id) { mParcelId = id; } + + LLUUID getParcelId() { return mParcelId; } + + void setSimName(const std::string& sim_name) { mSimName = sim_name; } + + std::string getSimName() { return mSimName; } + + void setFromSearch(bool val) { mFromSearch = val; } + + bool fromSearch() { return mFromSearch; } + + bool getInfoLoaded() { return mInfoLoaded; } + + void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } + + BOOL isDirty() const override; + + void resetDirty() override; + + bool isNew() { return mIsNew; } + + bool isNewWithErrors() { return mIsNewWithErrors; } + + bool canClose(); + + U32 getCategory(); + + void setCategory(U32 category); + + U32 getContentType(); + + void setContentType(bool mature); + + bool getAutoRenew(); + + S32 getPriceForListing() { return mPriceForListing; } + + void setEditMode(BOOL edit_mode); + bool getEditMode() {return mEditMode;} + + static void setClickThrough( + const LLUUID& classified_id, + S32 teleport, + S32 map, + S32 profile, + bool from_new_table); + + static void sendClickMessage( + const std::string& type, + bool from_search, + const LLUUID& classified_id, + const LLUUID& parcel_id, + const LLVector3d& global_pos, + const std::string& sim_name); + + void doSave(); + +protected: + + void resetData() override; + + void resetControls(); + + void updateButtons(); + void updateInfoRect(); + + static std::string createLocationText( + const std::string& original_name, + const std::string& sim_name, + const LLVector3d& pos_global); + + void sendClickMessage(const std::string& type); + + void scrollToTop(); + + void onEditClick(); + void onCancelClick(); + void onSaveClick(); + void onMapClick(); + void onTeleportClick(); + + void sendUpdate(); + + void enableSave(bool enable); + + void enableEditing(bool enable); + + std::string makeClassifiedName(); + + void setPriceForListing(S32 price) { mPriceForListing = price; } + + U8 getFlags(); + + std::string getLocationNotice(); + + bool isValidName(); + + void notifyInvalidName(); + + void onSetLocationClick(); + void onChange(); + + void onPublishFloaterPublishClicked(); + + void onTexturePickerMouseEnter(); + void onTexturePickerMouseLeave(); + + void onTextureSelected(); + + void updateTabLabel(const std::string& title); + +private: + + LLTextureCtrl* mSnapshotCtrl; + LLUICtrl* mEditIcon; + LLUICtrl* mClassifiedNameText; + LLTextEditor* mClassifiedDescText; + LLLineEditor* mClassifiedNameEdit; + LLTextEditor* mClassifiedDescEdit; + LLUICtrl* mLocationText; + LLUICtrl* mLocationEdit; + LLUICtrl* mCategoryText; + LLComboBox* mCategoryCombo; + LLUICtrl* mContentTypeText; + LLIconCtrl* mContentTypeM; + LLIconCtrl* mContentTypeG; + LLComboBox* mContentTypeCombo; + LLUICtrl* mPriceText; + LLUICtrl* mAutoRenewText; + LLUICtrl* mAutoRenewEdit; + + LLButton* mMapButton; + LLButton* mTeleportButton; + LLButton* mEditButton; + LLButton* mSaveButton; + LLButton* mSetLocationButton; + LLButton* mCancelButton; + + LLPanel* mUtilityBtnCnt; + LLPanel* mPublishBtnsCnt; + LLPanel* mSaveBtnCnt; + LLPanel* mCancelBtnCnt; + + LLScrollContainer* mScrollContainer; + LLView* mInfoPanel; + LLPanel* mInfoScroll; + LLPanel* mEditPanel; + + + LLUUID mClassifiedId; + LLVector3d mPosGlobal; + LLUUID mParcelId; + std::string mSimName; + bool mFromSearch; + bool mInfoLoaded; + bool mEditMode; + + // Needed for stat tracking + S32 mTeleportClicksOld; + S32 mMapClicksOld; + S32 mProfileClicksOld; + S32 mTeleportClicksNew; + S32 mMapClicksNew; + S32 mProfileClicksNew; + + S32 mPriceForListing; + + static void handleSearchStatResponse(LLUUID classifiedId, LLSD result); + + typedef std::list<LLPanelProfileClassified*> panel_list_t; + static panel_list_t sAllPanels; + + + bool mIsNew; + bool mIsNewWithErrors; + bool mCanClose; + bool mEditOnLoad; + + LLPublishClassifiedFloater* mPublishFloater; +}; + +#endif // LL_PANELPROFILECLASSIFIEDS_H diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp new file mode 100644 index 0000000000..774119f169 --- /dev/null +++ b/indra/newview/llpanelprofilepicks.cpp @@ -0,0 +1,883 @@ +/** + * @file llpanelprofilepicks.cpp + * @brief LLPanelProfilePicks and related class implementations + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelprofilepicks.h" + +#include "llagent.h" +#include "llagentpicksinfo.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llcommandhandler.h" +#include "lldispatcher.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llpanelprofile.h" +#include "llparcel.h" +#include "llstartup.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" + +static LLPanelInjector<LLPanelProfilePicks> t_panel_profile_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfilePick> t_panel_profile_pick("panel_profile_pick"); + + +class LLPickHandler : public LLCommandHandler +{ +public: + + // requires trusted browser to trigger + LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (LLStartUp::getStartupState() < STATE_STARTED) + { + return true; + } + + if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnablePicks")) + { + LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + + // handle app/pick/create urls first + if (params.size() == 1 && params[0].asString() == "create") + { + LLAvatarActions::createPick(); + return true; + } + + // then handle the general app/pick/{UUID}/{CMD} urls + if (params.size() < 2) + { + return false; + } + + // get the ID for the pick_id + LLUUID pick_id; + if (!pick_id.set(params[0], FALSE)) + { + return false; + } + + // edit the pick in the side tray. + // need to ask the server for more info first though... + const std::string verb = params[1].asString(); + if (verb == "edit") + { + LLAvatarActions::showPick(gAgent.getID(), pick_id); + return true; + } + else + { + LL_WARNS() << "unknown verb " << verb << LL_ENDL; + return false; + } + } +}; +LLPickHandler gPickHandler; + + +//----------------------------------------------------------------------------- +// LLPanelProfilePicks +//----------------------------------------------------------------------------- + +LLPanelProfilePicks::LLPanelProfilePicks() + : LLPanelProfilePropertiesProcessorTab() + , mPickToSelectOnLoad(LLUUID::null) +{ +} + +LLPanelProfilePicks::~LLPanelProfilePicks() +{ +} + +void LLPanelProfilePicks::onOpen(const LLSD& key) +{ + LLPanelProfilePropertiesProcessorTab::onOpen(key); + + resetData(); + + bool own_profile = getSelfProfile(); + if (own_profile) + { + mNewButton->setVisible(TRUE); + mNewButton->setEnabled(FALSE); + + mDeleteButton->setVisible(TRUE); + mDeleteButton->setEnabled(FALSE); + } + + childSetVisible("buttons_header", own_profile); +} + +void LLPanelProfilePicks::createPick(const LLPickData &data) +{ + if (getIsLoaded()) + { + if (canAddNewPick()) + { + mNoItemsLabel->setVisible(FALSE); + LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + pick_panel->setAvatarId(getAvatarId()); + pick_panel->processProperties(&data); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(pick_panel). + select_tab(true). + label(pick_panel->getPickName())); + updateButtons(); + } + else + { + // This means that something doesn't properly check limits + // before creating a pick + LL_WARNS() << "failed to add pick" << LL_ENDL; + } + } + else + { + mSheduledPickCreation.push_back(data); + } +} + +void LLPanelProfilePicks::selectPick(const LLUUID& pick_id) +{ + if (getIsLoaded()) + { + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); + if (pick_panel) + { + if (pick_panel->getPickId() == pick_id) + { + mTabContainer->selectTabPanel(pick_panel); + break; + } + } + } + } + else + { + mPickToSelectOnLoad = pick_id; + } +} + +BOOL LLPanelProfilePicks::postBuild() +{ + mTabContainer = getChild<LLTabContainer>("tab_picks"); + mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); + mNewButton = getChild<LLButton>("new_btn"); + mDeleteButton = getChild<LLButton>("delete_btn"); + + mNewButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickNewBtn, this)); + mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickDelete, this)); + + return TRUE; +} + +void LLPanelProfilePicks::onClickNewBtn() +{ + mNoItemsLabel->setVisible(FALSE); + LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + pick_panel->setAvatarId(getAvatarId()); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(pick_panel). + select_tab(true). + label(pick_panel->getPickName())); + updateButtons(); +} + +void LLPanelProfilePicks::onClickDelete() +{ + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); + if (pick_panel) + { + LLUUID pick_id = pick_panel->getPickId(); + LLSD args; + args["PICK"] = pick_panel->getPickName(); + LLSD payload; + payload["pick_id"] = pick_id; + payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); + LLNotificationsUtil::add("ProfileDeletePick", args, payload, + boost::bind(&LLPanelProfilePicks::callbackDeletePick, this, _1, _2)); + } +} + +void LLPanelProfilePicks::callbackDeletePick(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + LLUUID pick_id = notification["payload"]["pick_id"].asUUID(); + S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); + if (pick_panel && pick_panel->getPickId() == pick_id) + { + mTabContainer->removeTabPanel(pick_panel); + } + + if (pick_id.notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->sendPickDelete(pick_id); + } + + updateButtons(); + } +} + +void LLPanelProfilePicks::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PICKS == type) + { + LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); + if (avatar_picks && getAvatarId() == avatar_picks->target_id) + { + processProperties(avatar_picks); + } + } +} + +void LLPanelProfilePicks::processProperties(const LLAvatarPicks* avatar_picks) +{ + LLUUID selected_id = mPickToSelectOnLoad; + bool has_selection = false; + if (mPickToSelectOnLoad.isNull()) + { + if (mTabContainer->getTabCount() > 0) + { + LLPanelProfilePick* active_pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); + if (active_pick_panel) + { + selected_id = active_pick_panel->getPickId(); + } + } + } + + mTabContainer->deleteAllTabs(); + + LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); + for (; avatar_picks->picks_list.end() != it; ++it) + { + LLUUID pick_id = it->first; + std::string pick_name = it->second; + + LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + + pick_panel->setPickId(pick_id); + pick_panel->setPickName(pick_name); + pick_panel->setAvatarId(getAvatarId()); + + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(pick_panel). + select_tab(selected_id == pick_id). + label(pick_name)); + + if (selected_id == pick_id) + { + has_selection = true; + } + } + + while (!mSheduledPickCreation.empty() && canAddNewPick()) + { + const LLPickData data = + mSheduledPickCreation.back(); + + LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + pick_panel->setAvatarId(getAvatarId()); + pick_panel->processProperties(&data); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(pick_panel). + select_tab(!has_selection). + label(pick_panel->getPickName())); + + mSheduledPickCreation.pop_back(); + has_selection = true; + } + + // reset 'do on load' values + mPickToSelectOnLoad = LLUUID::null; + mSheduledPickCreation.clear(); + + if (getSelfProfile()) + { + mNoItemsLabel->setValue(LLTrans::getString("NoPicksText")); + } + else + { + mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksText")); + } + + bool has_data = mTabContainer->getTabCount() > 0; + mNoItemsLabel->setVisible(!has_data); + if (has_data && !has_selection) + { + mTabContainer->selectFirstTab(); + } + + setLoaded(); + updateButtons(); +} + +void LLPanelProfilePicks::resetData() +{ + resetLoading(); + mTabContainer->deleteAllTabs(); +} + +void LLPanelProfilePicks::updateButtons() +{ + if (getSelfProfile()) + { + mNewButton->setEnabled(canAddNewPick()); + mDeleteButton->setEnabled(canDeletePick()); + } +} + +void LLPanelProfilePicks::apply() +{ + if (getIsLoaded()) + { + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); + if (pick_panel) + { + pick_panel->apply(); + } + } + } +} + +void LLPanelProfilePicks::updateData() +{ + // Send picks request only once + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(avatar_id); + } + if (!getIsLoaded()) + { + mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); + mNoItemsLabel->setVisible(TRUE); + } +} + +bool LLPanelProfilePicks::hasUnsavedChanges() +{ + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); + if (pick_panel && (pick_panel->isDirty() || pick_panel->isDirty())) + { + return true; + } + } + return false; +} + +void LLPanelProfilePicks::commitUnsavedChanges() +{ + for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + { + LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); + if (pick_panel) + { + pick_panel->apply(); + } + } +} + +bool LLPanelProfilePicks::canAddNewPick() +{ + return (!LLAgentPicksInfo::getInstance()->isPickLimitReached() && + mTabContainer->getTabCount() < LLAgentPicksInfo::getInstance()->getMaxNumberOfPicks()); +} + +bool LLPanelProfilePicks::canDeletePick() +{ + return (mTabContainer->getTabCount() > 0); +} + + +//----------------------------------------------------------------------------- +// LLPanelProfilePick +//----------------------------------------------------------------------------- + +LLPanelProfilePick::LLPanelProfilePick() + : LLPanelProfilePropertiesProcessorTab() + , LLRemoteParcelInfoObserver() + , mSnapshotCtrl(NULL) + , mPickId(LLUUID::null) + , mParcelId(LLUUID::null) + , mRequestedId(LLUUID::null) + , mLocationChanged(false) + , mNewPick(false) + , mIsEditing(false) +{ +} + +//static +LLPanelProfilePick* LLPanelProfilePick::create() +{ + LLPanelProfilePick* panel = new LLPanelProfilePick(); + panel->buildFromFile("panel_profile_pick.xml"); + return panel; +} + +LLPanelProfilePick::~LLPanelProfilePick() +{ + if (mParcelId.notNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); + } +} + +void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) +{ + if (avatar_id.isNull()) + { + return; + } + LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + + // creating new Pick + if (getPickId().isNull() && getSelfProfile()) + { + mNewPick = true; + + setPosGlobal(gAgent.getPositionGlobal()); + + LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; + std::string pick_name, pick_desc, region_name; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + parcel_id = parcel->getID(); + pick_name = parcel->getName(); + pick_desc = parcel->getDesc(); + snapshot_id = parcel->getSnapshotID(); + } + + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + setParcelID(parcel_id); + setPickName(pick_name.empty() ? region_name : pick_name); + setPickDesc(pick_desc); + setSnapshotId(snapshot_id); + setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal())); + + enableSaveButton(TRUE); + } + else + { + LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(getAvatarId(), getPickId()); + + enableSaveButton(FALSE); + } + + resetDirty(); + + if (getSelfProfile()) + { + mPickName->setEnabled(TRUE); + mPickDescription->setEnabled(TRUE); + mSetCurrentLocationButton->setVisible(TRUE); + } + else + { + mSnapshotCtrl->setEnabled(FALSE); + } +} + +BOOL LLPanelProfilePick::postBuild() +{ + mPickName = getChild<LLLineEditor>("pick_name"); + mPickDescription = getChild<LLTextEditor>("pick_desc"); + mSaveButton = getChild<LLButton>("save_changes_btn"); + mCreateButton = getChild<LLButton>("create_changes_btn"); + mCancelButton = getChild<LLButton>("cancel_changes_btn"); + mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn"); + + mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot"); + mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); + + childSetAction("teleport_btn", boost::bind(&LLPanelProfilePick::onClickTeleport, this)); + childSetAction("show_on_map_btn", boost::bind(&LLPanelProfilePick::onClickMap, this)); + + mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); + mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); + mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this)); + mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); + + mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); + mPickName->setEnabled(FALSE); + + mPickDescription->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1)); + mPickDescription->setFocusReceivedCallback(boost::bind(&LLPanelProfilePick::onDescriptionFocusReceived, this)); + + getChild<LLUICtrl>("pick_location")->setEnabled(FALSE); + + return TRUE; +} + +void LLPanelProfilePick::onDescriptionFocusReceived() +{ + if (!mIsEditing && getSelfProfile()) + { + mIsEditing = true; + mPickDescription->setParseHTML(false); + } +} + +void LLPanelProfilePick::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PICK_INFO != type) + { + return; + } + + LLPickData* pick_info = static_cast<LLPickData*>(data); + if (!pick_info + || pick_info->creator_id != getAvatarId() + || pick_info->pick_id != getPickId()) + { + return; + } + + processProperties(pick_info); +} + +void LLPanelProfilePick::processProperties(const LLPickData* pick_info) +{ + mIsEditing = false; + mPickDescription->setParseHTML(true); + mParcelId = pick_info->parcel_id; + setSnapshotId(pick_info->snapshot_id); + if (!getSelfProfile()) + { + mSnapshotCtrl->setEnabled(FALSE); + } + setPickName(pick_info->name); + setPickDesc(pick_info->desc); + setPosGlobal(pick_info->pos_global); + + // Send remote parcel info request to get parcel name and sim (region) name. + sendParcelInfoRequest(); + + // *NOTE dzaporozhan + // We want to keep listening to APT_PICK_INFO because user may + // edit the Pick and we have to update Pick info panel. + // revomeObserver is called from onClickBack + + setLoaded(); +} + +void LLPanelProfilePick::apply() +{ + if ((mNewPick || getIsLoaded()) && isDirty()) + { + sendUpdate(); + } +} + +void LLPanelProfilePick::setSnapshotId(const LLUUID& id) +{ + mSnapshotCtrl->setImageAssetID(id); + mSnapshotCtrl->setValid(TRUE); +} + +void LLPanelProfilePick::setPickName(const std::string& name) +{ + mPickName->setValue(name); +} + +const std::string LLPanelProfilePick::getPickName() +{ + return mPickName->getValue().asString(); +} + +void LLPanelProfilePick::setPickDesc(const std::string& desc) +{ + mPickDescription->setValue(desc); +} + +void LLPanelProfilePick::setPickLocation(const std::string& location) +{ + getChild<LLUICtrl>("pick_location")->setValue(location); +} + +void LLPanelProfilePick::onClickMap() +{ + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfilePick::onClickTeleport() +{ + if (!getPosGlobal().isExactlyZero()) + { + gAgent.teleportViaLocation(getPosGlobal()); + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + } +} + +void LLPanelProfilePick::enableSaveButton(BOOL enable) +{ + childSetVisible("save_changes_lp", enable); + + childSetVisible("save_btn_lp", enable && !mNewPick); + childSetVisible("create_btn_lp", enable && mNewPick); + childSetVisible("cancel_btn_lp", enable && !mNewPick); +} + +void LLPanelProfilePick::onSnapshotChanged() +{ + enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onPickChanged(LLUICtrl* ctrl) +{ + if (ctrl && ctrl == mPickName) + { + updateTabLabel(mPickName->getText()); + } + + enableSaveButton(isDirty()); +} + +void LLPanelProfilePick::resetDirty() +{ + LLPanel::resetDirty(); + + mPickName->resetDirty(); + mPickDescription->resetDirty(); + mSnapshotCtrl->resetDirty(); + mLocationChanged = false; +} + +BOOL LLPanelProfilePick::isDirty() const +{ + if (mNewPick + || LLPanel::isDirty() + || mLocationChanged + || mSnapshotCtrl->isDirty() + || mPickName->isDirty() + || mPickDescription->isDirty()) + { + return TRUE; + } + return FALSE; +} + +void LLPanelProfilePick::onClickSetLocation() +{ + // Save location for later use. + setPosGlobal(gAgent.getPositionGlobal()); + + std::string parcel_name, region_name; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + mParcelId = parcel->getID(); + parcel_name = parcel->getName(); + } + + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); + + mLocationChanged = true; + enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onClickSave() +{ + sendUpdate(); + + mLocationChanged = false; +} + +void LLPanelProfilePick::onClickCancel() +{ + LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(getAvatarId(), getPickId()); + mLocationChanged = false; + enableSaveButton(FALSE); +} + +std::string LLPanelProfilePick::getLocationNotice() +{ + static const std::string notice = getString("location_notice"); + return notice; +} + +void LLPanelProfilePick::sendParcelInfoRequest() +{ + if (mParcelId != mRequestedId) + { + if (mRequestedId.notNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedId, this); + } + LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); + + mRequestedId = mParcelId; + } +} + +void LLPanelProfilePick::processParcelInfo(const LLParcelData& parcel_data) +{ + setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, parcel_data.sim_name, getPosGlobal())); + + // We have received parcel info for the requested ID so clear it now. + mRequestedId.setNull(); + + if (mParcelId.notNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); + } +} + +void LLPanelProfilePick::sendUpdate() +{ + LLPickData pick_data; + + // If we don't have a pick id yet, we'll need to generate one, + // otherwise we'll keep overwriting pick_id 00000 in the database. + if (getPickId().isNull()) + { + getPickId().generate(); + } + + pick_data.agent_id = gAgentID; + pick_data.session_id = gAgent.getSessionID(); + pick_data.pick_id = getPickId(); + pick_data.creator_id = gAgentID;; + + //legacy var need to be deleted + pick_data.top_pick = FALSE; + pick_data.parcel_id = mParcelId; + pick_data.name = getPickName(); + pick_data.desc = mPickDescription->getValue().asString(); + pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); + pick_data.pos_global = getPosGlobal(); + pick_data.sort_order = 0; + pick_data.enabled = TRUE; + + LLAvatarPropertiesProcessor::getInstance()->sendPickInfoUpdate(&pick_data); + + if(mNewPick) + { + // Assume a successful create pick operation, make new number of picks + // available immediately. Actual number of picks will be requested in + // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. + LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); + } +} + +// static +std::string LLPanelProfilePick::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global) +{ + std::string location_text(owner_name); + if (!original_name.empty()) + { + if (!location_text.empty()) + { + location_text.append(", "); + } + location_text.append(original_name); + + } + + if (!sim_name.empty()) + { + if (!location_text.empty()) + { + location_text.append(", "); + } + location_text.append(sim_name); + } + + if (!location_text.empty()) + { + location_text.append(" "); + } + + if (!pos_global.isNull()) + { + S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; + S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; + S32 region_z = ll_round((F32)pos_global.mdV[VZ]); + location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); + } + return location_text; +} + +void LLPanelProfilePick::updateTabLabel(const std::string& title) +{ + setLabel(title); + LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); + if (parent) + { + parent->setCurrentTabName(title); + } +} + diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h new file mode 100644 index 0000000000..f84463cc9b --- /dev/null +++ b/indra/newview/llpanelprofilepicks.h @@ -0,0 +1,248 @@ +/** + * @file llpanelprofilepicks.h + * @brief LLPanelProfilePicks and related class definitions + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELPICKS_H +#define LL_LLPANELPICKS_H + +#include "llpanel.h" +#include "lluuid.h" +#include "llavatarpropertiesprocessor.h" +#include "llpanelavatar.h" +#include "llremoteparcelrequest.h" + +class LLTabContainer; +class LLTextureCtrl; +class LLMediaCtrl; +class LLLineEditor; +class LLTextEditor; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfilePicks + : public LLPanelProfilePropertiesProcessorTab +{ +public: + LLPanelProfilePicks(); + /*virtual*/ ~LLPanelProfilePicks(); + + BOOL postBuild() override; + + void onOpen(const LLSD& key) override; + + void createPick(const LLPickData &data); + void selectPick(const LLUUID& pick_id); + + void processProperties(void* data, EAvatarProcessorType type) override; + void processProperties(const LLAvatarPicks* avatar_picks); + + void resetData() override; + + void updateButtons(); + + /** + * Saves changes. + */ + virtual void apply(); + + /** + * Sends update data request to server. + */ + void updateData() override; + + bool hasUnsavedChanges() override; + void commitUnsavedChanges() override; + + friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +private: + void onClickNewBtn(); + void onClickDelete(); + void callbackDeletePick(const LLSD& notification, const LLSD& response); + + bool canAddNewPick(); + bool canDeletePick(); + + LLTabContainer* mTabContainer; + LLUICtrl* mNoItemsLabel; + LLButton* mNewButton; + LLButton* mDeleteButton; + + LLUUID mPickToSelectOnLoad; + std::list<LLPickData> mSheduledPickCreation; +}; + + +class LLPanelProfilePick + : public LLPanelProfilePropertiesProcessorTab + , public LLRemoteParcelInfoObserver +{ +public: + + // Creates new panel + static LLPanelProfilePick* create(); + + LLPanelProfilePick(); + + /*virtual*/ ~LLPanelProfilePick(); + + BOOL postBuild() override; + + void setAvatarId(const LLUUID& avatar_id) override; + + void setPickId(const LLUUID& id) { mPickId = id; } + virtual LLUUID& getPickId() { return mPickId; } + + virtual void setPickName(const std::string& name); + const std::string getPickName(); + + void processProperties(void* data, EAvatarProcessorType type) override; + void processProperties(const LLPickData* pick_data); + + /** + * Returns true if any of Pick properties was changed by user. + */ + BOOL isDirty() const override; + + /** + * Saves changes. + */ + virtual void apply(); + + void updateTabLabel(const std::string& title); + + //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing + void processParcelInfo(const LLParcelData& parcel_data) override; + void setParcelID(const LLUUID& parcel_id) override { mParcelId = parcel_id; } + void setErrorStatus(S32 status, const std::string& reason) override {}; + +protected: + + /** + * Sends remote parcel info request to resolve parcel name from its ID. + */ + void sendParcelInfoRequest(); + + /** + * "Location text" is actually the owner name, the original + * name that owner gave the parcel, and the location. + */ + static std::string createLocationText( + const std::string& owner_name, + const std::string& original_name, + const std::string& sim_name, + const LLVector3d& pos_global); + + /** + * Sets snapshot id. + * + * Will mark snapshot control as valid if id is not null. + * Will mark snapshot control as invalid if id is null. If null id is a valid value, + * you have to manually mark snapshot is valid. + */ + virtual void setSnapshotId(const LLUUID& id); + virtual void setPickDesc(const std::string& desc); + virtual void setPickLocation(const std::string& location); + + virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + virtual LLVector3d& getPosGlobal() { return mPosGlobal; } + + /** + * Callback for "Map" button, opens Map + */ + void onClickMap(); + + /** + * Callback for "Teleport" button, teleports user to Pick location. + */ + void onClickTeleport(); + + /** + * Enables/disables "Save" button + */ + void enableSaveButton(BOOL enable); + + /** + * Called when snapshot image changes. + */ + void onSnapshotChanged(); + + /** + * Callback for Pick snapshot, name and description changed event. + */ + void onPickChanged(LLUICtrl* ctrl); + + /** + * Resets panel and all cantrols to unedited state + */ + void resetDirty() override; + + /** + * Callback for "Set Location" button click + */ + void onClickSetLocation(); + + /** + * Callback for "Save" and "Create" button click + */ + void onClickSave(); + + /** + * Callback for "Save" button click + */ + void onClickCancel(); + + std::string getLocationNotice(); + + /** + * Sends Pick properties to server. + */ + void sendUpdate(); + +protected: + + LLTextureCtrl* mSnapshotCtrl; + LLLineEditor* mPickName; + LLTextEditor* mPickDescription; + LLButton* mSetCurrentLocationButton; + LLButton* mSaveButton; + LLButton* mCreateButton; + LLButton* mCancelButton; + + LLVector3d mPosGlobal; + LLUUID mParcelId; + LLUUID mPickId; + LLUUID mRequestedId; + + bool mLocationChanged; + bool mNewPick; + bool mIsEditing; + + void onDescriptionFocusReceived(); +}; + +#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 89c558e4f8..39f4c7485b 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -51,6 +51,7 @@ #include "llfocusmgr.h" #include "llmanipscale.h" #include "llinventorymodel.h" +#include "llmenubutton.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -168,6 +169,9 @@ BOOL LLPanelVolume::postBuild() mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution)); } + mMenuClipboardFeatures = getChild<LLMenuButton>("clipboard_features_params_btn"); + mMenuClipboardLight = getChild<LLMenuButton>("clipboard_light_params_btn"); + std::map<std::string, std::string> material_name_map; material_name_map["Stone"]= LLTrans::getString("Stone"); material_name_map["Metal"]= LLTrans::getString("Metal"); @@ -208,6 +212,8 @@ LLPanelVolume::LLPanelVolume() { setMouseOpaque(FALSE); + mCommitCallbackRegistrar.add("PanelVolume.menuDoToSelected", boost::bind(&LLPanelVolume::menuDoToSelected, this, _2)); + mEnableCallbackRegistrar.add("PanelVolume.menuEnable", boost::bind(&LLPanelVolume::menuEnableItem, this, _2)); } @@ -409,7 +415,6 @@ void LLPanelVolume::getState( ) gAgentAvatarp->updateMeshVisibility(); } } - // Flexible properties BOOL is_flexible = volobjp && volobjp->isFlexible(); @@ -564,6 +569,9 @@ void LLPanelVolume::getState( ) mObject = objectp; mRootObject = root_objectp; + + mMenuClipboardFeatures->setEnabled(editable && single_volume && volobjp); // Note: physics doesn't need to be limited by single volume + mMenuClipboardLight->setEnabled(editable && single_volume && volobjp); } // static @@ -587,13 +595,6 @@ void LLPanelVolume::refresh() mRootObject = NULL; } - BOOL visible = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE; - - getChildView("Light FOV")->setVisible( visible); - getChildView("Light Focus")->setVisible( visible); - getChildView("Light Ambiance")->setVisible( visible); - getChildView("light texture control")->setVisible( visible); - bool enable_mesh = false; LLSD sim_features; @@ -831,6 +832,290 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data) } } +void LLPanelVolume::onCopyFeatures() +{ + LLViewerObject* objectp = mObject; + if (!objectp) + { + return; + } + + LLSD clipboard; + + LLVOVolume *volobjp = NULL; + if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + { + volobjp = (LLVOVolume *)objectp; + } + + // Flexi Prim + if (volobjp && volobjp->isFlexible()) + { + LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + if (attributes) + { + clipboard["flex"]["lod"] = attributes->getSimulateLOD(); + clipboard["flex"]["gav"] = attributes->getGravity(); + clipboard["flex"]["ten"] = attributes->getTension(); + clipboard["flex"]["fri"] = attributes->getAirFriction(); + clipboard["flex"]["sen"] = attributes->getWindSensitivity(); + LLVector3 force = attributes->getUserForce(); + clipboard["flex"]["forx"] = force.mV[0]; + clipboard["flex"]["fory"] = force.mV[1]; + clipboard["flex"]["forz"] = force.mV[2]; + } + } + + // Physics + { + clipboard["physics"]["shape"] = objectp->getPhysicsShapeType(); + clipboard["physics"]["gravity"] = objectp->getPhysicsGravity(); + clipboard["physics"]["friction"] = objectp->getPhysicsFriction(); + clipboard["physics"]["density"] = objectp->getPhysicsDensity(); + clipboard["physics"]["restitution"] = objectp->getPhysicsRestitution(); + + U8 material_code = 0; + struct f : public LLSelectedTEGetFunctor<U8> + { + U8 get(LLViewerObject* object, S32 te) + { + return object->getMaterial(); + } + } func; + bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, material_code); + // This should always be true since material should be per object. + if (material_same) + { + clipboard["physics"]["material"] = material_code; + } + } + + mClipboardParams["features"] = clipboard; +} + +void LLPanelVolume::onPasteFeatures() +{ + LLViewerObject* objectp = mObject; + if (!objectp && mClipboardParams.has("features")) + { + return; + } + + LLSD &clipboard = mClipboardParams["features"]; + + LLVOVolume *volobjp = NULL; + if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + { + volobjp = (LLVOVolume *)objectp; + } + + // Physics + bool is_root = objectp->isRoot(); + + // Not sure if phantom should go under physics, but doesn't fit elsewhere + BOOL is_phantom = clipboard["is_phantom"].asBoolean() && is_root; + LLSelectMgr::getInstance()->selectionUpdatePhantom(is_phantom); + + BOOL is_physical = clipboard["is_physical"].asBoolean() && is_root; + LLSelectMgr::getInstance()->selectionUpdatePhysics(is_physical); + + if (clipboard.has("physics")) + { + objectp->setPhysicsShapeType((U8)clipboard["physics"]["shape"].asInteger()); + U8 cur_material = objectp->getMaterial(); + U8 material = (U8)clipboard["physics"]["material"].asInteger() | (cur_material & ~LL_MCODE_MASK); + + objectp->setMaterial(material); + objectp->sendMaterialUpdate(); + objectp->setPhysicsGravity(clipboard["physics"]["gravity"].asReal()); + objectp->setPhysicsFriction(clipboard["physics"]["friction"].asReal()); + objectp->setPhysicsDensity(clipboard["physics"]["density"].asReal()); + objectp->setPhysicsRestitution(clipboard["physics"]["restitution"].asReal()); + objectp->updateFlags(TRUE); + } + + // Flexible + bool is_flexible = clipboard.has("flex"); + if (is_flexible && volobjp->canBeFlexible()) + { + LLVOVolume *volobjp = (LLVOVolume *)objectp; + BOOL update_shape = FALSE; + + // do before setParameterEntry or it will think that it is already flexi + update_shape = volobjp->setIsFlexible(is_flexible); + + if (objectp->getClickAction() == CLICK_ACTION_SIT) + { + objectp->setClickAction(CLICK_ACTION_NONE); + } + + LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + if (attributes) + { + LLFlexibleObjectData new_attributes; + new_attributes = *attributes; + new_attributes.setSimulateLOD(clipboard["flex"]["lod"].asInteger()); + new_attributes.setGravity(clipboard["flex"]["gav"].asReal()); + new_attributes.setTension(clipboard["flex"]["ten"].asReal()); + new_attributes.setAirFriction(clipboard["flex"]["fri"].asReal()); + new_attributes.setWindSensitivity(clipboard["flex"]["sen"].asReal()); + F32 fx = (F32)clipboard["flex"]["forx"].asReal(); + F32 fy = (F32)clipboard["flex"]["fory"].asReal(); + F32 fz = (F32)clipboard["flex"]["forz"].asReal(); + LLVector3 force(fx, fy, fz); + new_attributes.setUserForce(force); + objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); + } + + if (update_shape) + { + mObject->sendShapeUpdate(); + LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); + } + } + else + { + LLVOVolume *volobjp = (LLVOVolume *)objectp; + if (volobjp->setIsFlexible(false)) + { + mObject->sendShapeUpdate(); + LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); + } + } +} + +void LLPanelVolume::onCopyLight() +{ + LLViewerObject* objectp = mObject; + if (!objectp) + { + return; + } + + LLSD clipboard; + + LLVOVolume *volobjp = NULL; + if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + { + volobjp = (LLVOVolume *)objectp; + } + + // Light Source + if (volobjp && volobjp->getIsLight()) + { + clipboard["light"]["intensity"] = volobjp->getLightIntensity(); + clipboard["light"]["radius"] = volobjp->getLightRadius(); + clipboard["light"]["falloff"] = volobjp->getLightFalloff(); + LLColor3 color = volobjp->getLightSRGBColor(); + clipboard["light"]["r"] = color.mV[0]; + clipboard["light"]["g"] = color.mV[1]; + clipboard["light"]["b"] = color.mV[2]; + + // Spotlight + if (volobjp->isLightSpotlight()) + { + LLUUID id = volobjp->getLightTextureID(); + if (id.notNull() && get_can_copy_texture(id)) + { + clipboard["spot"]["id"] = id; + LLVector3 spot_params = volobjp->getSpotLightParams(); + clipboard["spot"]["fov"] = spot_params.mV[0]; + clipboard["spot"]["focus"] = spot_params.mV[1]; + clipboard["spot"]["ambiance"] = spot_params.mV[2]; + } + } + } + + mClipboardParams["light"] = clipboard; +} + +void LLPanelVolume::onPasteLight() +{ + LLViewerObject* objectp = mObject; + if (!objectp && mClipboardParams.has("light")) + { + return; + } + + LLSD &clipboard = mClipboardParams["light"]; + + LLVOVolume *volobjp = NULL; + if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + { + volobjp = (LLVOVolume *)objectp; + } + + // Light Source + if (volobjp) + { + if (clipboard.has("light")) + { + volobjp->setIsLight(TRUE); + volobjp->setLightIntensity((F32)clipboard["light"]["intensity"].asReal()); + volobjp->setLightRadius((F32)clipboard["light"]["radius"].asReal()); + volobjp->setLightFalloff((F32)clipboard["light"]["falloff"].asReal()); + F32 r = (F32)clipboard["light"]["r"].asReal(); + F32 g = (F32)clipboard["light"]["g"].asReal(); + F32 b = (F32)clipboard["light"]["b"].asReal(); + volobjp->setLightSRGBColor(LLColor3(r, g, b)); + } + else + { + volobjp->setIsLight(FALSE); + } + + if (clipboard.has("spot")) + { + volobjp->setLightTextureID(clipboard["spot"]["id"].asUUID()); + LLVector3 spot_params; + spot_params.mV[0] = (F32)clipboard["spot"]["fov"].asReal(); + spot_params.mV[1] = (F32)clipboard["spot"]["focus"].asReal(); + spot_params.mV[2] = (F32)clipboard["spot"]["ambiance"].asReal(); + volobjp->setSpotLightParams(spot_params); + } + } +} + +void LLPanelVolume::menuDoToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste + if (command == "features_paste") + { + onPasteFeatures(); + } + else if (command == "light_paste") + { + onPasteLight(); + } + // copy + else if (command == "features_copy") + { + onCopyFeatures(); + } + else if (command == "light_copy") + { + onCopyLight(); + } +} + +bool LLPanelVolume::menuEnableItem(const LLSD& userdata) +{ + std::string command = userdata.asString(); + + // paste options + if (command == "features_paste") + { + return mClipboardParams.has("features"); + } + else if (command == "light_paste") + { + return mClipboardParams.has("light"); + } + return false; +} + // static void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata ) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 6e49ccb742..d9198f3693 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLTextBox; class LLUICtrl; class LLButton; +class LLMenuButton; class LLViewerObject; class LLComboBox; class LLColorSwatchCtrl; @@ -76,6 +77,13 @@ public: static void setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp); + void onCopyFeatures(); + void onPasteFeatures(); + void onCopyLight(); + void onPasteLight(); + + void menuDoToSelected(const LLSD& userdata); + bool menuEnableItem(const LLSD& userdata); protected: void getState(); @@ -123,6 +131,11 @@ protected: LLSpinCtrl* mSpinPhysicsFriction; LLSpinCtrl* mSpinPhysicsDensity; LLSpinCtrl* mSpinPhysicsRestitution; + + LLMenuButton* mMenuClipboardFeatures; + LLMenuButton* mMenuClipboardLight; + + LLSD mClipboardParams; }; #endif diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 94d20828ec..9b60d1ae2f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -38,154 +38,11 @@ #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif -// See EXT-4301. -/** - * class LLAvalineUpdater - observe the list of voice participants in session and check - * presence of Avaline Callers among them. - * - * LLAvalineUpdater is a LLVoiceClientParticipantObserver. It provides two kinds of validation: - * - whether Avaline caller presence among participants; - * - whether watched Avaline caller still exists in voice channel. - * Both validations have callbacks which will notify subscriber if any of event occur. - * - * @see findAvalineCaller() - * @see checkIfAvalineCallersExist() - */ -class LLAvalineUpdater : public LLVoiceClientParticipantObserver -{ -public: - typedef boost::function<void(const LLUUID& speaker_id)> process_avaline_callback_t; - - LLAvalineUpdater(process_avaline_callback_t found_cb, process_avaline_callback_t removed_cb) - : mAvalineFoundCallback(found_cb) - , mAvalineRemovedCallback(removed_cb) - { - LLVoiceClient::getInstance()->addObserver(this); - } - ~LLAvalineUpdater() - { - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } - } - - /** - * Adds UUID of Avaline caller to watch. - * - * @see checkIfAvalineCallersExist(). - */ - void watchAvalineCaller(const LLUUID& avaline_caller_id) - { - mAvalineCallers.insert(avaline_caller_id); - } - - void onParticipantsChanged() - { - uuid_set_t participant_uuids; - LLVoiceClient::getInstance()->getParticipantList(participant_uuids); - - - // check whether Avaline caller exists among voice participants - // and notify Participant List - findAvalineCaller(participant_uuids); - - // check whether watched Avaline callers still present among voice participant - // and remove if absents. - checkIfAvalineCallersExist(participant_uuids); - } - -private: - typedef std::set<LLUUID> uuid_set_t; - - /** - * Finds Avaline callers among voice participants and calls mAvalineFoundCallback. - * - * When Avatar is in group call with Avaline caller and then ends call Avaline caller stays - * in Group Chat floater (exists in LLSpeakerMgr). If Avatar starts call with that group again - * Avaline caller is added to voice channel AFTER Avatar is connected to group call. - * But Voice Control Panel (VCP) is filled from session LLSpeakerMgr and there is no information - * if a speaker is Avaline caller. - * - * In this case this speaker is created as avatar and will be recreated when it appears in - * Avatar's Voice session. - * - * @see LLParticipantList::onAvalineCallerFound() - */ - void findAvalineCaller(const uuid_set_t& participant_uuids) - { - uuid_set_t::const_iterator it = participant_uuids.begin(), it_end = participant_uuids.end(); - - for(; it != it_end; ++it) - { - const LLUUID& participant_id = *it; - if (!LLVoiceClient::getInstance()->isParticipantAvatar(participant_id)) - { - LL_DEBUGS("Avaline") << "Avaline caller found among voice participants: " << participant_id << LL_ENDL; - - if (mAvalineFoundCallback) - { - mAvalineFoundCallback(participant_id); - } - } - } - } - - /** - * Finds Avaline callers which are not anymore among voice participants and calls mAvalineRemovedCallback. - * - * The problem is when Avaline caller ends a call it is removed from Voice Client session but - * still exists in LLSpeakerMgr. Server does not send such information. - * This method implements a HUCK to notify subscribers that watched Avaline callers by class - * are not anymore in the call. - * - * @see LLParticipantList::onAvalineCallerRemoved() - */ - void checkIfAvalineCallersExist(const uuid_set_t& participant_uuids) - { - uuid_set_t::iterator it = mAvalineCallers.begin(); - uuid_set_t::const_iterator participants_it_end = participant_uuids.end(); - - while (it != mAvalineCallers.end()) - { - const LLUUID participant_id = *it; - LL_DEBUGS("Avaline") << "Check avaline caller: " << participant_id << LL_ENDL; - bool not_found = participant_uuids.find(participant_id) == participants_it_end; - if (not_found) - { - LL_DEBUGS("Avaline") << "Watched Avaline caller is not found among voice participants: " << participant_id << LL_ENDL; - - // notify Participant List - if (mAvalineRemovedCallback) - { - mAvalineRemovedCallback(participant_id); - } - - // remove from the watch list - mAvalineCallers.erase(it++); - } - else - { - ++it; - } - } - } - - process_avaline_callback_t mAvalineFoundCallback; - process_avaline_callback_t mAvalineRemovedCallback; - - uuid_set_t mAvalineCallers; -}; - LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewModelInterface& root_view_model) : LLConversationItemSession(data_source->getSessionID(), root_view_model), mSpeakerMgr(data_source), mValidateSpeakerCallback(NULL) { - - mAvalineUpdater = new LLAvalineUpdater(boost::bind(&LLParticipantList::onAvalineCallerFound, this, _1), - boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1)); - mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); @@ -243,32 +100,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLFolderViewMode LLParticipantList::~LLParticipantList() { - delete mAvalineUpdater; -} - -/* - Seems this method is not necessary after onAvalineCallerRemoved was implemented; - - It does nothing because list item is always created with correct class type for Avaline caller. - For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client - session. - This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call. - - Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself. - Asked in EXT-4301. -*/ -void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) -{ - removeParticipant(participant_id); - // re-add avaline caller with a correct class instance. - addAvatarIDExceptAgent(participant_id); -} - -void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id) -{ - LL_DEBUGS("Avaline") << "Removing avaline caller from the list: " << participant_id << LL_ENDL; - - mSpeakerMgr->removeAvalineSpeaker(participant_id); } void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) @@ -386,7 +217,6 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) std::string display_name = LLVoiceClient::getInstance()->getDisplayName(avatar_id); // Create a participant view model instance participant = new LLConversationItemParticipant(display_name.empty() ? LLTrans::getString("AvatarNameWaiting") : display_name, avatar_id, mRootViewModel); - mAvalineUpdater->watchAvalineCaller(avatar_id); } // *TODO : Need to update the online/offline status of the participant diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 3a3ae76604..14c0a63692 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -32,7 +32,6 @@ class LLSpeakerMgr; class LLUICtrl; -class LLAvalineUpdater; class LLParticipantList : public LLConversationItemSession { @@ -133,8 +132,6 @@ protected: }; private: - void onAvalineCallerFound(const LLUUID& participant_id); - void onAvalineCallerRemoved(const LLUUID& participant_id); /** * Adjusts passed participant to work properly. @@ -156,7 +153,6 @@ private: LLPointer<SpeakerMuteListener> mSpeakerMuteListener; validate_speaker_callback_t mValidateSpeakerCallback; - LLAvalineUpdater* mAvalineUpdater; }; #endif // LL_PARTICIPANTLIST_H diff --git a/indra/newview/llpatchvertexarray.cpp b/indra/newview/llpatchvertexarray.cpp index 6e3e375488..a7011dfad5 100644 --- a/indra/newview/llpatchvertexarray.cpp +++ b/indra/newview/llpatchvertexarray.cpp @@ -69,11 +69,9 @@ void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_p // (The -1 is there because an LLSurface has a buffer of 1 on // its East and North edges). U32 power_of_two = 1; - U32 surface_order = 0; while (power_of_two < (surface_width-1)) { power_of_two *= 2; - surface_order += 1; } if (power_of_two == (surface_width-1)) diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 9bc77393dc..9bf771db8a 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -163,12 +163,16 @@ void LLPersistentNotificationStorage::loadNotifications() LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL; } -void LLPersistentNotificationStorage::initialize() +void LLPersistentNotificationStorage::reset() { - std::string file_name = "open_notifications_" + LLGridManager::getInstance()->getGrid() + ".xml"; - setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, file_name)); - setOldFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")); + std::string file_name = "open_notifications_" + LLGridManager::getInstance()->getGrid() + ".xml"; + setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, file_name)); + setOldFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")); +} +void LLPersistentNotificationStorage::initialize() +{ + reset(); LLNotifications::instance().getChannel("Persistent")-> connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); } diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h index 1fb4487286..335d85aaf6 100644 --- a/indra/newview/llpersistentnotificationstorage.h +++ b/indra/newview/llpersistentnotificationstorage.h @@ -52,6 +52,7 @@ public: void saveNotifications(); void loadNotifications(); + void reset(); protected: diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp index 5bfe5c9941..9603ee6329 100644 --- a/indra/newview/llphysicsshapebuilderutil.cpp +++ b/indra/newview/llphysicsshapebuilderutil.cpp @@ -29,7 +29,7 @@ #include "llphysicsshapebuilderutil.h" /* static */ -void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut ) +void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut) { const LLProfileParams& profile_params = volume_params.getProfileParams(); const LLPathParams& path_params = volume_params.getPathParams(); @@ -191,6 +191,7 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara if ( volume_params.shouldForceConvex() ) { + // Server distinguishes between convex of a prim vs isSculpt, but we don't care. specOut.mType = PhysicsShapeSpecification::USER_CONVEX; } // Make a simpler convex shape if we can. @@ -199,6 +200,16 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara { specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; } + else if (volume_params.isMeshSculpt() && + // Check overall dimensions, not individual triangles. + (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || + scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || + scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE + ) ) + { + // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't. + specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; + } else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy) { specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT; diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h index bd5b7d799c..b3b100296f 100644 --- a/indra/newview/llphysicsshapebuilderutil.h +++ b/indra/newview/llphysicsshapebuilderutil.h @@ -47,6 +47,7 @@ const F32 SHAPE_BUILDER_ENTRY_SNAP_SCALE_BIN_SIZE = 0.15f; const F32 SHAPE_BUILDER_ENTRY_SNAP_PARAMETER_BIN_SIZE = 0.010f; const F32 SHAPE_BUILDER_CONVEXIFICATION_SIZE = 2.f * COLLISION_TOLERANCE; const F32 SHAPE_BUILDER_MIN_GEOMETRY_SIZE = 0.5f * COLLISION_TOLERANCE; +const F32 SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE = 0.5f; class LLPhysicsVolumeParams : public LLVolumeParams { diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index c267c3c699..30d0a22ef0 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -332,7 +332,6 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n else { ECameraPreset new_camera_preset = (ECameraPreset)gSavedSettings.getU32("CameraPresetType"); - bool new_camera_offsets = false; if (IS_CAMERA) { if (isDefaultCameraPreset(name)) @@ -354,7 +353,6 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n { new_camera_preset = CAMERA_PRESET_CUSTOM; } - new_camera_offsets = (!isDefaultCameraPreset(name) || (ECameraPreset)gSavedSettings.getU32("CameraPresetType") != new_camera_preset); } for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) { diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 230def5362..3fd4f51559 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -866,7 +866,10 @@ bool LLPreviewNotecard::loadNotecardText(const std::string& filename) buffer[nread] = '\0'; fclose(file); - mEditor->setText(LLStringExplicit(buffer)); + std::string text = std::string(buffer); + LLStringUtil::replaceTabsWithSpaces(text, LLTextEditor::spacesPerTab()); + + mEditor->setText(text); delete[] buffer; return true; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a32dc8beda..d677a996c1 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -601,7 +601,10 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename) buffer[nread] = '\0'; fclose(file); - mEditor->setText(LLStringExplicit(buffer)); + std::string text = std::string(buffer); + LLStringUtil::replaceTabsWithSpaces(text, LLTextEditor::spacesPerTab()); + + mEditor->setText(text); delete[] buffer; return true; diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index cd7b93aba7..10177c8023 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -367,7 +367,10 @@ void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent) // add space for dimensions and aspect ratio S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD; - + if (getChild<LLLayoutPanel>("buttons_panel")->getVisible()) + { + info_height += getChild<LLLayoutPanel>("buttons_panel")->getRect().getHeight(); + } LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0); client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ; @@ -412,6 +415,16 @@ void LLPreviewTexture::openToSave() mPreviewToSave = TRUE; } +void LLPreviewTexture::hideCtrlButtons() +{ + getChildView("desc txt")->setVisible(false); + getChildView("desc")->setVisible(false); + getChild<LLLayoutStack>("preview_stack")->collapsePanel(getChild<LLLayoutPanel>("buttons_panel"), true); + getChild<LLLayoutPanel>("buttons_panel")->setVisible(false); + getChild<LLComboBox>("combo_aspect_ratio")->setCurrentByIndex(0); //unconstrained + reshape(getRect().getWidth(), getRect().getHeight()); +} + // static void LLPreviewTexture::onFileLoadedForSave(BOOL success, LLViewerFetchedTexture *src_vi, diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 9b6a843875..16db51332e 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -67,6 +67,8 @@ public: static void onSaveAsBtn(void* data); + void hideCtrlButtons(); + /*virtual*/ void setObjectID(const LLUUID& object_id); protected: void init(); diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp index 83b0c4f1bf..0faf6bf889 100644 --- a/indra/newview/llrecentpeople.cpp +++ b/indra/newview/llrecentpeople.cpp @@ -42,14 +42,6 @@ bool LLRecentPeople::add(const LLUUID& id, const LLSD& userdata) if (is_not_group_id) { - // For each avaline call the id of caller is different even if - // the phone number is the same. - // To avoid duplication of avaline list items in the recent list - // of panel People, deleting id's with similar phone number. - const LLUUID& caller_id = getIDByPhoneNumber(userdata); - if (caller_id.notNull()) - mPeople.erase(caller_id); - //[] instead of insert to replace existing id->llsd["date"] with new date value mPeople[id] = userdata; mChangedSignal(); @@ -90,35 +82,6 @@ const LLSD& LLRecentPeople::getData(const LLUUID& id) const return no_data; } -bool LLRecentPeople::isAvalineCaller(const LLUUID& id) const -{ - recent_people_t::const_iterator it = mPeople.find(id); - - if (it != mPeople.end()) - { - const LLSD& user = it->second; - return user["avaline_call"].asBoolean(); - } - - return false; -} - -const LLUUID& LLRecentPeople::getIDByPhoneNumber(const LLSD& userdata) -{ - if (!userdata["avaline_call"].asBoolean()) - return LLUUID::null; - - for (recent_people_t::const_iterator it = mPeople.begin(); it != mPeople.end(); ++it) - { - const LLSD& user_info = it->second; - - if (user_info["call_number"].asString() == userdata["call_number"].asString()) - return it->first; - } - - return LLUUID::null; -} - // virtual bool LLRecentPeople::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index 18b669ff4f..1b322f2c0a 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -62,9 +62,7 @@ public: * @param id avatar to add. * * @param userdata additional information about last interaction party. - * For example when last interaction party is not an avatar - * but an avaline caller, additional info (such as phone - * number, session id and etc.) should be added. + * For example session id can be added. * * @return false if the avatar is in the list already, true otherwise */ @@ -97,13 +95,6 @@ public: const LLSD& getData(const LLUUID& id) const; /** - * Checks whether specific participant is an avaline caller - * - * @param id identifier of specific participant - */ - bool isAvalineCaller(const LLUUID& id) const; - - /** * Set callback to be called when the list changed. * * Multiple callbacks can be set. @@ -122,8 +113,6 @@ public: private: - const LLUUID& getIDByPhoneNumber(const LLSD& userdata); - typedef std::map<LLUUID, LLSD> recent_people_t; recent_people_t mPeople; signal_t mChangedSignal; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 055ccd5818..f4ace52faa 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -213,7 +213,12 @@ void LLRemoteParcelInfoProcessor::regionParcelInfoCoro(std::string url, if (!status) { - observer->setErrorStatus(status.getStatus(), status.getMessage()); + std::string message = status.getMessage(); + if (message.empty()) + { + message = status.toString(); + } + observer->setErrorStatus(status.getStatus(), message); } else { diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp index f7aa63e34d..e250f9bc7a 100644 --- a/indra/newview/llsceneview.cpp +++ b/indra/newview/llsceneview.cpp @@ -266,14 +266,11 @@ void LLSceneView::draw() U32 count = triangles[idx].size(); - U32 total = 0; - gGL.begin(LLRender::LINE_STRIP); //plot triangles for (U32 i = 0; i < count; ++i) { U32 tri_count = triangles[idx][i]; - total += tri_count; F32 y = (F32) (tri_count-tri_domain[0])/triangle_range*tri_rect.getHeight()+tri_rect.mBottom; F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft; @@ -290,15 +287,8 @@ void LLSceneView::draw() gGL.end(); gGL.flush(); - U32 total_visible = 0; count = visible_triangles[idx].size(); - for (U32 i = 0; i < count; ++i) - { - U32 tri_count = visible_triangles[idx][i]; - total_visible += tri_count; - } - std::string label = llformat("%s Object Triangle Counts (Ktris) -- Visible: %.2f/%.2f (%.2f KB Visible)", category[idx], total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f, total_visible_bytes[idx]/1024.f); diff --git a/indra/newview/llsearchableui.h b/indra/newview/llsearchableui.h index e033cae3ab..31f11eb8ef 100644 --- a/indra/newview/llsearchableui.h +++ b/indra/newview/llsearchableui.h @@ -41,9 +41,9 @@ namespace ll struct PanelData; struct TabContainerData; - typedef boost::shared_ptr< SearchableItem > SearchableItemPtr; - typedef boost::shared_ptr< PanelData > PanelDataPtr; - typedef boost::shared_ptr< TabContainerData > TabContainerDataPtr; + typedef std::shared_ptr< SearchableItem > SearchableItemPtr; + typedef std::shared_ptr< PanelData > PanelDataPtr; + typedef std::shared_ptr< TabContainerData > TabContainerDataPtr; typedef std::vector< TabContainerData > tTabContainerDataList; typedef std::vector< SearchableItemPtr > tSearchableItemList; @@ -55,7 +55,7 @@ namespace ll LLView const *mView; ll::ui::SearchableControl const *mCtrl; - std::vector< boost::shared_ptr< SearchableItem > > mChildren; + std::vector< std::shared_ptr< SearchableItem > > mChildren; virtual ~SearchableItem(); @@ -68,8 +68,8 @@ namespace ll LLPanel const *mPanel; std::string mLabel; - std::vector< boost::shared_ptr< SearchableItem > > mChildren; - std::vector< boost::shared_ptr< PanelData > > mChildPanel; + std::vector< std::shared_ptr< SearchableItem > > mChildren; + std::vector< std::shared_ptr< PanelData > > mChildPanel; virtual ~PanelData(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 82a165cb35..86f7d2bf25 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -310,14 +310,29 @@ void LLSelectMgr::resetObjectOverrides(LLObjectSelectionHandle selected_handle) { struct f : public LLSelectedNodeFunctor { + f(bool a, LLSelectMgr* p) : mAvatarOverridesPersist(a), mManager(p) {} + bool mAvatarOverridesPersist; + LLSelectMgr* mManager; virtual bool apply(LLSelectNode* node) { + if (mAvatarOverridesPersist) + { + LLViewerObject* object = node->getObject(); + if (object && !object->getParent()) + { + LLVOAvatar* avatar = object->asAvatar(); + if (avatar) + { + mManager->mAvatarOverridesMap.emplace(avatar->getID(), AvatarPositionOverride(node->mLastPositionLocal, node->mLastRotation, object)); + } + } + } node->mLastPositionLocal.setVec(0, 0, 0); node->mLastRotation = LLQuaternion(); node->mLastScale.setVec(0, 0, 0); return true; } - } func; + } func(mAllowSelectAvatar, this); selected_handle->applyToNodes(&func); } @@ -351,6 +366,93 @@ void LLSelectMgr::overrideObjectUpdates() getSelection()->applyToNodes(&func); } +void LLSelectMgr::resetAvatarOverrides() +{ + mAvatarOverridesMap.clear(); +} + +void LLSelectMgr::overrideAvatarUpdates() +{ + if (mAvatarOverridesMap.size() == 0) + { + return; + } + + if (!mAllowSelectAvatar || !gFloaterTools) + { + resetAvatarOverrides(); + return; + } + + if (!gFloaterTools->getVisible() && getSelection()->isEmpty()) + { + // when user switches selection, floater is invisible and selection is empty + LLToolset *toolset = LLToolMgr::getInstance()->getCurrentToolset(); + if (toolset->isShowFloaterTools() + && toolset->isToolSelected(0)) // Pie tool + { + resetAvatarOverrides(); + return; + } + } + + // remove selected avatars from this list, + // but set object overrides to make sure avatar won't snap back + struct f : public LLSelectedNodeFunctor + { + f(LLSelectMgr* p) : mManager(p) {} + LLSelectMgr* mManager; + virtual bool apply(LLSelectNode* selectNode) + { + LLViewerObject* object = selectNode->getObject(); + if (object && !object->getParent()) + { + LLVOAvatar* avatar = object->asAvatar(); + if (avatar) + { + uuid_av_override_map_t::iterator iter = mManager->mAvatarOverridesMap.find(avatar->getID()); + if (iter != mManager->mAvatarOverridesMap.end()) + { + if (selectNode->mLastPositionLocal.isExactlyZero()) + { + selectNode->mLastPositionLocal = iter->second.mLastPositionLocal; + } + if (selectNode->mLastRotation == LLQuaternion()) + { + selectNode->mLastRotation = iter->second.mLastRotation; + } + mManager->mAvatarOverridesMap.erase(iter); + } + } + } + return true; + } + } func(this); + getSelection()->applyToNodes(&func); + + // Override avatar positions + uuid_av_override_map_t::iterator it = mAvatarOverridesMap.begin(); + while (it != mAvatarOverridesMap.end()) + { + if (it->second.mObject->isDead()) + { + it = mAvatarOverridesMap.erase(it); + } + else + { + if (!it->second.mLastPositionLocal.isExactlyZero()) + { + it->second.mObject->setPosition(it->second.mLastPositionLocal); + } + if (it->second.mLastRotation != LLQuaternion()) + { + it->second.mObject->setRotation(it->second.mLastRotation); + } + it++; + } + } +} + //----------------------------------------------------------------------------- // Select just the object, not any other group members. //----------------------------------------------------------------------------- @@ -886,7 +988,7 @@ void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to // Can't select yourself if (objectp->mID == gAgentID - && !LLSelectMgr::getInstance()->mAllowSelectAvatar) + && !mAllowSelectAvatar) { continue; } @@ -6281,6 +6383,24 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep) LLSelectNode::~LLSelectNode() { + LLSelectMgr *manager = LLSelectMgr::getInstance(); + if (manager->mAllowSelectAvatar + && (!mLastPositionLocal.isExactlyZero() + || mLastRotation != LLQuaternion())) + { + LLViewerObject* object = getObject(); //isDead() check + if (object && !object->getParent()) + { + LLVOAvatar* avatar = object->asAvatar(); + if (avatar) + { + // Avatar was moved and needs to stay that way + manager->mAvatarOverridesMap.emplace(avatar->getID(), LLSelectMgr::AvatarPositionOverride(mLastPositionLocal, mLastRotation, object)); + } + } + } + + delete mPermissions; mPermissions = NULL; } @@ -6788,6 +6908,10 @@ void LLSelectMgr::updateSelectionCenter() const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection // center (tractor beam) + // override any avatar updates received + // Works only if avatar was repositioned + // and edit floater is visible + overrideAvatarUpdates(); //override any object updates received //for selected objects overrideObjectUpdates(); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index ce0316e610..199141fc32 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -467,6 +467,30 @@ public: void resetObjectOverrides(LLObjectSelectionHandle selected_handle); void overrideObjectUpdates(); + void resetAvatarOverrides(); + void overrideAvatarUpdates(); + + struct AvatarPositionOverride + { + AvatarPositionOverride(); + AvatarPositionOverride(LLVector3 &vec, LLQuaternion &quat, LLViewerObject *obj) : + mLastPositionLocal(vec), + mLastRotation(quat), + mObject(obj) + { + } + LLVector3 mLastPositionLocal; + LLQuaternion mLastRotation; + LLPointer<LLViewerObject> mObject; + }; + + // Avatar overrides should persist even after selection + // was removed as long as edit floater is up + typedef std::map<LLUUID, AvatarPositionOverride> uuid_av_override_map_t; + uuid_av_override_map_t mAvatarOverridesMap; +public: + + // Returns the previous value of mForceSelection BOOL setForceSelection(BOOL force); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 0d53950889..42cd1133a2 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1567,6 +1567,62 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) } } +// return false if drawable is rigged and: +// - a linked rigged drawable has a different spatial group +// - a linked rigged drawable face has the wrong draw order index +bool check_rigged_group(LLDrawable* drawable) +{ + if (drawable->isState(LLDrawable::RIGGED)) + { + LLSpatialGroup* group = drawable->getSpatialGroup(); + LLDrawable* root = drawable->getRoot(); + + if (root->isState(LLDrawable::RIGGED) && root->getSpatialGroup() != group) + { + llassert(false); + return false; + } + + S32 last_draw_index = -1; + if (root->isState(LLDrawable::RIGGED)) + { + for (auto& face : root->getFaces()) + { + if ((S32) face->getDrawOrderIndex() <= last_draw_index) + { + llassert(false); + return false; + } + last_draw_index = face->getDrawOrderIndex(); + } + } + + for (auto& child : root->getVObj()->getChildren()) + { + if (child->mDrawable->isState(LLDrawable::RIGGED)) + { + for (auto& face : child->mDrawable->getFaces()) + { + if ((S32) face->getDrawOrderIndex() <= last_draw_index) + { + llassert(false); + return false; + } + last_draw_index = face->getDrawOrderIndex(); + } + } + + if (child->mDrawable->getSpatialGroup() != group) + { + llassert(false); + return false; + } + } + } + + return true; +} + void renderOctree(LLSpatialGroup* group) { //render solid object bounding box, color @@ -1611,6 +1667,9 @@ void renderOctree(LLSpatialGroup* group) { continue; } + + llassert(check_rigged_group(drawable)); + if (!group->getSpatialPartition()->isBridge()) { gGL.pushMatrix(); @@ -3028,7 +3087,7 @@ public: } - void visit(const LLOctreeNode<LLVolumeTriangle>* branch) + void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch) { LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); @@ -3070,7 +3129,7 @@ public: } gGL.begin(LLRender::TRIANGLES); - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) { @@ -3164,14 +3223,14 @@ void renderRaycast(LLDrawable* drawablep) { F32 t = 1.f; - if (!face.mOctree) + if (!face.getOctree()) { ((LLVolumeFace*) &face)->createOctree(); } LLRenderOctreeRaycast render(start, dir, &t); - render.traverse(face.mOctree); + render.traverse(face.getOctree()); } gGL.popMatrix(); @@ -3787,7 +3846,7 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v) } LL_ALIGN_PREFIX(16) -class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry> +class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> { public: LL_ALIGN_16(LLVector4a mStart); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index abb936c3e5..ea671a130e 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -534,7 +534,7 @@ void LLSpeakerMgr::updateSpeakerList() } else if (mSpeakers.size() == 0) { - // For all other session type (ad-hoc, P2P, avaline), we use the initial participants targets list + // For all other session type (ad-hoc, P2P), we use the initial participants targets list for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it) { // Add buddies if they are on line, add any other avatar. diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index d1dbf72fe9..ed795b5155 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -245,14 +245,6 @@ public: bool isSpeakerToBeRemoved(const LLUUID& speaker_id); /** - * Removes avaline speaker. - * - * This is a HACK due to server does not send information that Avaline caller ends call. - * It can be removed when server is updated. See EXT-4301 for details - */ - bool removeAvalineSpeaker(const LLUUID& speaker_id) { return removeSpeaker(speaker_id); } - - /** * Initializes mVoiceModerated depend on LLSpeaker::mModeratorMutedVoice of agent's participant. * * Is used only to implement workaround to initialize mVoiceModerated on first join to group chat. See EXT-6937 diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0829b1a213..054e9530d4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -97,6 +97,7 @@ #include "llfloateravatarpicker.h" #include "llcallbacklist.h" #include "llcallingcard.h" +#include "llclassifiedinfo.h" #include "llconsole.h" #include "llcontainerview.h" #include "llconversationlog.h" @@ -124,8 +125,6 @@ #include "llpanellogin.h" #include "llmutelist.h" #include "llavatarpropertiesprocessor.h" -#include "llpanelclassified.h" -#include "llpanelpick.h" #include "llpanelgrouplandmoney.h" #include "llpanelgroupnotices.h" #include "llparcel.h" @@ -194,6 +193,7 @@ #include "llavatariconctrl.h" #include "llvoicechannel.h" #include "llpathfindingmanager.h" +#include "llremoteparcelrequest.h" #include "lllogin.h" #include "llevents.h" @@ -255,6 +255,7 @@ static bool mLoginStatePastUI = false; static bool mBenefitsSuccessfullyInit = false; const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds +const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; // Give region 3 chances std::unique_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); std::unique_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); @@ -661,7 +662,7 @@ bool idle_startup() #else void* window_handle = NULL; #endif - bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle, LLAppViewer::instance()->getSecondLifeTitle()); + bool init = gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle()); if(init) { gAudiop->setMuted(TRUE); @@ -927,6 +928,12 @@ bool idle_startup() LLPersistentNotificationStorage::initParamSingleton(); LLDoNotDisturbNotificationStorage::initParamSingleton(); } + else + { + // reinitialize paths in case user switched grids or accounts + LLPersistentNotificationStorage::getInstance()->reset(); + LLDoNotDisturbNotificationStorage::getInstance()->reset(); + } // Set PerAccountSettingsFile to the default value. std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")); @@ -1388,10 +1395,21 @@ bool idle_startup() { LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); } + else if (regionp->capabilitiesError()) + { + // Try to connect despite capabilities' error state + LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); + } else { U32 num_retries = regionp->getNumSeedCapRetries(); - if (num_retries > 0) + if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN) + { + // Region will keep trying to get capabilities, + // but for now continue as if caps were granted + LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); + } + else if (num_retries > 0) { LLStringUtil::format_map_t args; args["[NUMBER]"] = llformat("%d", num_retries + 1); @@ -2385,6 +2403,11 @@ void login_callback(S32 option, void *userdata) void show_release_notes_if_required() { static bool release_notes_shown = false; + // We happen to know that instantiating LLVersionInfo implicitly + // instantiates the LLEventMailDrop named "relnotes", which we (might) use + // below. If viewer release notes stop working, might be because that + // LLEventMailDrop got moved out of LLVersionInfo and hasn't yet been + // instantiated. if (!release_notes_shown && (LLVersionInfo::instance().getChannelAndVersion() != gLastRunVersion) && LLVersionInfo::instance().getViewerMaturity() != LLVersionInfo::TEST_VIEWER // don't show Release Notes for the test builds && gSavedSettings.getBOOL("UpdaterShowReleaseNotes") @@ -2652,7 +2675,6 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); -// msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply); msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); msg->setHandlerFunc("ScriptDialog", process_script_dialog); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d4fc6f3de2..9403e73b87 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1042,7 +1042,8 @@ void LLTextureCache::setReadOnly(BOOL read_only) mReadOnly = read_only ; } -//called in the main thread. +// Called in the main thread. +// Returns the unused amount of max_size if any S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache_mismatch) { llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 1c4a56b549..0ce82a1297 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -48,6 +48,7 @@ #include "llui.h" #include "llviewerinventory.h" #include "llpermissions.h" +#include "llpreviewtexture.h" #include "llsaleinfo.h" #include "llassetstorage.h" #include "lltextbox.h" @@ -80,6 +81,67 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1; //static const char WHITE_IMAGE_NAME[] = "Blank Texture"; //static const char NO_IMAGE_NAME[] = "None"; + + +//static +bool get_is_predefined_texture(LLUUID asset_id) +{ + if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) + || asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) + || asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) + || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) + { + return true; + } + return false; +} + +LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(asset_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + LLUUID res; + if (items.size()) + { + for (S32 i = 0; i < items.size(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp) + { + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID())) + { + bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()); + if (allow_trans != no_trans_perm) + { + return itemp->getUUID(); + } + res = itemp->getUUID(); + } + } + } + } + return res; +} + +bool get_can_copy_texture(LLUUID asset_id) +{ + // User is allowed to copy a texture if: + // library asset or default texture, + // or copy perm asset exists in user's inventory + + return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull(); +} + LLFloaterTexturePicker::LLFloaterTexturePicker( LLView* owner, LLUUID image_asset_id, @@ -1154,6 +1216,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) mNeedsRawImageData( FALSE ), mValid( TRUE ), mShowLoadingPlaceholder( TRUE ), + mOpenTexPreview(false), mImageAssetID(p.image_id), mDefaultImageAssetID(p.default_image_id), mDefaultImageName(p.default_image_name), @@ -1410,12 +1473,31 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) if (!handled && mBorder->parentPointInView(x, y)) { - showPicker(FALSE); - //grab textures first... - LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); - //...then start full inventory fetch. - LLInventoryModelBackgroundFetch::instance().start(); - handled = TRUE; + if (!mOpenTexPreview) + { + showPicker(FALSE); + //grab textures first... + LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); + //...then start full inventory fetch. + LLInventoryModelBackgroundFetch::instance().start(); + handled = TRUE; + } + else + { + if (getImageAssetID().notNull()) + { + LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", getValue()); + if (preview_texture && !preview_texture->isDependent()) + { + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + { + root_floater->addDependentFloater(preview_texture); + preview_texture->hideCtrlButtons(); + } + } + } + } } return handled; diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 92f6f89af6..fbb38c4464 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -52,6 +52,16 @@ class LLViewerFetchedTexture; typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; typedef boost::function<void (LLInventoryItem*)> texture_selected_callback; +// Helper functions for UI that work with picker +bool get_is_predefined_texture(LLUUID asset_id); + +// texture picker works by asset ids since objects normaly do +// not retain inventory ids as result these functions are looking +// for textures in inventory by asset ids +// This search can be performance unfriendly and doesn't warranty +// that the texture is original source of asset +LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); +bool get_can_copy_texture(LLUUID image_id); ////////////////////////////////////////////////////////////////////////////////////////// // LLTextureCtrl @@ -159,6 +169,8 @@ public: void setBlankImageAssetID( const LLUUID& id ) { mBlankImageAssetID = id; } const LLUUID& getBlankImageAssetID() const { return mBlankImageAssetID; } + void setOpenTexPreview(bool open_preview) { mOpenTexPreview = open_preview; } + void setCaption(const std::string& caption); void setCanApplyImmediately(BOOL b); @@ -238,6 +250,8 @@ private: BOOL mShowLoadingPlaceholder; std::string mLoadingPlaceholderString; S32 mLabelWidth; + bool mOpenTexPreview; + BOOL mBakeTextureEnabled; }; ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 8baad30e8f..692e8d91a9 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -291,7 +291,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLineEditor->setText(edit_text_contents); std::string notif_name = mNotification->getName(); - if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name)) + if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name) || ("CreateSubfolder" == notif_name)) { mLineEditor->setPrevalidate(&LLTextValidate::validateASCII); } diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 50868d0fa5..b16b26b96e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -60,6 +60,7 @@ #include "llvoavatarself.h" #include "llworld.h" #include "llpanelface.h" +#include "lluiusage.h" // syntactic sugar #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember)) @@ -1100,7 +1101,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face, LLInventoryItem* item, LLToolDragAndDrop::ESource source, - const LLUUID& src_id) + const LLUUID& src_id, + S32 tex_channel) { if (hit_face == -1) return; if (!item) @@ -1124,7 +1126,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, if (gFloaterTools->getVisible() && panel_face) { - switch (LLSelectMgr::getInstance()->getTextureChannel()) + tex_channel = (tex_channel > -1) ? tex_channel : LLSelectMgr::getInstance()->getTextureChannel(); + switch (tex_channel) { case 0: @@ -1303,10 +1306,12 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, LLMessageSystem* msg = gMessageSystem; if (mSource == SOURCE_NOTECARD) { + LLUIUsage::instance().logCommand("Object.RezObjectFromNotecard"); msg->newMessageFast(_PREHASH_RezObjectFromNotecard); } else { + LLUIUsage::instance().logCommand("Object.RezObject"); msg->newMessageFast(_PREHASH_RezObject); } msg->nextBlockFast(_PREHASH_AgentData); diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 24a712029c..4537d73332 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -244,7 +244,8 @@ public: static void dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face, LLInventoryItem* item, ESource source, - const LLUUID& src_id); + const LLUUID& src_id, + S32 tex_channel = -1); static void dropTextureAllFaces(LLViewerObject* hit_obj, LLInventoryItem* item, ESource source, diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 43deac60d9..5fb83bf08e 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -71,6 +71,7 @@ #include "llui.h" #include "llweb.h" #include "pipeline.h" // setHighlightObject +#include "lluiusage.h" extern BOOL gDebugClicks; @@ -568,6 +569,8 @@ bool LLToolPie::walkToClickedLocation() return false; } + LLUIUsage::instance().logCommand("Agent.WalkToClickedLocation"); + LLPickInfo saved_pick = mPick; if (gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) { diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 814bade56a..7cdd7cc5c8 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -62,6 +62,7 @@ #include "llprimitive.h" #include "llwindow.h" // incBusyCount() #include "material_codes.h" +#include "lluiusage.h" const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f); @@ -227,6 +228,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); } + LLUIUsage::instance().logCommand("Build.ObjectAdd"); gMessageSystem->newMessageFast(_PREHASH_ObjectAdd); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 3f7e8531fb..14fae8d035 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -50,6 +50,10 @@ #include "llpreviewnotecard.h" #include "llpreviewgesture.h" #include "llcoproceduremanager.h" +#include "llthread.h" +#include "llkeyframemotion.h" +#include "lldatapacker.h" +#include "llvoavatarself.h" void dialog_refresh_all(); @@ -450,9 +454,62 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() errorLabel = "DoNotSupportBulkAnimationUpload"; error = true; } - else if (assetType == LLAssetType::AT_ANIMATION) + else if (exten == "anim") + { + // Default unless everything succeeds + errorLabel = "ProblemWithFile"; + error = true; + + // read from getFileName() + LLAPRFile infile; + infile.open(getFileName(),LL_APR_RB); + if (!infile.getFileHandle()) + { + LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL; + errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str()); + } + else + { + S32 size = LLAPRFile::size(getFileName()); + U8* buffer = new U8[size]; + S32 size_read = infile.read(buffer,size); + if (size_read != size) + { + errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read); + } + else + { + LLDataPackerBinaryBuffer dp(buffer, size); + LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId()); + motionp->setCharacter(gAgentAvatarp); + if (motionp->deserialize(dp, getAssetId(), false)) + { + // write to temp file + bool succ = motionp->dumpToFile(filename); + if (succ) + { + assetType = LLAssetType::AT_ANIMATION; + errorLabel = ""; + error = false; + } + else + { + errorMessage = "Failed saving temporary animation file"; + } + } + else + { + errorMessage = "Failed reading animation file"; + } + } + } + } + else { - filename = getFileName(); + // Unknown extension + errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str()); + errorLabel = "ErrorMessage"; + error = TRUE;; } if (error) @@ -863,6 +920,7 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res { args["FILE"] = uploadInfo->getDisplayName(); args["REASON"] = reason; + args["ERROR"] = reason; } LLNotificationsUtil::add(label, args); diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index 782285ce36..febae36ae8 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -33,8 +33,6 @@ // comment out to turn off wind #define kAUDIO_ENABLE_WIND //#define kAUDIO_ENABLE_WATER 1 // comment out to turn off water -#define kAUDIO_NUM_BUFFERS 30 -#define kAUDIO_NUM_SOURCES 30 void init_audio(); void audio_update_volume(bool force_update = true); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 9036e87514..bc46a61fb0 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -639,157 +639,186 @@ bool toggle_show_object_render_cost(const LLSD& newvalue) void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value); //////////////////////////////////////////////////////////////////////////// +LLPointer<LLControlVariable> setting_get_control(LLControlGroup& group, const std::string& setting) +{ + LLPointer<LLControlVariable> cntrl_ptr = group.getControl(setting); + if (cntrl_ptr.isNull()) + { + LL_ERRS() << "Unable to set up setting listener for " << setting + << ". Please reinstall viewer from https ://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." + << LL_ENDL; + } + return cntrl_ptr; +} + +void setting_setup_signal_listener(LLControlGroup& group, const std::string& setting, std::function<void(const LLSD& newvalue)> callback) +{ + setting_get_control(group, setting)->getSignal()->connect([callback](LLControlVariable* control, const LLSD& new_val, const LLSD& old_val) + { + callback(new_val); + }); +} + +void setting_setup_signal_listener(LLControlGroup& group, const std::string& setting, std::function<void()> callback) +{ + setting_get_control(group, setting)->getSignal()->connect([callback](LLControlVariable* control, const LLSD& new_val, const LLSD& old_val) + { + callback(); + }); +} + void settings_setup_listeners() { - gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2)); - gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2)); - gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2)); - gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); - gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); - gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); - gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); - gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); - gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleWindowResized, _2)); - gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); - gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2)); - gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2)); - gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleShadowsResized, _2)); - gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); - gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); - gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); - gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); - gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _2)); - gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _2)); - gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _2)); - gSavedSettings.getControl("RenderFogRatio")->getSignal()->connect(boost::bind(&handleFogRatioChanged, _2)); - gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _2)); - gSavedSettings.getControl("RenderDynamicLOD")->getSignal()->connect(boost::bind(&handleRenderDynamicLODChanged, _2)); - gSavedSettings.getControl("RenderLocalLights")->getSignal()->connect(boost::bind(&handleRenderLocalLightsChanged, _2)); - gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2)); - gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderVSyncEnable")->getSignal()->connect(boost::bind(&handleVSyncChanged, _2)); - gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); - gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2)); - gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2)); - gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2)); - gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); - gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); - gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); - gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); - gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); - gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); - gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _2)); - gSavedSettings.getControl("UseOcclusion")->getSignal()->connect(boost::bind(&handleUseOcclusionChanged, _2)); - gSavedSettings.getControl("AudioLevelMaster")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelSFX")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("AudioLevelUnderwaterRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2)); - gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderUseVAO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderPreferStreamDraw")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2)); - gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("JoystickAxis6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisScale6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("FlycamAxisDeadZone6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("AvatarAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("BuildAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _2)); - gSavedSettings.getControl("DebugViews")->getSignal()->connect(boost::bind(&handleDebugViewsChanged, _2)); - gSavedSettings.getControl("UserLogFile")->getSignal()->connect(boost::bind(&handleLogFileChanged, _2)); - gSavedSettings.getControl("RenderHideGroupTitle")->getSignal()->connect(boost::bind(handleHideGroupTitleChanged, _2)); - gSavedSettings.getControl("HighResSnapshot")->getSignal()->connect(boost::bind(handleHighResSnapshotChanged, _2)); - gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("PTTCurrentlyEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("PushToTalkButton")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("PushToTalkToggle")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("VoiceEarLocation")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); - gSavedSettings.getControl("VelocityInterpolate")->getSignal()->connect(boost::bind(&handleVelocityInterpolate, _2)); - gSavedSettings.getControl("QAMode")->getSignal()->connect(boost::bind(&show_debug_menus)); - gSavedSettings.getControl("UseDebugMenus")->getSignal()->connect(boost::bind(&show_debug_menus)); - gSavedSettings.getControl("AgentPause")->getSignal()->connect(boost::bind(&toggle_agent_pause, _2)); - gSavedSettings.getControl("ShowNavbarNavigationPanel")->getSignal()->connect(boost::bind(&toggle_show_navigation_panel, _2)); - gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2)); - gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2)); - gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); - gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); - gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); - gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); - gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); - gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); - gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2)); - gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&handleAvatarHoverOffsetChanged, _2)); + setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); + setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized); + setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); + setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); + setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarCloth", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarPhysicsLODFactor", handleAvatarPhysicsLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainLODFactor", handleTerrainLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTreeLODFactor", handleTreeLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFlexTimeFactor", handleFlexLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGamma", handleGammaChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFogRatio", handleFogRatioChanged); + setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderLocalLights", handleRenderLocalLightsChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged); + setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged); + setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged); + setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); + setting_setup_signal_listener(gSavedSettings, "TextureMemory", handleVideoMemoryChanged); + setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged); + setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged); + setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged); + setting_setup_signal_listener(gSavedSettings, "UploadBakedTexOld", handleUploadBakedTexOldChanged); + setting_setup_signal_listener(gSavedSettings, "UseOcclusion", handleUseOcclusionChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMaster", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelSFX", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelUI", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelAmbient", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMusic", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMedia", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelVoice", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelDoppler", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelRolloff", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelUnderwaterRolloff", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteAudio", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteMusic", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteMedia", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVBOEnable", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseVAO", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVBOMappingDisable", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseStreamVBO", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderPreferStreamDraw", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "DebugViews", handleDebugViewsChanged); + setting_setup_signal_listener(gSavedSettings, "UserLogFile", handleLogFileChanged); + setting_setup_signal_listener(gSavedSettings, "RenderHideGroupTitle", handleHideGroupTitleChanged); + setting_setup_signal_listener(gSavedSettings, "HighResSnapshot", handleHighResSnapshotChanged); + setting_setup_signal_listener(gSavedSettings, "EnableVoiceChat", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PTTCurrentlyEnabled", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PushToTalkButton", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PushToTalkToggle", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceEarLocation", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceInputAudioDevice", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceOutputAudioDevice", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMic", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VelocityInterpolate", handleVelocityInterpolate); + setting_setup_signal_listener(gSavedSettings, "QAMode", show_debug_menus); + setting_setup_signal_listener(gSavedSettings, "UseDebugMenus", show_debug_menus); + setting_setup_signal_listener(gSavedSettings, "AgentPause", toggle_agent_pause); + setting_setup_signal_listener(gSavedSettings, "ShowNavbarNavigationPanel", toggle_show_navigation_panel); + setting_setup_signal_listener(gSavedSettings, "ShowMiniLocationPanel", toggle_show_mini_location_panel); + setting_setup_signal_listener(gSavedSettings, "ShowObjectRenderingCost", toggle_show_object_render_cost); + setting_setup_signal_listener(gSavedSettings, "ForceShowGrid", handleForceShowGrid); + setting_setup_signal_listener(gSavedSettings, "RenderTransparentWater", handleRenderTransparentWaterChanged); + setting_setup_signal_listener(gSavedSettings, "SpellCheck", handleSpellCheckChanged); + setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged); + setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged); + setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMuteByteLimit", handleRenderAutoMuteByteLimitChanged); + + setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6a2b06d9b5..bc0fafb29f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -739,7 +739,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) glh::matrix4f proj = get_current_projection(); glh::matrix4f mod = get_current_modelview(); glViewport(0,0,512,512); - LLVOAvatar::updateFreezeCounter() ; LLVOAvatar::updateImpostors(); diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp new file mode 100644 index 0000000000..cec08c4f15 --- /dev/null +++ b/indra/newview/llviewerdisplayname.cpp @@ -0,0 +1,226 @@ +/** + * @file llviewerdisplayname.cpp + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewerdisplayname.h" + +// viewer includes +#include "llagent.h" +#include "llfloaterprofile.h" +#include "llfloaterreg.h" +#include "llviewerregion.h" +#include "llvoavatar.h" + +// library includes +#include "llavatarnamecache.h" +#include "llhttpnode.h" +#include "llnotificationsutil.h" +#include "llui.h" // getLanguage() + +namespace LLViewerDisplayName +{ + // Fired when viewer receives server response to display name change + set_name_signal_t sSetDisplayNameSignal; + + // Fired when there is a change in the agent's name + name_changed_signal_t sNameChangedSignal; + + void addNameChangedCallback(const name_changed_signal_t::slot_type& cb) + { + sNameChangedSignal.connect(cb); + } + + void doNothing() { } +} + +void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot) +{ + // TODO: simple validation here + + LLViewerRegion* region = gAgent.getRegion(); + llassert(region); + std::string cap_url = region->getCapability("SetDisplayName"); + if (cap_url.empty()) + { + // this server does not support display names, report error + slot(false, "unsupported", LLSD()); + return; + } + + // People API requires both the old and new value to change a variable. + // Our display name will be in cache before the viewer's UI is available + // to request a change, so we can use direct lookup without callback. + LLAvatarName av_name; + if (!LLAvatarNameCache::get( gAgent.getID(), &av_name)) + { + slot(false, "name unavailable", LLSD()); + return; + } + + // People API expects array of [ "old value", "new value" ] + LLSD change_array = LLSD::emptyArray(); + change_array.append(av_name.getDisplayName()); + change_array.append(display_name); + + LL_INFOS() << "Set name POST to " << cap_url << LL_ENDL; + + // Record our caller for when the server sends back a reply + sSetDisplayNameSignal.connect(slot); + + // POST the requested change. The sim will not send a response back to + // this request directly, rather it will send a separate message after it + // communicates with the back-end. + LLSD body; + body["display_name"] = change_array; + LLCoros::instance().launch("LLViewerDisplayName::SetDisplayNameCoro", + boost::bind(&LLViewerDisplayName::setDisplayNameCoro, cap_url, body)); +} + +void LLViewerDisplayName::setDisplayNameCoro(const std::string& cap_url, const LLSD& body) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("SetDisplayNameCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); + + // People API can return localized error messages. Indicate our + // language preference via header. + httpHeaders->append(HTTP_OUT_HEADER_ACCEPT_LANGUAGE, LLUI::getLanguage()); + + LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, body, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS() << "Unable to set display name. Status: " << status.toString() << LL_ENDL; + LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); + LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); + } +} + +class LLSetDisplayNameReply : public LLHTTPNode +{ + LOG_CLASS(LLSetDisplayNameReply); +public: + /*virtual*/ void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLSD body = input["body"]; + + S32 status = body["status"].asInteger(); + bool success = (status == HTTP_OK); + std::string reason = body["reason"].asString(); + LLSD content = body["content"]; + + LL_INFOS() << "status " << status << " reason " << reason << LL_ENDL; + + // If viewer's concept of display name is out-of-date, the set request + // will fail with 409 Conflict. If that happens, fetch up-to-date + // name information. + if (status == HTTP_CONFLICT) + { + LLUUID agent_id = gAgent.getID(); + // Flush stale data + LLAvatarNameCache::getInstance()->erase( agent_id ); + // Queue request for new data: nothing to do on callback though... + // Note: no need to disconnect the callback as it never gets out of scope + LLAvatarNameCache::getInstance()->get(agent_id, boost::bind(&LLViewerDisplayName::doNothing)); + // Kill name tag, as it is wrong + LLVOAvatar::invalidateNameTag( agent_id ); + } + + // inform caller of result + LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content); + LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); + } +}; + + +class LLDisplayNameUpdate : public LLHTTPNode +{ + /*virtual*/ void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLSD body = input["body"]; + LLUUID agent_id = body["agent_id"]; + std::string old_display_name = body["old_display_name"]; + // By convention this record is called "agent" in the People API + LLSD name_data = body["agent"]; + + // Inject the new name data into cache + LLAvatarName av_name; + av_name.fromLLSD( name_data ); + + LL_INFOS() << "name-update now " << LLDate::now() + << " next_update " << LLDate(av_name.mNextUpdate) + << LL_ENDL; + + // Name expiration time may be provided in headers, or we may use a + // default value + // *TODO: get actual headers out of ResponsePtr + //LLSD headers = response->mHeaders; + LLSD headers; + av_name.mExpires = + LLAvatarNameCache::getInstance()->nameExpirationFromHeaders(headers); + + LLAvatarNameCache::getInstance()->insert(agent_id, av_name); + + // force name tag to update + LLVOAvatar::invalidateNameTag(agent_id); + + LLSD args; + args["OLD_NAME"] = old_display_name; + args["SLID"] = av_name.getUserName(); + args["NEW_NAME"] = av_name.getDisplayName(); + LLNotificationsUtil::add("DisplayNameUpdate", args); + if (agent_id == gAgent.getID()) + { + LLViewerDisplayName::sNameChangedSignal(); + } + + LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::findInstance("profile", LLSD().with("id", agent_id))); + if (profile_floater) + { + profile_floater->refreshName(); + } + } +}; + +LLHTTPRegistration<LLSetDisplayNameReply> + gHTTPRegistrationMessageSetDisplayNameReply( + "/message/SetDisplayNameReply"); + +LLHTTPRegistration<LLDisplayNameUpdate> + gHTTPRegistrationMessageDisplayNameUpdate( + "/message/DisplayNameUpdate"); diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h new file mode 100644 index 0000000000..337aaa68b6 --- /dev/null +++ b/indra/newview/llviewerdisplayname.h @@ -0,0 +1,55 @@ +/** + * @file llviewerdisplayname.h + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERDISPLAYNAME_H +#define LLVIEWERDISPLAYNAME_H + +#include <boost/signals2.hpp> + +class LLSD; +class LLUUID; + +namespace LLViewerDisplayName +{ + typedef boost::signals2::signal< + void (bool success, const std::string& reason, const LLSD& content)> + set_name_signal_t; + typedef set_name_signal_t::slot_type set_name_slot_t; + + typedef boost::signals2::signal<void (void)> name_changed_signal_t; + typedef name_changed_signal_t::slot_type name_changed_slot_t; + + // Sends an update to the server to change a display name + // and call back when done. May not succeed due to service + // unavailable or name not available. + void set(const std::string& display_name, const set_name_slot_t& slot); + + void setDisplayNameCoro(const std::string& cap_url, const LLSD& body); + + void addNameChangedCallback(const name_changed_signal_t::slot_type& cb); +} + +#endif // LLVIEWERDISPLAYNAME_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dd03d6cfdd..06a6c5e373 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -57,11 +57,13 @@ #include "llfloatercamera.h" #include "llfloatercamerapresets.h" #include "llfloaterchatvoicevolume.h" +#include "llfloaterclassified.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" #include "llfloatercreatelandmark.h" #include "llfloaterdeleteprefpreset.h" #include "llfloaterdestinations.h" +#include "llfloaterdisplayname.h" #include "llfloatereditextdaycycle.h" #include "llfloaterenvironmentadjust.h" #include "llfloaterexperienceprofile.h" @@ -111,6 +113,7 @@ #include "llfloaterpreference.h" #include "llfloaterpreferenceviewadvanced.h" #include "llfloaterpreviewtrash.h" +#include "llfloaterprofile.h" #include "llfloaterproperties.h" #include "llfloaterregiondebugconsole.h" #include "llfloaterregioninfo.h" @@ -141,7 +144,6 @@ #include "llfloateruipreview.h" #include "llfloatervoiceeffect.h" #include "llfloaterwebcontent.h" -#include "llfloaterwebprofile.h" #include "llfloatervoicevolume.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindowsize.h" @@ -155,7 +157,7 @@ #include "llmoveview.h" #include "llfloaterimnearbychat.h" #include "llpanelblockedlist.h" -#include "llpanelclassified.h" +#include "llpanelprofileclassifieds.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" #include "llpreviewnotecard.h" @@ -228,6 +230,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); + LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>); @@ -275,6 +278,7 @@ void LLViewerFloaterReg::registerFloaters() LLInspectRemoteObjectUtil::registerFloater(); LLFloaterVoiceVolumeUtil::registerFloater(); LLNotificationsUI::registerFloater(); + LLFloaterDisplayNameUtil::registerFloater(); LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>); LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); @@ -320,7 +324,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>); LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>); LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>); - LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview"); LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>); @@ -367,8 +370,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>); LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); - LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); - LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); + LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>); LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 812f804ea9..a1cb152e1e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -48,7 +48,7 @@ #include "llmutelist.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llpanelprofile.h" +#include "llavataractions.h" #include "llparcel.h" #include "llpluginclassmedia.h" #include "llurldispatcher.h" @@ -3194,7 +3194,7 @@ bool LLViewerMediaImpl::isForcedUnloaded() const } // If this media's class is not supposed to be shown, unload - if (!shouldShowBasedOnClass()) + if (!shouldShowBasedOnClass() || isObscured()) { return true; } @@ -3881,6 +3881,40 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const ////////////////////////////////////////////////////////////////////////////////////////// // +bool LLViewerMediaImpl::isObscured() const +{ + if (getUsedInUI() || isParcelMedia() || isAttachedToHUD()) return false; + + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!agent_parcel) + { + return false; + } + + if (agent_parcel->getObscureMOAP() && !isInAgentParcel()) + { + return true; + } + + return false; +} + +bool LLViewerMediaImpl::isAttachedToHUD() const +{ + std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin(); + std::list< LLVOVolume* >::const_iterator end = mObjectList.end(); + for ( ; iter != end; iter++) + { + if ((*iter)->isHUDAttachment()) + { + return true; + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const { bool result = false; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 806692929a..f1f42afd81 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -411,6 +411,8 @@ public: void cancelMimeTypeProbe(); + bool isAttachedToHUD() const; + // Is this media attached to an avatar *not* self bool isAttachedToAnotherAvatar() const; @@ -423,6 +425,7 @@ public: private: bool isAutoPlayable() const; bool shouldShowBasedOnClass() const; + bool isObscured() const; static bool isObjectAttachedToAnotherAvatar(LLVOVolume *obj); static bool isObjectInAgentParcel(LLVOVolume *obj); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8522c2ed55..3573af40cb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -33,10 +33,11 @@ #include "llviewermenu.h" // linden library includes -#include "llavatarnamecache.h" // IDEVO +#include "llavatarnamecache.h" // IDEVO (I Are Not Men!) +#include "llcombobox.h" +#include "llcoros.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" -#include "llcombobox.h" #include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" @@ -53,6 +54,7 @@ #include "llcompilequeue.h" #include "llconsole.h" #include "lldebugview.h" +#include "lldiskcache.h" #include "llenvironment.h" #include "llfilepicker.h" #include "llfirstuse.h" @@ -93,6 +95,7 @@ #include "llmarketplacefunctions.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" +#include "llnavigationbar.h" #include "llparcel.h" #include "llrootview.h" #include "llsceneview.h" @@ -2100,6 +2103,32 @@ class LLAdvancedDropPacket : public view_listener_t } }; +////////////////////// +// PURGE DISK CACHE // +////////////////////// + + +class LLAdvancedPurgeDiskCache : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); + llassert_always(main_queue); + llassert_always(general_queue); + main_queue->postTo( + general_queue, + []() // Work done on general queue + { + LLDiskCache::getInstance()->purge(); + // Nothing needed to return + }, + [](){}); // Callback to main thread is empty as there is nothing left to do + + return true; + } +}; + //////////////////// // EVENT Recorder // @@ -2324,25 +2353,13 @@ class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t }; ///////////////////////////////////// -// Enable Framebuffer Objects /// -///////////////////////////////////// -class LLAdvancedEnableRenderFBO: public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - bool new_value = gGLManager.mHasFramebufferObject; - return new_value; - } -}; - -///////////////////////////////////// // Enable Deferred Rendering /// ///////////////////////////////////// class LLAdvancedEnableRenderDeferred: public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && + bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0; return new_value; } @@ -2355,7 +2372,7 @@ class LLAdvancedEnableRenderDeferredOptions: public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && + bool new_value = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred"); return new_value; } @@ -2407,6 +2424,7 @@ class LLAdvancedForceErrorLlerror : public view_listener_t return true; } }; + class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2416,6 +2434,22 @@ class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t } }; +class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLCoros::instance().launch( + "AdvancedForceErrorBadMemoryAccessCoro", + [](){ + // Wait for one mainloop() iteration, letting the enclosing + // handleEvent() method return. + llcoro::suspend(); + force_error_bad_memory_access(NULL); + }); + return true; + } +}; + class LLAdvancedForceErrorInfiniteLoop : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2434,6 +2468,22 @@ class LLAdvancedForceErrorSoftwareException : public view_listener_t } }; +class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLCoros::instance().launch( + "AdvancedForceErrorSoftwareExceptionCoro", + [](){ + // Wait for one mainloop() iteration, letting the enclosing + // handleEvent() method return. + llcoro::suspend(); + force_error_software_exception(NULL); + }); + return true; + } +}; + class LLAdvancedForceErrorDriverCrash : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -2725,6 +2775,32 @@ void handle_object_touch() send_ObjectDeGrab_message(object, pick); } +void handle_object_show_original() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) + { + return; + } + + LLViewerObject *parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if(parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + + if (!object || object->isAvatar()) + { + return; + } + + show_item_original(object->getAttachmentItemID()); +} static void init_default_item_label(const std::string& item_name) @@ -3609,6 +3685,11 @@ bool my_profile_visible() return floaterp && floaterp->isInVisibleChain(); } +bool picks_tab_visible() +{ + return my_profile_visible() && LLAvatarActions::isPickTabSelected(gAgentID); +} + bool enable_freeze_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar @@ -5334,12 +5415,10 @@ class LLToolsEnablePathfindingRebakeRegion : public view_listener_t { bool returnValue = false; - if (LLPathfindingManager::getInstance() != NULL) - { - LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance(); - returnValue = (rebakeInstance->canRebakeRegion() && - (rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available)); - } + if (LLNavigationBar::instanceExists()) + { + returnValue = LLNavigationBar::getInstance()->isRebakeNavMeshAvailable(); + } return returnValue; } }; @@ -6302,6 +6381,29 @@ class LLAvatarToggleMyProfile : public view_listener_t } }; +class LLAvatarTogglePicks : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloater * instance = LLAvatarActions::getProfileFloater(gAgent.getID()); + if (LLFloater::isMinimized(instance) || (instance && !instance->hasFocus() && !instance->getIsChrome())) + { + instance->setMinimized(FALSE); + instance->setFocus(TRUE); + LLAvatarActions::showPicks(gAgent.getID()); + } + else if (picks_tab_visible()) + { + instance->closeFloater(); + } + else + { + LLAvatarActions::showPicks(gAgent.getID()); + } + return true; + } +}; + class LLAvatarToggleSearch : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -6772,6 +6874,15 @@ class LLShowAgentProfile : public view_listener_t } }; +class LLShowAgentProfilePicks : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLAvatarActions::showPicks(gAgent.getID()); + return true; + } +}; + class LLToggleAgentProfile : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -9310,7 +9421,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); // Develop > Render view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion"); - view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO"); view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred"); view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions"); view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate"); @@ -9409,6 +9519,9 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog"); view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket"); + // Advanced > Cache + view_listener_t::addMenu(new LLAdvancedPurgeDiskCache(), "Advanced.PurgeDiskCache"); + // Advanced > Recorder view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot"); view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); @@ -9419,8 +9532,10 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror"); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess"); + view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); + view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash"); @@ -9495,12 +9610,14 @@ void initialize_menus() enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall)); view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse"); view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); + view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks"); view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch"); view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton"); view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations"); enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible)); + enable.add("Avatar.IsPicksTabOpen", boost::bind(&picks_tab_visible)); commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL"))); @@ -9510,6 +9627,7 @@ void initialize_menus() // Object pie menu view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); commit.add("Object.Touch", boost::bind(&handle_object_touch)); + commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); commit.add("Object.Delete", boost::bind(&handle_object_delete)); view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); @@ -9576,6 +9694,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak"); view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL"); view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); + view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks"); view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile"); view_listener_t::addMenu(new LLToggleControl(), "ToggleControl"); view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index be80d0bc0a..d97ed61e11 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -33,6 +33,7 @@ #include "llavataractions.h" #include "llavatarnamecache.h" // IDEVO HACK #include "lleventtimer.h" +#include "llfloatercreatelandmark.h" #include "llfloaterreg.h" #include "llfolderview.h" #include "llfollowcamparams.h" @@ -122,6 +123,7 @@ #include "llexperiencecache.h" #include "llexperiencecache.h" +#include "lluiusage.h" extern void on_new_message(const LLSD& msg); @@ -261,6 +263,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { case 0: { + LLUIUsage::instance().logCommand("Agent.AcceptFriendship"); // accept LLAvatarTracker::formFriendship(payload["from_id"]); @@ -303,6 +306,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) // fall-through case 2: // Send IM - decline and start IM session { + LLUIUsage::instance().logCommand("Agent.DeclineFriendship"); // decline // We no longer notify other viewers, but we DO still send // the rejection to the simulator to delete the pending userop. @@ -833,6 +837,11 @@ void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accep EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE; + if (accept_invite) + { + LLUIUsage::instance().logCommand("Group.Join"); + } + send_improved_im(group_id, std::string("name"), std::string("message"), @@ -1560,6 +1569,17 @@ bool highlight_offered_object(const LLUUID& obj_id) } } + if (obj->getType() == LLAssetType::AT_LANDMARK) + { + LLFloaterCreateLandmark *floater = LLFloaterReg::findTypedInstance<LLFloaterCreateLandmark>("add_landmark"); + if (floater && floater->getItem() && floater->getItem()->getUUID() == obj_id) + { + // LLFloaterCreateLandmark is supposed to handle this, + // keep landmark creation floater at the front + return false; + } + } + return true; } @@ -3334,13 +3354,6 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // trigger a control event. U32 control_flags = gAgent.getControlFlags(); - // Rotation into both directions should cancel out - U32 mask = AGENT_CONTROL_YAW_POS | AGENT_CONTROL_YAW_NEG; - if ((control_flags & mask) == mask) - { - control_flags &= ~mask; - } - MASK key_mask = gKeyboard->currentMask(TRUE); if (key_mask & MASK_ALT || key_mask & MASK_CONTROL) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a95636ff23..aad6c14b4d 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -356,6 +356,13 @@ LLViewerObject::~LLViewerObject() mPartSourcep = NULL; } + if (mText) + { + // something recovered LLHUDText when object was already dead + mText->markDead(); + mText = NULL; + } + // Delete memory associated with extra parameters. std::map<U16, ExtraParameter*>::iterator iter; for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) @@ -2457,11 +2464,19 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, needs_refresh = needs_refresh || child->mUserSelected; } + static LLCachedControl<bool> allow_select_avatar(gSavedSettings, "AllowSelectAvatar", FALSE); if (needs_refresh) { LLSelectMgr::getInstance()->updateSelectionCenter(); dialog_refresh_all(); - } + } + else if (allow_select_avatar && asAvatar()) + { + // Override any avatar position updates received + // Works only if avatar was repositioned using build + // tools and build floater is visible + LLSelectMgr::getInstance()->overrideAvatarUpdates(); + } // Mark update time as approx. now, with the ping delay. diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 55e2386d10..e930b58111 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -571,7 +571,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(update_cache) { - objectp = regionp->updateCacheEntry(local_id, objectp, update_type); + //update object cache if the object receives a full-update or terse update + objectp = regionp->updateCacheEntry(local_id, objectp); } // This looks like it will break if the local_id of the object doesn't change diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 12624ec3a2..36b2bd4c32 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -948,6 +948,7 @@ void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_M break; case STATE_MODE_DIFF: + if (mOctreeNode) { LLSpatialSetOcclusionStateDiff setter(state); setter.traverse(mOctreeNode); @@ -955,6 +956,7 @@ void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_M break; case STATE_MODE_BRANCH: + if (mOctreeNode) { LLSpatialSetOcclusionState setter(state); setter.traverse(mOctreeNode); @@ -1024,6 +1026,7 @@ void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE break; case STATE_MODE_DIFF: + if (mOctreeNode) { LLSpatialClearOcclusionStateDiff clearer(state); clearer.traverse(mOctreeNode); @@ -1031,6 +1034,7 @@ void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE break; case STATE_MODE_BRANCH: + if (mOctreeNode) { LLSpatialClearOcclusionState clearer(state); clearer.traverse(mOctreeNode); diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index e6974b0f84..7666062f99 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -45,11 +45,11 @@ class LLViewerOctreeGroup; class LLViewerOctreeEntry; class LLViewerOctreePartition; -typedef LLOctreeListener<LLViewerOctreeEntry> OctreeListener; -typedef LLTreeNode<LLViewerOctreeEntry> TreeNode; -typedef LLOctreeNode<LLViewerOctreeEntry> OctreeNode; -typedef LLOctreeRoot<LLViewerOctreeEntry> OctreeRoot; -typedef LLOctreeTraveler<LLViewerOctreeEntry> OctreeTraveler; +typedef LLOctreeListener<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeListener; +typedef LLTreeNode<LLViewerOctreeEntry> TreeNode; +typedef LLOctreeNode<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeNode; +typedef LLOctreeRoot<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeRoot; +typedef LLOctreeTraveler<LLViewerOctreeEntry, LLPointer<LLViewerOctreeEntry>> OctreeTraveler; #if LL_OCTREE_PARANOIA_CHECK #define assert_octree_valid(x) x->validate() @@ -179,7 +179,7 @@ protected: //defines an octree group for an octree node, which contains multiple entries. //LL_ALIGN_PREFIX(16) class LLViewerOctreeGroup -: public LLOctreeListener<LLViewerOctreeEntry> +: public OctreeListener { LL_ALIGN_NEW friend class LLViewerOctreeCull; @@ -198,8 +198,8 @@ public: }; public: - typedef LLOctreeNode<LLViewerOctreeEntry>::element_iter element_iter; - typedef LLOctreeNode<LLViewerOctreeEntry>::element_list element_list; + typedef OctreeNode::element_iter element_iter; + typedef OctreeNode::element_list element_list; LLViewerOctreeGroup(OctreeNode* node); LLViewerOctreeGroup(const LLViewerOctreeGroup& rhs) @@ -245,7 +245,6 @@ public: const LLVector4a* getObjectExtents() const {return mObjectExtents;} //octree wrappers to make code more readable - element_list& getData() { return mOctreeNode->getData(); } element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index e69b0347f8..75eb16c085 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1553,6 +1553,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use BOOL region_allow_environment_override = true; S32 parcel_environment_version = 0; BOOL agent_parcel_update = false; // updating previous(existing) agent parcel + U32 extended_flags = 0; //obscure MOAP S32 other_clean_time = 0; @@ -1591,6 +1592,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use else if (sequence_id == 0 || sequence_id > parcel_mgr.mAgentParcelSequenceID) { // new agent parcel + // *TODO: Does it really make sense to set the agent parcel to this + // parcel if the client doesn't know what kind of parcel data this is? parcel_mgr.mAgentParcelSequenceID = sequence_id; parcel = parcel_mgr.mAgentParcel; } @@ -1642,6 +1645,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use msg->getBOOLFast(_PREHASH_RegionAllowAccessBlock, _PREHASH_RegionAllowAccessOverride, region_allow_access_override); } + if (msg->getNumberOfBlocks(_PREHASH_ParcelExtendedFlags)) + { + msg->getU32Fast(_PREHASH_ParcelExtendedFlags, _PREHASH_Flags, extended_flags); + } + if (msg->getNumberOfBlocks(_PREHASH_ParcelEnvironmentBlock)) { msg->getS32Fast(_PREHASH_ParcelEnvironmentBlock, _PREHASH_ParcelEnvironmentVersion, parcel_environment_version); @@ -1698,6 +1706,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use parcel->setParcelEnvironmentVersion(cur_parcel_environment_version); parcel->setRegionAllowEnvironmentOverride(region_allow_environment_override); + parcel->setObscureMOAP((bool)extended_flags); + parcel->unpackMessage(msg); if (parcel == parcel_mgr.mAgentParcel) @@ -1879,8 +1889,13 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use } else { - // Check for video - LLViewerParcelMedia::getInstance()->update(parcel); + if (gNonInteractive) + { + return; + } + + // Check for video + LLViewerParcelMedia::getInstance()->update(parcel); // Then check for music if (gAudiop) diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 02f7bbeed8..785c84c38d 100644..100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -264,7 +264,7 @@ BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const { S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS); - return PARCEL_SOUND_LOCAL & mOwnership[row * mParcelGridsPerEdge + column]; + return parcelFlags(row, column, PARCEL_SOUND_LOCAL); } U8 LLViewerParcelOverlay::ownership( const LLVector3& pos) const @@ -278,12 +278,19 @@ U8 LLViewerParcelOverlay::parcelLineFlags(const LLVector3& pos) const { S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS); - return parcelLineFlags(row, column); + return parcelFlags(row, column, PARCEL_WEST_LINE | PARCEL_SOUTH_LINE); } U8 LLViewerParcelOverlay::parcelLineFlags(S32 row, S32 col) const { - U8 flags = PARCEL_WEST_LINE | PARCEL_SOUTH_LINE; - if (row > mParcelGridsPerEdge || col > mParcelGridsPerEdge) + return parcelFlags(row, col, PARCEL_WEST_LINE | PARCEL_SOUTH_LINE); +} + +U8 LLViewerParcelOverlay::parcelFlags(S32 row, S32 col, U8 flags) const +{ + if (row >= mParcelGridsPerEdge + || col >= mParcelGridsPerEdge + || row < 0 + || col < 0) { LL_WARNS() << "Attempted to get ownership out of region's overlay, row: " << row << " col: " << col << LL_ENDL; return flags; @@ -908,8 +915,8 @@ S32 LLViewerParcelOverlay::renderPropertyLines () // Always fudge a little vertically. pull_toward_camera.mV[VZ] += 0.01f; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); // Move to appropriate region coords LLVector3 origin = mRegion->getOriginAgent(); @@ -1014,7 +1021,66 @@ S32 LLViewerParcelOverlay::renderPropertyLines () } - gGL.popMatrix(); + gGL.popMatrix(); return drawn; } + +// Draw half of a single cell (no fill) in a grid drawn from left to right and from bottom to top +void grid_2d_part_lines(const F32 left, const F32 top, const F32 right, const F32 bottom, bool has_left, bool has_bottom) +{ + gGL.begin(LLRender::LINES); + + if (has_left) + { + gGL.vertex2f(left, bottom); + gGL.vertex2f(left, top); + } + if (has_bottom) + { + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, bottom); + } + + gGL.end(); +} + +void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) +{ + if (!mOwnership) + { + return; + } + if (!gSavedSettings.getBOOL("MiniMapShowPropertyLines")) + { + return; + } + + LLVector3 origin_agent = mRegion->getOriginAgent(); + LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent(); + F32 region_left = rel_region_pos.mV[0] * scale_pixels_per_meter; + F32 region_bottom = rel_region_pos.mV[1] * scale_pixels_per_meter; + F32 map_parcel_width = PARCEL_GRID_STEP_METERS * scale_pixels_per_meter; + const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + glLineWidth(1.0f); + gGL.color4fv(parcel_outline_color); + for (S32 i = 0; i < GRIDS_PER_EDGE + 1; i++) + { + const F32 bottom = region_bottom + (i * map_parcel_width); + const F32 top = bottom + map_parcel_width; + for (S32 j = 0; j < GRIDS_PER_EDGE + 1; j++) + { + const F32 left = region_left + (j * map_parcel_width); + const F32 right = left + map_parcel_width; + const bool is_region_boundary = i == GRIDS_PER_EDGE || j == GRIDS_PER_EDGE; + const U8 overlay = is_region_boundary ? 0 : mOwnership[(i * GRIDS_PER_EDGE) + j]; + // The property line vertices are three-dimensional, but here we only care about the x and y coordinates, as we are drawing on a + // 2D map + const bool has_left = i != GRIDS_PER_EDGE && (j == GRIDS_PER_EDGE || (overlay & PARCEL_WEST_LINE)); + const bool has_bottom = j != GRIDS_PER_EDGE && (i == GRIDS_PER_EDGE || (overlay & PARCEL_SOUTH_LINE)); + grid_2d_part_lines(left, top, right, bottom, has_left, has_bottom); + } + } +} diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index e30dbf17b3..c466cc3b6b 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -69,6 +69,7 @@ public: // Returns the number of vertices drawn S32 renderPropertyLines(); + void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); U8 ownership( const LLVector3& pos) const; U8 parcelLineFlags( const LLVector3& pos) const; @@ -82,12 +83,14 @@ public: void idleUpdate(bool update_now = false); void updateGL(); - + private: // This is in parcel rows and columns, not grid rows and columns // Stored in bottom three bits. U8 ownership(S32 row, S32 col) const - { return 0x7 & mOwnership[row * mParcelGridsPerEdge + col]; } + { return parcelFlags(row, col, (U8)0x7); } + + U8 parcelFlags(S32 row, S32 col, U8 flags) const; void addPropertyLine(std::vector<LLVector3>& vertex_array, std::vector<LLColor4U>& color_array, diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b282a2b90c..ad7321ca4b 100644..100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -95,8 +95,6 @@ // The server only keeps our pending agent info for 60 seconds. // We want to allow for seed cap retry, but its not useful after that 60 seconds. -// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. -const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; // Even though we gave up on login, keep trying for caps after we are logged in: const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000; @@ -178,7 +176,6 @@ public: mCompositionp(NULL), mEventPoll(NULL), mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), - mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), mSeedCapAttempts(0), mHttpResponderID(0), mLastCameraUpdate(0), @@ -231,7 +228,6 @@ public: LLEventPoll* mEventPoll; S32 mSeedCapMaxAttempts; - S32 mSeedCapMaxAttemptsBeforeLogin; S32 mSeedCapAttempts; S32 mHttpResponderID; @@ -266,14 +262,13 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) return; } - LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton! - if (!world_inst) + if (!LLWorld::instanceExists()) { LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL; return; } - regionp = world_inst->getRegionFromHandle(regionHandle); + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); if (!regionp) //region was removed { LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL; @@ -287,19 +282,13 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) if (url.empty()) { LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL; + regionp->setCapabilitiesError(); return; // this error condition is not recoverable. } // record that we just entered a new region newRegionEntry(*regionp); - // After a few attempts, continue login. But keep trying to get the caps: - if (impl->mSeedCapAttempts >= impl->mSeedCapMaxAttemptsBeforeLogin && - STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); - } - if (impl->mSeedCapAttempts > impl->mSeedCapMaxAttempts) { // *TODO: Give a user pop-up about this error? @@ -321,7 +310,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) regionp = NULL; impl = NULL; - world_inst = NULL; result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames); if (STATE_WORLD_INIT > LLStartUp::getStartupState()) @@ -332,17 +320,17 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) if (LLApp::isExiting() || gDisconnected) { + LL_DEBUGS("AppInit", "Capabilities") << "Shutting down" << LL_ENDL; return; } - world_inst = LLWorld::getInstance(); - if (!world_inst) + if (!LLWorld::instanceExists()) { LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL; return; } - regionp = world_inst->getRegionFromHandle(regionHandle); + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); if (!regionp) //region was removed { LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; @@ -351,14 +339,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) impl = regionp->getRegionImplNC(); - ++impl->mSeedCapAttempts; - - if (id != impl->mHttpResponderID) // region is no longer referring to this request - { - LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL; - // setup for retry. - continue; - } + ++(impl->mSeedCapAttempts); if (!result.isMap() || result.has("error")) { @@ -379,6 +360,13 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) // remove the http_result from the llsd result.erase("http_result"); + if (id != impl->mHttpResponderID) // region is no longer referring to this request + { + LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL; + // setup for retry. + continue; + } + LLSD::map_const_iterator iter; for (iter = result.beginMap(); iter != result.endMap(); ++iter) { @@ -396,11 +384,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) << " region name " << regionp->getName() << LL_ENDL; regionp->setCapabilitiesReceived(true); - if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); - } - break; } while (true); @@ -444,6 +427,11 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle) if (url.empty()) { LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL; + if (regionp->getCapability("Seed").empty()) + { + // initial attempt failed to get this cap as well + regionp->setCapabilitiesError(); + } break; // this error condition is not recoverable. } @@ -645,7 +633,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mCacheLoaded(FALSE), mCacheDirty(FALSE), mReleaseNotesRequested(FALSE), - mCapabilitiesReceived(false), + mCapabilitiesState(CAPABILITIES_STATE_INIT), mSimulatorFeaturesReceived(false), mBitsReceived(0.f), mPacketsReceived(0.f), @@ -1080,6 +1068,15 @@ S32 LLViewerRegion::renderPropertyLines() } } +void LLViewerRegion::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) +{ + if (mParcelOverlay) + { + mParcelOverlay->renderPropertyLinesOnMinimap(scale_pixels_per_meter, parcel_outline_color); + } +} + + // This gets called when the height field changes. void LLViewerRegion::dirtyHeights() { @@ -1820,13 +1817,8 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry) //update object cache if the object receives a full-update or terse update //update_type == EObjectUpdateType::OUT_TERSE_IMPROVED or EObjectUpdateType::OUT_FULL -LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type) +LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* objectp) { - if(objectp && update_type != (U32)OUT_TERSE_IMPROVED) - { - return objectp; //no need to access cache - } - LLVOCacheEntry* entry = getCacheEntry(local_id); if (!entry) { @@ -1838,11 +1830,8 @@ LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* o objectp = addNewObject(entry); } - //remove from cache if terse update - if(update_type == (U32)OUT_TERSE_IMPROVED) - { - killCacheEntry(entry, true); - } + //remove from cache. + killCacheEntry(entry, true); return objectp; } @@ -2302,6 +2291,11 @@ void LLViewerRegion::requestSimulatorFeatures() std::string coroname = LLCoros::instance().launch("LLViewerRegionImpl::requestSimulatorFeatureCoro", boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, url, getHandle())); + + // requestSimulatorFeatures can be called from other coros, + // launch() acts like a suspend() + // Make sure we are still good to do + LLCoros::checkStop(); LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << " for region " << getRegionID() << LL_ENDL; } @@ -3002,6 +2996,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("AcceptFriendship"); capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("AgentPreferences"); + capabilityNames.append("AgentProfile"); capabilityNames.append("AgentState"); capabilityNames.append("AttachmentResources"); capabilityNames.append("AvatarPickerSearch"); @@ -3096,6 +3091,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UpdateScriptTask"); capabilityNames.append("UpdateSettingsAgentInventory"); capabilityNames.append("UpdateSettingsTaskInventory"); + capabilityNames.append("UploadAgentProfileImage"); capabilityNames.append("UploadBakedTexture"); capabilityNames.append("UserInfo"); capabilityNames.append("ViewerAsset"); @@ -3121,6 +3117,12 @@ void LLViewerRegion::setSeedCapability(const std::string& url) std::string coroname = LLCoros::instance().launch("LLEnvironmentRequest::requestBaseCapabilitiesCompleteCoro", boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, getHandle())); + + // setSeedCapability can be called from other coros, + // launch() acts like a suspend() + // Make sure we are still good to do + LLCoros::checkStop(); + return; } @@ -3134,6 +3136,11 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LLCoros::instance().launch("LLViewerRegionImpl::requestBaseCapabilitiesCoro", boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, getHandle())); + // setSeedCapability can be called from other coros, + // launch() acts like a suspend() + // Make sure we are still good to do + LLCoros::checkStop(); + LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << " for region " << getRegionID() << LL_ENDL; } @@ -3255,12 +3262,17 @@ bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const bool LLViewerRegion::capabilitiesReceived() const { - return mCapabilitiesReceived; + return mCapabilitiesState == CAPABILITIES_STATE_RECEIVED; +} + +bool LLViewerRegion::capabilitiesError() const +{ + return mCapabilitiesState == CAPABILITIES_STATE_ERROR; } void LLViewerRegion::setCapabilitiesReceived(bool received) { - mCapabilitiesReceived = received; + mCapabilitiesState = received ? CAPABILITIES_STATE_RECEIVED : CAPABILITIES_STATE_INIT; // Tell interested parties that we've received capabilities, // so that they can safely use getCapability(). @@ -3275,6 +3287,11 @@ void LLViewerRegion::setCapabilitiesReceived(bool received) } } +void LLViewerRegion::setCapabilitiesError() +{ + mCapabilitiesState = CAPABILITIES_STATE_ERROR; +} + boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) { return mCapabilitiesReceivedSignal.connect(cb); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index fcbf56c81f..6548e8d372 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -154,6 +154,8 @@ public: // Draw lines in the dirt showing ownership. Return number of // vertices drawn. S32 renderPropertyLines(); + void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); + // Call this whenever you change the height data in the region. // (Automatically called by LLSurfacePatch's update routine) @@ -268,7 +270,9 @@ public: // has region received its final (not seed) capability list? bool capabilitiesReceived() const; + bool capabilitiesError() const; void setCapabilitiesReceived(bool received); + void setCapabilitiesError(); boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); static bool isSpecialCapabilityName(const std::string &name); @@ -352,7 +356,7 @@ public: void requestCacheMisses(); void addCacheMissFull(const U32 local_id); //update object cache if the object receives a full-update or terse update - LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp, U32 update_type); + LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp); void findOrphans(U32 parent_id); void clearCachedVisibleObjects(); void dumpCache(); @@ -527,12 +531,20 @@ private: BOOL mCacheLoaded; BOOL mCacheDirty; BOOL mAlive; // can become false if circuit disconnects - BOOL mCapabilitiesReceived; BOOL mSimulatorFeaturesReceived; BOOL mReleaseNotesRequested; BOOL mDead; //if true, this region is in the process of deleting. BOOL mPaused; //pause processing the objects in the region + typedef enum + { + CAPABILITIES_STATE_INIT = 0, + CAPABILITIES_STATE_ERROR, + CAPABILITIES_STATE_RECEIVED + } eCababilitiesState; + + eCababilitiesState mCapabilitiesState; + typedef std::map<U32, std::vector<U32> > orphan_list_t; orphan_list_t mOrphanMap; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index c084e1d521..5475d66216 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -558,15 +558,14 @@ void LLViewerShaderMgr::setShaders() mShaderLevel[SHADER_DEFERRED] = deferred_class; mShaderLevel[SHADER_TRANSFORM] = transform_class; - BOOL loaded = loadBasicShaders(); - if (loaded) + std::string shader_name = loadBasicShaders(); + if (shader_name.empty()) { LL_INFOS() << "Loaded basic shaders." << LL_ENDL; } else { - LL_ERRS() << "Unable to load basic shaders, verify graphics driver installed and current." << LL_ENDL; - llassert(loaded); + LL_ERRS() << "Unable to load basic shader " << shader_name << ", verify graphics driver installed and current." << LL_ENDL; reentrance = false; // For hygiene only, re-try probably helps nothing return; } @@ -574,7 +573,7 @@ void LLViewerShaderMgr::setShaders() gPipeline.mShadersLoaded = true; // Load all shaders to set max levels - loaded = loadShadersEnvironment(); + BOOL loaded = loadShadersEnvironment(); if (loaded) { @@ -864,7 +863,7 @@ void LLViewerShaderMgr::unloadShaders() gPipeline.mShadersLoaded = false; } -BOOL LLViewerShaderMgr::loadBasicShaders() +std::string LLViewerShaderMgr::loadBasicShaders() { // Load basic dependency shaders first // All of these have to load for any shaders to function @@ -950,8 +949,8 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // Note usage of GL_VERTEX_SHADER_ARB if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0) { - LL_SHADER_LOADING_WARNS() << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; - return FALSE; + LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; + return shaders[i].first; } } @@ -1010,12 +1009,12 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // Note usage of GL_FRAGMENT_SHADER_ARB if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0) { - LL_SHADER_LOADING_WARNS() << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; - return FALSE; + LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; + return shaders[i].first; } } - return TRUE; + return std::string(); } BOOL LLViewerShaderMgr::loadShadersEnvironment() @@ -1517,6 +1516,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + if (alpha_mode != 0) + { + gDeferredMaterialProgram[i].mFeatures.hasAlphaMask = true; + gDeferredMaterialProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); + } + if (use_sun_shadow) { gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); @@ -1575,6 +1580,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); + if (alpha_mode != 0) + { + gDeferredMaterialWaterProgram[i].mFeatures.hasAlphaMask = true; + gDeferredMaterialWaterProgram[i].addPermutation("HAS_ALPHA_MASK", "1"); + } + if (use_sun_shadow) { gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index d8eeccbb22..59ba384bf7 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -49,7 +49,11 @@ public: void setShaders(); void unloadShaders(); S32 getShaderLevel(S32 type); - BOOL loadBasicShaders(); + + // loadBasicShaders in case of a failure returns + // name of a file error happened at, otherwise + // returns an empty string + std::string loadBasicShaders(); BOOL loadShadersEffects(); BOOL loadShadersDeferred(); BOOL loadShadersObject(); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 18e84fe4f0..327f121caf 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -553,6 +553,7 @@ void send_viewer_stats(bool include_preferences) system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value(); system["os"] = LLOSInfo::instance().getOSStringSimple(); system["cpu"] = gSysCPU.getCPUString(); + system["cpu_sse"] = gSysCPU.getSSEVersions(); system["address_size"] = ADDRESS_SIZE; system["os_bitness"] = LLOSInfo::instance().getOSBitness(); unsigned char MACAddress[MAC_ADDRESS_BYTES]; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index bbbf9ea7a3..da3c860ddb 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1148,15 +1148,14 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) total_update_count--; } } - - S32 fetch_count = 0; + size_t min_update_count = llmin(MIN_UPDATE_COUNT,(S32)(entries.size()-max_priority_count)); S32 min_count = max_priority_count + min_update_count; for (entries_list_t::iterator iter3 = entries.begin(); iter3 != entries.end(); ) { LLViewerFetchedTexture* imagep = *iter3++; - fetch_count += (imagep->updateFetch() ? 1 : 0); + imagep->updateFetch(); if (min_count <= min_update_count) { mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); @@ -1262,7 +1261,8 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) BOOL LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, - const U8 codec) + const U8 codec, + const S32 max_image_dimentions) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // Load the image @@ -1291,7 +1291,7 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, return FALSE; } // Convert to j2c (JPEG2000) and save the file locally - LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image); + LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions); if (compressedImage.isNull()) { image->setLastError("Couldn't convert the image to jpeg2000."); @@ -1316,10 +1316,10 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, } // note: modifies the argument raw_image!!!! -LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image) +LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + raw_image->biasedScaleToPowerOfTwo(max_image_dimentions); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); if (gSavedSettings.getBOOL("LosslessJ2CUpload") && diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index fead2e52b2..6fb0d3552e 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -92,8 +92,11 @@ class LLViewerTextureList friend class LLLocalBitmap; public: - static BOOL createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec); - static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image); + static BOOL createUploadFile(const std::string& filename, + const std::string& out_filename, + const U8 codec, + const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data ); static void receiveImageHeader(LLMessageSystem *msg, void **user_data); static void receiveImagePacket(LLMessageSystem *msg, void **user_data); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 24e4a02b61..8a7d5f12d0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -103,7 +103,6 @@ #include "llfilepicker.h" #include "llfirstuse.h" #include "llfloater.h" -#include "llfloaterbuildoptions.h" #include "llfloaterbuyland.h" #include "llfloatercamera.h" #include "llfloaterland.h" @@ -773,6 +772,12 @@ public: ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Skins/Decompositions Memory", LLMeshRepository::sCacheBytesSkins / (1024.f*1024.f), LLMeshRepository::sCacheBytesDecomps / (1024.f*1024.f))); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.3f MB Mesh Headers Memory", LLMeshRepository::sCacheBytesHeaders / (1024.f*1024.f))); ypos += y_inc; } @@ -1568,9 +1573,11 @@ void LLViewerWindow::handleFocusLost(LLWindow *window) showCursor(); getWindow()->setMouseClipping(FALSE); - // If losing focus while keys are down, reset them. + // If losing focus while keys are down, handle them as + // an 'up' to correctly release states, then reset states if (gKeyboard) { + gKeyboard->resetKeyDownAndHandle(); gKeyboard->resetKeys(); } @@ -1998,7 +2005,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) } LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable")); LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; - gGL.init() ; + gGL.init(true); if (LLFeatureManager::getInstance()->isSafe() || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) @@ -2511,10 +2518,11 @@ void LLViewerWindow::reshape(S32 width, S32 height) //glViewport(0, 0, width, height ); - if (height > 0) + LLViewerCamera * camera = LLViewerCamera::getInstance(); // simpleton, might not exist + if (height > 0 && camera) { - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + camera->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + camera->setAspect( getWorldViewAspectRatio() ); } calcDisplayScale(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 314c22eb6c..42550ed48d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1,4 +1,4 @@ -/** +/** * @File llvoavatar.cpp * @brief Implementation of LLVOAvatar class which is a derivation of LLViewerObject * @@ -183,8 +183,6 @@ const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32; // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB const S32 SWITCH_TO_BAKED_DISCARD = 5; -const F32 FOOT_COLLIDE_FUDGE = 0.04f; - const F32 HOVER_EFFECT_MAX_SPEED = 3.f; const F32 HOVER_EFFECT_STRENGTH = 0.f; const F32 UNDERWATER_EFFECT_STRENGTH = 0.1f; @@ -585,7 +583,6 @@ private: //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -S32 LLVOAvatar::sFreezeCounter = 0; U32 LLVOAvatar::sMaxNonImpostors = 12; // Set from RenderAvatarMaxNonImpostors bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonImpostors is 0 (unlimited) F32 LLVOAvatar::sRenderDistance = 256.f; @@ -610,7 +607,6 @@ S32 LLVOAvatar::sNumVisibleChatBubbles = 0; BOOL LLVOAvatar::sDebugInvisible = FALSE; BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; BOOL LLVOAvatar::sShowAnimationDebug = FALSE; -BOOL LLVOAvatar::sShowFootPlane = FALSE; BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; @@ -779,6 +775,13 @@ std::string LLVOAvatar::avString() const void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string comment) { + if (gDisconnected) + { + // If we disconected, these values are likely to be invalid and + // avString() might crash due to a dead sAvatarDictionary + return; + } + LL_INFOS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ]" << avString() @@ -2810,6 +2813,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (detailed_update) { U32 draw_order = 0; + S32 attachment_selected = LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment(); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -2849,7 +2853,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } // if selecting any attachments, update all of them as non-damped - if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment()) + if (attachment_selected) { gPipeline.updateMoveNormalAsync(attached_object->mDrawable); } @@ -4105,8 +4109,7 @@ void LLVOAvatar::computeUpdatePeriod() && (!isSelf() || visually_muted) && !isUIAvatar() && (sLimitNonImpostors || visually_muted) - && !mNeedsAnimUpdate - && !sFreezeCounter) + && !mNeedsAnimUpdate) { const LLVector4a* ext = mDrawable->getSpatialExtents(); LLVector4a size; @@ -4619,7 +4622,12 @@ bool LLVOAvatar::updateCharacter(LLAgent &agent) } else if (!getParent() && isSitting() && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED)) { - getOffObject(); + // If we are starting up, motion might be loading + LLMotion *motionp = mMotionController.findMotion(ANIM_AGENT_SIT_GROUND_CONSTRAINED); + if (!motionp || !mMotionController.isMotionLoading(motionp)) + { + getOffObject(); + } } //-------------------------------------------------------------------- @@ -5074,42 +5082,6 @@ U32 LLVOAvatar::renderSkinned() return num_indices; } - // render collision normal - // *NOTE: this is disabled (there is no UI for enabling sShowFootPlane) due - // to DEV-14477. the code is left here to aid in tracking down the cause - // of the crash in the future. -brad - if (sShowFootPlane && mDrawable.notNull()) - { - LLVector3 slaved_pos = mDrawable->getPositionAgent(); - LLVector3 foot_plane_normal(mFootPlane.mV[VX], mFootPlane.mV[VY], mFootPlane.mV[VZ]); - F32 dist_from_plane = (slaved_pos * foot_plane_normal) - mFootPlane.mV[VW]; - LLVector3 collide_point = slaved_pos; - collide_point.mV[VZ] -= foot_plane_normal.mV[VZ] * (dist_from_plane + COLLISION_TOLERANCE - FOOT_COLLIDE_FUDGE); - - gGL.begin(LLRender::LINES); - { - F32 SQUARE_SIZE = 0.2f; - gGL.color4f(1.f, 0.f, 0.f, 1.f); - - gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]); - gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]); - - gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]); - gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]); - - gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]); - gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]); - - gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]); - gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]); - - gGL.vertex3f(collide_point.mV[VX], collide_point.mV[VY], collide_point.mV[VZ]); - gGL.vertex3f(collide_point.mV[VX] + mFootPlane.mV[VX], collide_point.mV[VY] + mFootPlane.mV[VY], collide_point.mV[VZ] + mFootPlane.mV[VZ]); - - } - gGL.end(); - gGL.flush(); - } //-------------------------------------------------------------------- // render all geometry attached to the skeleton //-------------------------------------------------------------------- @@ -6184,7 +6156,21 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) if (iter == mJointMap.end() || iter->second == NULL) { //search for joint and cache found joint in lookup table - jointp = mRoot->findJoint(name); + if (mJointAliasMap.empty()) + { + getJointAliases(); + } + joint_alias_map_t::const_iterator alias_iter = mJointAliasMap.find(name); + std::string canonical_name; + if (alias_iter != mJointAliasMap.end()) + { + canonical_name = alias_iter->second; + } + else + { + canonical_name = name; + } + jointp = mRoot->findJoint(canonical_name); mJointMap[name] = jointp; } else @@ -7236,6 +7222,14 @@ LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx) } //----------------------------------------------------------------------------- +// hideHair() +//----------------------------------------------------------------------------- +void LLVOAvatar::hideHair() +{ + mMeshLOD[MESH_ID_HAIR]->setVisible(FALSE, TRUE); +} + +//----------------------------------------------------------------------------- // hideSkirt() //----------------------------------------------------------------------------- void LLVOAvatar::hideSkirt() @@ -10240,23 +10234,6 @@ LLHost LLVOAvatar::getObjectHost() const } } -//static -void LLVOAvatar::updateFreezeCounter(S32 counter) -{ - if(counter) - { - sFreezeCounter = counter; - } - else if(sFreezeCounter > 0) - { - sFreezeCounter--; - } - else - { - sFreezeCounter = 0; - } -} - BOOL LLVOAvatar::updateLOD() { if (mDrawable.isNull()) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 3c3decaad6..8d1dcbcda2 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -326,7 +326,6 @@ public: static bool sLimitNonImpostors; // use impostors for far away avatars static F32 sRenderDistance; // distance at which avatars will render. static BOOL sShowAnimationDebug; // show animation debug info - static BOOL sShowFootPlane; // show foot collision plane reported by server static BOOL sShowCollisionVolumes; // show skeletal collision volumes static BOOL sVisibleInFirstPerson; static S32 sNumLODChangesThisFrame; @@ -618,14 +617,6 @@ private: BOOL mCulled; //-------------------------------------------------------------------- - // Freeze counter - //-------------------------------------------------------------------- -public: - static void updateFreezeCounter(S32 counter = 0); -private: - static S32 sFreezeCounter; - - //-------------------------------------------------------------------- // Constants //-------------------------------------------------------------------- public: @@ -808,6 +799,7 @@ public: void parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& msg); void processAvatarAppearance(LLMessageSystem* mesgsys); void applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params); + void hideHair(); void hideSkirt(); void startAppearanceAnimation(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 60a69a4ac4..8fc1dcd81f 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -67,6 +67,7 @@ #include "llsdserialize.h" #include "llcallstack.h" #include "llcorehttputil.h" +#include "lluiusage.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -2663,6 +2664,7 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) { if (isAgentAvatarValid()) { + LLUIUsage::instance().logCommand("Avatar.CustomizeStart"); if (!gAgentAvatarp->mEndCustomizeCallback.get()) { gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index db8ad183f0..55fc663496 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -366,15 +366,6 @@ void LLVOCacheEntry::updateDebugSettings() } timer.reset(); - //the number of frames invisible objects stay in memory - static LLCachedControl<U32> inv_obj_time(gSavedSettings,"NonvisibleObjectsInMemoryTime"); - sMinFrameRange = inv_obj_time - 1; //make 0 to be the maximum - - //min radius: all objects within this radius remain loaded in memory - static LLCachedControl<F32> min_radius(gSavedSettings,"SceneLoadMinRadius"); - sNearRadius = llmin((F32)min_radius, gAgentCamera.mDrawDistance); //can not exceed the draw distance - sNearRadius = llmax(sNearRadius, 1.f); //minimum value is 1.0m - //objects within the view frustum whose visible area is greater than this threshold will be loaded static LLCachedControl<F32> front_pixel_threshold(gSavedSettings,"SceneLoadFrontPixelThreshold"); sFrontPixelThreshold = front_pixel_threshold; @@ -384,29 +375,38 @@ void LLVOCacheEntry::updateDebugSettings() sRearPixelThreshold = rear_pixel_threshold; sRearPixelThreshold = llmax(sRearPixelThreshold, sFrontPixelThreshold); //can not be smaller than sFrontPixelThreshold. - // a percentage of draw distance beyond which all objects outside of view frustum will be unloaded, regardless of pixel threshold - static LLCachedControl<F32> rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction"); - sRearFarRadius = llmax(rear_max_radius_frac * gAgentCamera.mDrawDistance / 100.f, 1.0f); //minimum value is 1.0m - sRearFarRadius = llmax(sRearFarRadius, (F32)min_radius); //can not be less than "SceneLoadMinRadius". - sRearFarRadius = llmin(sRearFarRadius, gAgentCamera.mDrawDistance); //can not be more than the draw distance. - - //make the above parameters adaptive to memory usage + //make parameters adaptive to memory usage //starts to put restrictions from low_mem_bound_MB, apply tightest restrictions when hits high_mem_bound_MB static LLCachedControl<U32> low_mem_bound_MB(gSavedSettings,"SceneLoadLowMemoryBound"); static LLCachedControl<U32> high_mem_bound_MB(gSavedSettings,"SceneLoadHighMemoryBound"); LLMemory::updateMemoryInfo() ; U32 allocated_mem = LLMemory::getAllocatedMemKB().value(); - allocated_mem /= 1024; //convert to MB. - if(allocated_mem < low_mem_bound_MB) - { - return; - } - F32 adjust_factor = llmax(0.f, (F32)(high_mem_bound_MB - allocated_mem) / (high_mem_bound_MB - low_mem_bound_MB)); - - sRearFarRadius = llmin(adjust_factor * sRearFarRadius, 96.f); //[0.f, 96.f] - sMinFrameRange = (U32)llclamp(adjust_factor * sMinFrameRange, 10.f, 64.f); //[10, 64] - sNearRadius = llmax(adjust_factor * sNearRadius, 1.0f); + static const F32 KB_to_MB = 1.f / 1024.f; + U32 clamped_memory = llclamp(allocated_mem * KB_to_MB, (F32) low_mem_bound_MB, (F32) high_mem_bound_MB); + const F32 adjust_range = high_mem_bound_MB - low_mem_bound_MB; + const F32 adjust_factor = (high_mem_bound_MB - clamped_memory) / adjust_range; // [0, 1] + + //min radius: all objects within this radius remain loaded in memory + static LLCachedControl<F32> min_radius(gSavedSettings,"SceneLoadMinRadius"); + static const F32 MIN_RADIUS = 1.0f; + const F32 draw_radius = gAgentCamera.mDrawDistance; + const F32 clamped_min_radius = llclamp((F32) min_radius, MIN_RADIUS, draw_radius); // [1, mDrawDistance] + sNearRadius = MIN_RADIUS + ((clamped_min_radius - MIN_RADIUS) * adjust_factor); + + // a percentage of draw distance beyond which all objects outside of view frustum will be unloaded, regardless of pixel threshold + static LLCachedControl<F32> rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction"); + const F32 min_radius_plus_one = sNearRadius + 1.f; + const F32 max_radius = rear_max_radius_frac * gAgentCamera.mDrawDistance; + const F32 clamped_max_radius = llclamp(max_radius, min_radius_plus_one, draw_radius); // [sNearRadius, mDrawDistance] + sRearFarRadius = min_radius_plus_one + ((clamped_max_radius - min_radius_plus_one) * adjust_factor); + + //the number of frames invisible objects stay in memory + static LLCachedControl<U32> inv_obj_time(gSavedSettings,"NonvisibleObjectsInMemoryTime"); + static const U32 MIN_FRAMES = 10; + static const U32 MAX_FRAMES = 64; + const U32 clamped_frames = inv_obj_time ? llclamp((U32) inv_obj_time, MIN_FRAMES, MAX_FRAMES) : MAX_FRAMES; // [10, 64], with zero => 64 + sMinFrameRange = MIN_FRAMES + ((clamped_frames - MIN_FRAMES) * adjust_factor); } //static diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index f971554c9d..b0eb8d962c 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -770,8 +770,6 @@ LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string mReceivedCall(FALSE) { // make sure URI reflects encoded version of other user's agent id - // *NOTE: in case of Avaline call generated SIP URL will be incorrect. - // But it will be overridden in LLVoiceChannelP2P::setSessionHandle() called when agent accepts call setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id)); } @@ -911,8 +909,6 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s else { LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL; - // In the case of an incoming AvaLine call, the generated URI will be different from the - // original one. This is because the P2P URI is based on avatar UUID but Avaline is not. // See LLVoiceClient::sessionAddedEvent() setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID)); } @@ -947,22 +943,5 @@ void LLVoiceChannelP2P::setState(EState state) void LLVoiceChannelP2P::addToTheRecentPeopleList() { - bool avaline_call = LLIMModel::getInstance()->findIMSession(mSessionID)->isAvalineSessionType(); - - if (avaline_call) - { - LLSD call_data; - std::string call_number = LLVoiceChannel::getSessionName(); - - call_data["avaline_call"] = true; - call_data["session_id"] = mSessionID; - call_data["call_number"] = call_number; - call_data["date"] = LLDate::now(); - - LLRecentPeople::instance().add(mOtherUserID, call_data); - } - else - { - LLRecentPeople::instance().add(mOtherUserID); - } + LLRecentPeople::instance().add(mOtherUserID); } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index e2bd1a39c7..2ef2d66f18 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -37,6 +37,7 @@ #include "llui.h" #include "llkeyboard.h" #include "llagent.h" +#include "lluiusage.h" const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; @@ -200,6 +201,7 @@ const LLVoiceVersionInfo LLVoiceClient::getVersion() LLVoiceVersionInfo result; result.serverVersion = std::string(); result.serverType = std::string(); + result.mBuildVersion = std::string(); return result; } } @@ -602,6 +604,10 @@ void LLVoiceClient::setMuteMic(bool muted) void LLVoiceClient::setUserPTTState(bool ptt) { + if (ptt) + { + LLUIUsage::instance().logCommand("Agent.EnableMicrophone"); + } mUserPTTState = ptt; updateMicMuteLogic(); mMicroChangedSignal(); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index cf527a4464..246883b611 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -95,6 +95,7 @@ struct LLVoiceVersionInfo { std::string serverType; std::string serverVersion; + std::string mBuildVersion; }; ////////////////////////////////// diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 19036a3f77..ac6369e4e2 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -690,6 +690,10 @@ void LLVivoxVoiceClient::voiceControlCoro() // surviving longer than LLVivoxVoiceClient voiceControlStateMachine(state); } + catch (const LLCoros::Stop&) + { + LL_DEBUGS("LLVivoxVoiceClient") << "Received a shutdown exception" << LL_ENDL; + } catch (const LLContinueError&) { LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient"); @@ -1606,13 +1610,33 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo() } else { - LL_WARNS("Voice") << "No voice channel credentials" << LL_ENDL; - + LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (channel != NULL) + { + if (channel->getSessionName().empty() && channel->getSessionID().isNull()) + { + if (LLViewerParcelMgr::getInstance()->allowAgentVoice()) + { + LL_WARNS("Voice") << "No channel credentials for default channel" << LL_ENDL; + } + } + else + { + LL_WARNS("Voice") << "No voice channel credentials" << LL_ENDL; + } + } } } else { - LL_WARNS("Voice") << "No voice credentials" << LL_ENDL; + if (LLViewerParcelMgr::getInstance()->allowAgentVoice()) + { + LL_WARNS("Voice") << "No voice credentials" << LL_ENDL; + } + else + { + LL_DEBUGS("Voice") << "No voice credentials" << LL_ENDL; + } } // set the spatial channel. If no voice credentials or uri are @@ -4572,6 +4596,23 @@ void LLVivoxVoiceClient::sessionNotificationEvent(std::string &sessionHandle, st } } +void LLVivoxVoiceClient::voiceServiceConnectionStateChangedEvent(int statusCode, std::string &statusString, std::string &build_id) +{ + // We don't generally need to process this. However, one occurence is when we first connect, and so it is the + // earliest opportunity to learn what we're connected to. + if (statusCode) + { + LL_WARNS("Voice") << "VoiceServiceConnectionStateChangedEvent statusCode: " << statusCode << + "statusString: " << statusString << LL_ENDL; + return; + } + if (build_id.empty()) + { + return; + } + mVoiceVersion.mBuildVersion = build_id; +} + void LLVivoxVoiceClient::auxAudioPropertiesEvent(F32 energy) { LL_DEBUGS("VoiceEnergy") << "got energy " << energy << LL_ENDL; @@ -4758,7 +4799,7 @@ void LLVivoxVoiceClient::sessionState::VerifySessions() if ((*it).expired()) { LL_WARNS("Voice") << "Expired session found! removing" << LL_ENDL; - mSession.erase(it++); + it = mSession.erase(it); } else ++it; @@ -6815,7 +6856,7 @@ void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id) if (list_iter->second == id) { LL_DEBUGS("VoiceFont") << "Removing " << id << " from the voice font list." << LL_ENDL; - mVoiceFontList.erase(list_iter++); + list_iter = mVoiceFontList.erase(list_iter); mVoiceFontListDirty = true; } else @@ -7554,6 +7595,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag) connectorHandle = string; else if (!stricmp("VersionID", tag)) versionID = string; + else if (!stricmp("Version", tag)) + mBuildID = string; else if (!stricmp("AccountHandle", tag)) accountHandle = string; else if (!stricmp("State", tag)) @@ -7856,7 +7899,8 @@ void LLVivoxProtocolParser::processResponse(std::string tag) // We don't need to process this, but we also shouldn't warn on it, since that confuses people. } else if (!stricmp(eventTypeCstr, "VoiceServiceConnectionStateChangedEvent")) - { // Yet another ignored event + { + LLVivoxVoiceClient::getInstance()->voiceServiceConnectionStateChangedEvent(statusCode, statusString, mBuildID); } else if (!stricmp(eventTypeCstr, "AudioDeviceHotSwapEvent")) { diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index cf30a4e86a..ebc3a62c35 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -465,6 +465,7 @@ protected: void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType); void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString); void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy); + void voiceServiceConnectionStateChangedEvent(int statusCode, std::string &statusString, std::string &build_id); void auxAudioPropertiesEvent(F32 energy); void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString); void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType); @@ -969,6 +970,7 @@ protected: std::string actionString; std::string connectorHandle; std::string versionID; + std::string mBuildID; std::string accountHandle; std::string sessionHandle; std::string sessionGroupHandle; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 068e8a131d..f3affbeb33 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -845,9 +845,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); - U32 index_count = 0; - U32 vertex_count = 0; - group->clearDrawMap(); LLVertexBuffer* buffer = group->mVertexBuffer; @@ -913,9 +910,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) llassert(facep->getIndicesCount() == 6); - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - S32 idx = draw_vec.size()-1; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bae3d540e3..a4e0d367c8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -230,6 +230,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; + mServerDrawableUpdateCount = 0; memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); mMDCImplCount = 0; mLastRiggingInfoLOD = -1; @@ -325,6 +326,9 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, LLColor4U color; const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); + const bool previously_volume_changed = mVolumeChanged; + const bool previously_face_mapping_changed = mFaceMappingChanged; + const bool previously_color_changed = mColorChanged; // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); @@ -548,9 +552,31 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // ...and clean up any media impls cleanUpMediaImpls(); + if (( + (mVolumeChanged && !previously_volume_changed) || + (mFaceMappingChanged && !previously_face_mapping_changed) || + (mColorChanged && !previously_color_changed) + ) + && !mLODChanged) { + onDrawableUpdateFromServer(); + } + return retval; } +// Called when a volume, material, etc is updated by the server, possibly by a +// script. If this occurs too often for this object, mark it as active so that +// it doesn't disrupt the octree/render batches, thereby potentially causing a +// big performance penalty. +void LLVOVolume::onDrawableUpdateFromServer() +{ + constexpr U32 UPDATES_UNTIL_ACTIVE = 8; + ++mServerDrawableUpdateCount; + if (mDrawable && !mDrawable->isActive() && mServerDrawableUpdateCount > UPDATES_UNTIL_ACTIVE) + { + mDrawable->makeActive(); + } +} void LLVOVolume::animateTextures() { @@ -1670,7 +1696,7 @@ void LLVOVolume::regenFaces() } } -BOOL LLVOVolume::genBBoxes(BOOL force_global) +BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds) { LL_PROFILE_ZONE_SCOPED; BOOL res = TRUE; @@ -1689,7 +1715,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) // updates needed, set REBUILD_RIGGED accordingly. // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. - updateRiggedVolume(); + updateRiggedVolume(false); } LLVolume* volume = mRiggedVolume; @@ -1746,20 +1772,9 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) } } - bool rigged = false; - - if (!isAnimatedObject()) - { - rigged = isRiggedMesh() && isAttachment(); - } - else - { - rigged = isRiggedMesh() && getControlAvatar() && getControlAvatar()->mPlaying; - } - if (any_valid_boxes) { - if (rebuild) + if (rebuild && should_update_octree_bounds) { //get the Avatar associated with this object if it's rigged LLVOAvatar* avatar = nullptr; @@ -1921,7 +1936,7 @@ void LLVOVolume::updateRelativeXform(bool force_identity) } } -bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &should_update_octree_bounds) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; bool regen_faces = false; @@ -1953,6 +1968,9 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) } compiled = TRUE; + // new_lod > old_lod breaks a feedback loop between LOD updates and + // bounding box updates. + should_update_octree_bounds = should_update_octree_bounds || mSculptChanged || new_lod > old_lod; sNumLODChanges += new_num_faces; if ((S32)getNumTEs() != getVolume()->getNumFaces()) @@ -1991,7 +2009,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) { - updateRiggedVolume(); + updateRiggedVolume(false); genBBoxes(FALSE); mDrawable->clearState(LLDrawable::REBUILD_RIGGED); } @@ -2012,8 +2030,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) group->dirtyMesh(); } - BOOL compiled = FALSE; - updateRelativeXform(); if (mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -2021,49 +2037,55 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } + BOOL compiled = FALSE; + // This should be true in most cases, unless we're sure no octree update is + // needed. + BOOL should_update_octree_bounds = bool(getRiggedVolume()) || mDrawable->isState(LLDrawable::REBUILD_POSITION) || !mDrawable->getSpatialExtents()->isFinite3(); + if (mVolumeChanged || mFaceMappingChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); bool was_regen_faces = false; + should_update_octree_bounds = true; if (mVolumeChanged) { - was_regen_faces = lodOrSculptChanged(drawable, compiled); + was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); drawable->setState(LLDrawable::REBUILD_VOLUME); } else if (mSculptChanged || mLODChanged || mColorChanged) { compiled = TRUE; - was_regen_faces = lodOrSculptChanged(drawable, compiled); + was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); } if (!was_regen_faces) { regenFaces(); } - - genBBoxes(FALSE); } else if (mLODChanged || mSculptChanged || mColorChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); compiled = TRUE; - lodOrSculptChanged(drawable, compiled); + lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) { updateRiggedVolume(false); } - genBBoxes(FALSE); } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else { compiled = TRUE; // All it did was move or we changed the texture coordinate offset - genBBoxes(FALSE); } + // Generate bounding boxes if needed, and update the object's size in the + // octree + genBBoxes(FALSE, should_update_octree_bounds); + // Update face flags updateFaceFlags(); @@ -4593,7 +4615,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& { if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) { - updateRiggedVolume(true); + updateRiggedVolume(true, LLRiggedVolume::DO_NOT_UPDATE_FACES); volume = mRiggedVolume; transform = false; } @@ -4668,6 +4690,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& continue; } + // This calculates the bounding box of the skinned mesh from scratch. It's actually quite expensive, but not nearly as expensive as building a full octree. + // rebuild_face_octrees = false because an octree for this face will be built later only if needed for narrow phase picking. + updateRiggedVolume(true, i, false); face_hit = volume->lineSegmentIntersect(local_start, local_end, i, &p, &tc, &n, &tn); @@ -4791,13 +4816,13 @@ void LLVOVolume::clearRiggedVolume() } } -void LLVOVolume::updateRiggedVolume(bool force_update) +void LLVOVolume::updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index, bool rebuild_face_octrees) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; //Update mRiggedVolume to match current animation frame of avatar. //Also update position/size in octree. - if ((!force_update) && (!treatAsRigged())) + if ((!force_treat_as_rigged) && (!treatAsRigged())) { clearRiggedVolume(); @@ -4826,10 +4851,10 @@ void LLVOVolume::updateRiggedVolume(bool force_update) updateRelativeXform(); } - mRiggedVolume->update(skin, avatar, volume); + mRiggedVolume->update(skin, avatar, volume, face_index, rebuild_face_octrees); } -void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume, FaceIndex face_index, bool rebuild_face_octrees) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; bool copy = false; @@ -4860,7 +4885,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if (is_paused) { S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); - if (frames_paused > 2) + if (frames_paused > 1) { return; } @@ -4879,7 +4904,24 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons S32 rigged_vert_count = 0; S32 rigged_face_count = 0; LLVector4a box_min, box_max; - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + S32 face_begin; + S32 face_end; + if (face_index == DO_NOT_UPDATE_FACES) + { + face_begin = 0; + face_end = 0; + } + else if (face_index == UPDATE_ALL_FACES) + { + face_begin = 0; + face_end = volume->getNumVolumeFaces(); + } + else + { + face_begin = face_index; + face_end = face_begin + 1; + } + for (S32 i = face_begin; i < face_end; ++i) { const LLVolumeFace& vol_face = volume->getVolumeFace(i); @@ -4964,15 +5006,10 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } + if (rebuild_face_octrees) { - delete dst_face.mOctree; - dst_face.mOctree = NULL; - - LLVector4a size; - size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); - size.splat(size.getLength3().getF32()*0.5f); - - dst_face.createOctree(1.f); + dst_face.destroyOctree(); + dst_face.createOctree(); } } } @@ -5495,6 +5532,7 @@ static inline void add_face(T*** list, U32* count, T* face) void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -5652,7 +5690,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { avatar->addAttachmentOverridesForObject(vobj, NULL, false); } - + // Standard rigged mesh attachments: bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to @@ -5696,7 +5734,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (facep->isState(LLFace::RIGGED)) { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); if (pool) { pool->removeFace(facep); @@ -5882,7 +5920,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { drawablep->clearState(LLDrawable::RIGGED); - vobj->updateRiggedVolume(); + vobj->updateRiggedVolume(false); } } } @@ -5992,7 +6030,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL)) { LLVOVolume* vobj = drawablep->getVOVolume(); @@ -6026,8 +6064,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { - llassert(!face->isState(LLFace::RIGGED)); - if (!face->getGeometryVolume(*volume, face->getTEOffset(), vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) { //something's gone wrong with the vertex buffer accounting, rebuild this group @@ -6156,7 +6192,6 @@ struct CompareBatchBreakerRigged } }; - U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL rigged) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4cb7a5481c..01ad40274b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -65,7 +65,10 @@ public: { } - void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume); + using FaceIndex = S32; + static const FaceIndex UPDATE_ALL_FACES = -1; + static const FaceIndex DO_NOT_UPDATE_FACES = -2; + void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume, FaceIndex face_index = UPDATE_ALL_FACES, bool rebuild_face_octrees = true); std::string mExtraDebugText; }; @@ -232,7 +235,7 @@ public: void updateFaceFlags(); void regenFaces(); - BOOL genBBoxes(BOOL force_global); + BOOL genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = TRUE); void preRebuild(); virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); @@ -362,8 +365,9 @@ public: S32 getMDCImplCount() { return mMDCImplCount; } - //rigged volume update (for raycasting) - void updateRiggedVolume(bool force_update = false); + // Rigged volume update (for raycasting) + // By default, this updates the bounding boxes of all the faces and builds an octree for precise per-triangle raycasting + void updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index = LLRiggedVolume::UPDATE_ALL_FACES, bool rebuild_face_octrees = true); LLRiggedVolume* getRiggedVolume(); //returns true if volume should be treated as a rigged volume @@ -386,13 +390,14 @@ protected: static S32 mRenderComplexity_last; static S32 mRenderComplexity_current; + void onDrawableUpdateFromServer(); void requestMediaDataUpdate(bool isNew); void cleanUpMediaImpls(); void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; void removeMediaImpl(S32 texture_index) ; private: - bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); + bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &shouldUpdateOctreeBounds); public: @@ -424,6 +429,7 @@ private: LLPointer<LLViewerFetchedTexture> mLightTexture; media_list_t mMediaImplList; S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 + U32 mServerDrawableUpdateCount; S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; S32 mMDCImplCount; diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index ff899fe895..3cc82621c4 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -36,7 +36,7 @@ #include "llstring.h" // newview -#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions +#include "llavataractions.h" // for getProfileURL() #include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals #include "llcorehttputil.h" diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 8abb49fba8..aa32ef04b2 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -763,14 +763,13 @@ void LLWorld::updateParticles() void LLWorld::renderPropertyLines() { S32 region_count = 0; - S32 vertex_count = 0; for (region_list_t::iterator iter = mVisibleRegionList.begin(); iter != mVisibleRegionList.end(); ++iter) { LLViewerRegion* regionp = *iter; region_count++; - vertex_count += regionp->renderPropertyLines(); + regionp->renderPropertyLines(); } } @@ -778,7 +777,6 @@ void LLWorld::renderPropertyLines() void LLWorld::updateNetStats() { F64Bits bits; - U32 packets = 0; for (region_list_t::iterator iter = mActiveRegionList.begin(); iter != mActiveRegionList.end(); ++iter) @@ -786,7 +784,6 @@ void LLWorld::updateNetStats() LLViewerRegion* regionp = *iter; regionp->updateNetStats(); bits += regionp->mBitsReceived; - packets += llfloor( regionp->mPacketsReceived ); regionp->mBitsReceived = (F32Bits)0.f; regionp->mPacketsReceived = 0.f; } diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 59ac4554d7..6e994b4e68 100644..100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -58,9 +58,15 @@ #include "llglheaders.h" +// # Constants +static const F32 MAP_DEFAULT_SCALE = 128.f; +static const F32 MAP_ITERP_TIME_CONSTANT = 0.75f; +static const F32 MAP_ZOOM_ACCELERATION_TIME = 0.3f; +static const F32 MAP_ZOOM_MAX_INTERP = 0.5f; +static const F32 MAP_SCALE_SNAP_THRESHOLD = 0.005f; + // Basically a C++ implementation of the OCEAN_COLOR defined in mapstitcher.py // Please ensure consistency between those 2 files (TODO: would be better to get that color from an asset source...) -// # Constants // OCEAN_COLOR = "#1D475F" const F32 OCEAN_RED = (F32)(0x1D)/255.f; const F32 OCEAN_GREEN = (F32)(0x47)/255.f; @@ -92,14 +98,12 @@ LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL; -F32 LLWorldMapView::sPanX = 0.f; -F32 LLWorldMapView::sPanY = 0.f; -F32 LLWorldMapView::sTargetPanX = 0.f; -F32 LLWorldMapView::sTargetPanY = 0.f; S32 LLWorldMapView::sTrackingArrowX = 0; S32 LLWorldMapView::sTrackingArrowY = 0; bool LLWorldMapView::sVisibleTilesLoaded = false; -F32 LLWorldMapView::sMapScale = 128.f; +F32 LLWorldMapView::sMapScaleSetting = MAP_DEFAULT_SCALE; +LLVector2 LLWorldMapView::sZoomPivot = LLVector2(0.0f, 0.0f); +LLFrameTimer LLWorldMapView::sZoomTimer = LLFrameTimer(); std::map<std::string,std::string> LLWorldMapView::sStringsMap; @@ -166,20 +170,27 @@ void LLWorldMapView::cleanupClass() sForSaleAdultImage = NULL; } -LLWorldMapView::LLWorldMapView() -: LLPanel(), - mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ), - mItemPicked(FALSE), - mPanning( FALSE ), - mMouseDownPanX( 0 ), - mMouseDownPanY( 0 ), - mMouseDownX( 0 ), - mMouseDownY( 0 ), - mSelectIDStart(0) +LLWorldMapView::LLWorldMapView() : + LLPanel(), + mBackgroundColor(LLColor4(OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f)), + mItemPicked(FALSE), + mPanX(0.f), + mPanY(0.f), + mTargetPanX(0.f), + mTargetPanY(0.f), + mPanning(FALSE), + mMouseDownPanX(0), + mMouseDownPanY(0), + mMouseDownX(0), + mMouseDownY(0), + mSelectIDStart(0), + mMapScale(0.f), + mTargetMapScale(0.f), + mMapIterpTime(MAP_ITERP_TIME_CONSTANT) { - //LL_INFOS("WorldMap") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; + // LL_INFOS("WorldMap") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; - clearLastClick(); + clearLastClick(); } BOOL LLWorldMapView::postBuild() @@ -210,6 +221,9 @@ BOOL LLWorldMapView::postBuild() mTextBoxNorthEast ->reshapeToFitText(); mTextBoxSouthWest->reshapeToFitText(); mTextBoxNorthWest ->reshapeToFitText(); + + sZoomTimer.stop(); + setScale(sMapScaleSetting, true); return true; } @@ -227,59 +241,111 @@ void LLWorldMapView::cleanupTextures() { } +void LLWorldMapView::zoom(F32 zoom) +{ + mTargetMapScale = scaleFromZoom(zoom); + if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) + { + sZoomPivot = LLVector2(0, 0); + sZoomTimer.start(); + } +} -// static -void LLWorldMapView::setScale( F32 scale ) +void LLWorldMapView::zoomWithPivot(F32 zoom, S32 x, S32 y) { - if (scale != sMapScale) - { - F32 old_scale = sMapScale; + mTargetMapScale = scaleFromZoom(zoom); + sZoomPivot = LLVector2(x, y); + if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) + { + sZoomTimer.start(); + } +} - sMapScale = scale; - if (sMapScale <= 0.f) - { - sMapScale = 0.1f; - } +F32 LLWorldMapView::getZoom() { return LLWorldMapView::zoomFromScale(mMapScale); } - F32 ratio = (scale / old_scale); - sPanX *= ratio; - sPanY *= ratio; - sTargetPanX = sPanX; - sTargetPanY = sPanY; - sVisibleTilesLoaded = false; - } -} +F32 LLWorldMapView::getScale() { return mMapScale; } +// static +void LLWorldMapView::setScaleSetting(F32 scaleSetting) { sMapScaleSetting = scaleSetting; } + +// static +F32 LLWorldMapView::getScaleSetting() { return sMapScaleSetting; } + +void LLWorldMapView::setScale(F32 scale, bool snap) +{ + if (scale != mMapScale) + { + F32 old_scale = mMapScale; + + mMapScale = scale; + // Set the scale used when saving the setting + sMapScaleSetting = scale; + if (mMapScale <= 0.f) + { + mMapScale = 0.1f; + } + mMapIterpTime = MAP_ITERP_TIME_CONSTANT; + F32 ratio = (scale / old_scale); + mPanX *= ratio; + mPanY *= ratio; + mTargetPanX = mPanX; + mTargetPanY = mPanY; + sVisibleTilesLoaded = false; + + // If we are zooming relative to somewhere else rather than the center of the map, compensate for the difference in panning here + if (!sZoomPivot.isExactlyZero()) + { + LLVector2 relative_pivot; + relative_pivot.mV[VX] = sZoomPivot.mV[VX] - (getRect().getWidth() / 2.0); + relative_pivot.mV[VY] = sZoomPivot.mV[VY] - (getRect().getHeight() / 2.0); + LLVector2 zoom_pan_offset = relative_pivot - (relative_pivot * scale / old_scale); + mPanX += zoom_pan_offset.mV[VX]; + mPanY += zoom_pan_offset.mV[VY]; + mTargetPanX += zoom_pan_offset.mV[VX]; + mTargetPanY += zoom_pan_offset.mV[VY]; + } + } + + if (snap) + { + mTargetMapScale = scale; + } +} // static -void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y ) +void LLWorldMapView::translatePan(S32 delta_x, S32 delta_y) { - sPanX += delta_x; - sPanY += delta_y; - sTargetPanX = sPanX; - sTargetPanY = sPanY; - sVisibleTilesLoaded = false; + mPanX += delta_x; + mPanY += delta_y; + mTargetPanX = mPanX; + mTargetPanY = mPanY; + sVisibleTilesLoaded = false; } // static -void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) +void LLWorldMapView::setPan(S32 x, S32 y, BOOL snap) { - sTargetPanX = (F32)x; - sTargetPanY = (F32)y; - if (snap) - { - sPanX = sTargetPanX; - sPanY = sTargetPanY; - } - sVisibleTilesLoaded = false; + mMapIterpTime = MAP_ITERP_TIME_CONSTANT; + mTargetPanX = (F32) x; + mTargetPanY = (F32) y; + if (snap) + { + mPanX = mTargetPanX; + mPanY = mTargetPanY; + } + sVisibleTilesLoaded = false; } -bool LLWorldMapView::showRegionInfo() +// static +void LLWorldMapView::setPanWithInterpTime(S32 x, S32 y, BOOL snap, F32 interp_time) { - return (LLWorldMipmap::scaleToLevel(sMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); + setPan(x, y, snap); + mMapIterpTime = interp_time; } +bool LLWorldMapView::showRegionInfo() { return (LLWorldMipmap::scaleToLevel(mMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); } + /////////////////////////////////////////////////////////////////////////////////// // HELPERS @@ -300,9 +366,28 @@ void LLWorldMapView::draw() mVisibleRegions.clear(); - // animate pan if necessary - sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(0.1f)); - sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(0.1f)); + // animate pan if necessary + mPanX = lerp(mPanX, mTargetPanX, LLSmoothInterpolation::getInterpolant(mMapIterpTime)); + mPanY = lerp(mPanY, mTargetPanY, LLSmoothInterpolation::getInterpolant(mMapIterpTime)); + + //RN: snaps to zoom value because interpolation caused jitter in the text rendering + if (!sZoomTimer.getStarted() && mMapScale != mTargetMapScale) + { + sZoomTimer.start(); + } + bool snap_scale = false; + F32 interp = llmin(MAP_ZOOM_MAX_INTERP, sZoomTimer.getElapsedTimeF32() / MAP_ZOOM_ACCELERATION_TIME); + F32 current_zoom_val = zoomFromScale(mMapScale); + F32 target_zoom_val = zoomFromScale(mTargetMapScale); + F32 new_zoom_val = lerp(current_zoom_val, target_zoom_val, interp); + if (abs(new_zoom_val - current_zoom_val) < MAP_SCALE_SNAP_THRESHOLD) + { + sZoomTimer.stop(); + snap_scale = true; + new_zoom_val = target_zoom_val; + } + F32 map_scale = scaleFromZoom(new_zoom_val); + setScale(map_scale, snap_scale); const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); @@ -310,7 +395,7 @@ void LLWorldMapView::draw() const F32 half_height = F32(height) / 2.0f; LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + S32 level = LLWorldMipmap::scaleToLevel(mMapScale); LLLocalClipRect clip(getLocalRect()); { @@ -347,15 +432,15 @@ void LLWorldMapView::draw() // Find x and y position relative to camera's center. LLVector3d rel_region_pos = origin_global - camera_global; - F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; + F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * mMapScale; + F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * mMapScale; // Coordinates of the sim in pixels in the UI panel // When the view isn't panned, 0,0 = center of rectangle - F32 bottom = sPanY + half_height + relative_y; - F32 left = sPanX + half_width + relative_x; - F32 top = bottom + sMapScale ; - F32 right = left + sMapScale ; + F32 bottom = mPanY + half_height + relative_y; + F32 left = mPanX + half_width + relative_x; + F32 top = bottom + mMapScale ; + F32 right = left + mMapScale ; // Discard if region is outside the screen rectangle (not visible on screen) if ((top < 0.f) || (bottom > height) || @@ -416,7 +501,7 @@ void LLWorldMapView::draw() if (overlayimage) { // Inform the fetch mechanism of the size we need - S32 draw_size = ll_round(sMapScale); + S32 draw_size = ll_round(mMapScale); overlayimage->setKnownDrawSize(ll_round(draw_size * LLUI::getScaleFactor().mV[VX]), ll_round(draw_size * LLUI::getScaleFactor().mV[VY])); // Draw something whenever we have enough info if (overlayimage->hasGLTexture()) @@ -444,7 +529,7 @@ void LLWorldMapView::draw() } // Draw the region name in the lower left corner - if (sMapScale >= DRAW_TEXT_THRESHOLD) + if (mMapScale >= DRAW_TEXT_THRESHOLD) { LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD)); std::string mesg; @@ -464,7 +549,7 @@ void LLWorldMapView::draw() LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, S32_MAX, //max_chars - sMapScale, //max_pixels + mMapScale, //max_pixels NULL, TRUE); //use ellipses } @@ -591,7 +676,7 @@ void LLWorldMapView::setVisible(BOOL visible) void LLWorldMapView::drawMipmap(S32 width, S32 height) { // Compute the level of the mipmap to use for the current scale level - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + S32 level = LLWorldMipmap::scaleToLevel(mMapScale); // Set the tile boost level so that unused tiles get to 0 LLWorldMap::getInstance()->equalizeBoostLevels(); @@ -874,7 +959,7 @@ void LLWorldMapView::drawAgents() void LLWorldMapView::drawFrustum() { // Draw frustum - F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; + F32 meters_to_pixels = mMapScale/ REGION_WIDTH_METERS; F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); @@ -884,8 +969,8 @@ void LLWorldMapView::drawFrustum() F32 half_width_pixels = half_width_meters * meters_to_pixels; // Compute the frustum coordinates. Take the UI scale into account. - F32 ctr_x = ((getLocalRect().getWidth() * 0.5f + sPanX) * LLUI::getScaleFactor().mV[VX]); - F32 ctr_y = ((getLocalRect().getHeight() * 0.5f + sPanY) * LLUI::getScaleFactor().mV[VY]); + F32 ctr_x = ((getLocalRect().getWidth() * 0.5f + mPanX) * LLUI::getScaleFactor().mV[VX]); + F32 ctr_y = ((getLocalRect().getHeight() * 0.5f + mPanY) * LLUI::getScaleFactor().mV[VY]); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -942,13 +1027,13 @@ LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles - pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS; - pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS; + pos_local.mV[VX] *= mMapScale / REGION_WIDTH_METERS; + pos_local.mV[VY] *= mMapScale / REGION_WIDTH_METERS; // leave Z component in meters - pos_local.mV[VX] += getRect().getWidth() / 2 + sPanX; - pos_local.mV[VY] += getRect().getHeight() / 2 + sPanY; + pos_local.mV[VX] += getRect().getWidth() / 2 + mPanX; + pos_local.mV[VY] += getRect().getHeight() / 2 + mPanY; return pos_local; } @@ -1019,12 +1104,12 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& // If you change this, then you need to change LLTracker::getTrackedPositionGlobal() as well LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) { - x -= llfloor((getRect().getWidth() / 2 + sPanX)); - y -= llfloor((getRect().getHeight() / 2 + sPanY)); + x -= llfloor((getRect().getWidth() / 2 + mPanX)); + y -= llfloor((getRect().getHeight() / 2 + mPanY)); LLVector3 pos_local( (F32)x, (F32)y, 0.f ); - pos_local *= ( REGION_WIDTH_METERS / sMapScale ); + pos_local *= ( REGION_WIDTH_METERS / mMapScale ); LLVector3d pos_global; pos_global.setVec( pos_local ); @@ -1481,7 +1566,7 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, LLWorldMap::getInstance()->cancelTracking(); - S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + S32 level = LLWorldMipmap::scaleToLevel(mMapScale); // If the zoom level is not too far out already, test hits if (level <= DRAW_SIMINFO_THRESHOLD) { @@ -1598,8 +1683,8 @@ BOOL LLWorldMapView::handleMouseDown( S32 x, S32 y, MASK mask ) { gFocusMgr.setMouseCapture( this ); - mMouseDownPanX = ll_round(sPanX); - mMouseDownPanY = ll_round(sPanY); + mMouseDownPanX = ll_round(mPanX); + mMouseDownPanY = ll_round(mPanY); mMouseDownX = x; mMouseDownY = y; sHandledLastClick = TRUE; @@ -1614,8 +1699,8 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) { // restore mouse cursor S32 local_x, local_y; - local_x = mMouseDownX + llfloor(sPanX - mMouseDownPanX); - local_y = mMouseDownY + llfloor(sPanY - mMouseDownPanY); + local_x = mMouseDownX + llfloor(mPanX - mMouseDownPanX); + local_y = mMouseDownY + llfloor(mPanY - mMouseDownPanY); LLRect clip_rect = getRect(); clip_rect.stretch(-8); clip_rect.clipPointToRect(mMouseDownX, mMouseDownY, local_x, local_y); @@ -1643,7 +1728,7 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) void LLWorldMapView::updateVisibleBlocks() { - if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD) + if (LLWorldMipmap::scaleToLevel(mMapScale) > DRAW_SIMINFO_THRESHOLD) { // If we're zoomed out too much, we just don't load all those sim info: too much! return; @@ -1659,16 +1744,16 @@ void LLWorldMapView::updateVisibleBlocks() const F32 half_height = F32(height) / 2.0f; // Compute center into sim grid coordinates - S32 world_center_x = S32((-sPanX / sMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); - S32 world_center_y = S32((-sPanY / sMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); + S32 world_center_x = S32((-mPanX / mMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); + S32 world_center_y = S32((-mPanY / mMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); // Compute the boundaries into sim grid coordinates - S32 world_left = world_center_x - S32(half_width / sMapScale) - 1; - S32 world_right = world_center_x + S32(half_width / sMapScale) + 1; - S32 world_bottom = world_center_y - S32(half_height / sMapScale) - 1; - S32 world_top = world_center_y + S32(half_height / sMapScale) + 1; + S32 world_left = world_center_x - S32(half_width / mMapScale) - 1; + S32 world_right = world_center_x + S32(half_width / mMapScale) + 1; + S32 world_bottom = world_center_y - S32(half_height / mMapScale) - 1; + S32 world_top = world_center_y + S32(half_height / mMapScale) + 1; - //LL_INFOS("WorldMap") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL; + //LL_INFOS("WorldMap") << "LLWorldMapView::updateVisibleBlocks() : mMapScale = " << mMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL; LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top); } @@ -1689,10 +1774,10 @@ BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask ) F32 delta_y = (F32)(gViewerWindow->getCurrentMouseDY()); // Set pan to value at start of drag + offset - sPanX += delta_x; - sPanY += delta_y; - sTargetPanX = sPanX; - sTargetPanY = sPanY; + mPanX += delta_x; + mPanY += delta_y; + mTargetPanX = mPanX; + mTargetPanY = mPanY; gViewerWindow->moveCursorToCenter(); } @@ -1789,4 +1874,8 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) return FALSE; } +// static +F32 LLWorldMapView::scaleFromZoom(F32 zoom) { return exp2(zoom) * 256.0f; } +// static +F32 LLWorldMapView::zoomFromScale(F32 scale) { return log2(scale / 256.f); } diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index a2a6dc53fb..ce8af76a82 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -67,12 +67,22 @@ public: bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track); void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); - // Scale and pan are shared across all instances! (i.e. Terrain and Objects maps are always registered) - static void setScale( F32 scale ); - static void translatePan( S32 delta_x, S32 delta_y ); - static void setPan( S32 x, S32 y, BOOL snap = TRUE ); + // Scale, aka zoom, is shared across all instances! (i.e. Terrain and Objects maps are always registered) + // Zoom is used for UI and will interpolate the map scale over multiple frames. + void zoom(F32 zoom); + void zoomWithPivot(F32 zoom, S32 x, S32 y); + F32 getZoom(); + // Scale is a linear scaling factor of in-world coordinates + F32 getScale(); + // setScaleSetting/getScaleSetting are for the default map setting on login + static void setScaleSetting(F32 scaleSetting); + static F32 getScaleSetting(); + // Pan is in pixels relative to the center of the map. + void translatePan( S32 delta_x, S32 delta_y ); + void setPan( S32 x, S32 y, BOOL snap = TRUE ); + void setPanWithInterpTime(S32 x, S32 y, BOOL snap, F32 interp_time); // Return true if the current scale level is above the threshold for accessing region info - static bool showRegionInfo(); + bool showRegionInfo(); LLVector3 globalPosToView(const LLVector3d& global_pos); LLVector3d viewPosToGlobal(S32 x,S32 y); @@ -153,14 +163,12 @@ public: static LLUIImagePtr sForSaleImage; static LLUIImagePtr sForSaleAdultImage; - static F32 sMapScale; // scale = size of a region in pixels - BOOL mItemPicked; - static F32 sPanX; // in pixels - static F32 sPanY; // in pixels - static F32 sTargetPanX; // in pixels - static F32 sTargetPanY; // in pixels + F32 mPanX; // in pixels + F32 mPanY; // in pixels + F32 mTargetPanX; // in pixels + F32 mTargetPanY; // in pixels static S32 sTrackingArrowX; static S32 sTrackingArrowY; static bool sVisibleTilesLoaded; @@ -194,6 +202,19 @@ public: private: void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right); + + void setScale(F32 scale, bool snap = true); + + static F32 scaleFromZoom(F32 zoom); + static F32 zoomFromScale(F32 scale); + + F32 mMapScale; + F32 mTargetMapScale; + static F32 sMapScaleSetting; + static LLVector2 sZoomPivot; + static LLFrameTimer sZoomTimer; + + F32 mMapIterpTime; }; #endif diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 32c8ce66a0..5c56a1d34f 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -40,6 +40,7 @@ #include "httpoptions.h" #include "httpheaders.h" #include "bufferarray.h" +#include "llversioninfo.h" #include "llviewercontrol.h" // Have to include these last to avoid queue redefinition! @@ -378,6 +379,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); + std::string user_agent = llformat("%s %d.%d.%d (%d)", + LLVersionInfo::instance().getChannel().c_str(), + LLVersionInfo::instance().getMajor(), + LLVersionInfo::instance().getMinor(), + LLVersionInfo::instance().getPatch(), + LLVersionInfo::instance().getBuild()); + + httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + ///* Setting the DNS cache timeout to -1 disables it completely. //This might help with bug #503 */ //httpOpts->setDNSCacheTimeout(-1); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c297f0f080..96ba80dacc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3939,7 +3939,7 @@ void LLPipeline::postSort(LLCamera& camera) } LL_PUSH_CALLSTACKS(); // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. - if (LLFloaterTelehub::renderBeacons()) + if (LLFloaterTelehub::renderBeacons() && !sShadowRender) { LLFloaterTelehub::addBeacons(); } @@ -7238,6 +7238,7 @@ void LLPipeline::doResetVertexBuffers(bool forced) mResetVertexBuffers = false; mCubeVB = NULL; + mDeferredVB = NULL; for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -7271,10 +7272,11 @@ void LLPipeline::doResetVertexBuffers(bool forced) LLPathingLib::getInstance()->cleanupVBOManager(); } LLVOPartGroup::destroyGL(); + gGL.resetVertexBuffer(); SUBSYSTEM_CLEANUP(LLVertexBuffer); - if (LLVertexBuffer::sGLCount > 0) + if (LLVertexBuffer::sGLCount != 0) { LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; } @@ -7295,6 +7297,10 @@ void LLPipeline::doResetVertexBuffers(bool forced) LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + gGL.initVertexBuffer(); + + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); + mDeferredVB->allocateBuffer(8, 0, true); LLVOPartGroup::restoreGL(); } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 7beb013fba..c3ce83e834 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -514,8 +514,8 @@ name="MapFrustumColor" reference="White_10" /> <color - name="MapFrustumRotatingColor" - value="1 1 1 0.2" /> + name="MapParcelOutlineColor" + value="1 1 0 0.5" /> <color name="MapTrackColor" reference="Red" /> @@ -607,10 +607,10 @@ value="0 0 0 1" /> <color name="NetMapGroupOwnAboveWater" - reference="Purple" /> + value="0.85 0 0.85 1" /> <color name="NetMapGroupOwnBelowWater" - value="0.78 0 0.78 1" /> + value="0.63 0 0.63 1" /> <color name="NetMapOtherOwnAboveWater" value="0.24 0.24 0.24 1" /> @@ -619,10 +619,10 @@ value="0.12 0.12 0.12 1" /> <color name="NetMapYouOwnAboveWater" - value="0 1 1 1" /> + value="0 0.85 0.85 1" /> <color name="NetMapYouOwnBelowWater" - value="0 0.78 0.78 1" /> + value="0 0.63 0.63 1" /> <color name="NotifyBoxColor" value="LtGray" /> @@ -886,6 +886,22 @@ name="PanelNotificationListItem" value="0.3 0.3 0.3 .3" /> + <!-- profiles --> + <color + name="StatusUserOnline" + reference="White" /> + <color + name="StatusUserOffline" + reference="LtGray_35" /> + <!-- Groups visible in own profiles --> + <color + name="GroupVisibleInProfile" + reference="TextBgFocusColor" /> + <color + name="GroupHiddenInProfile" + reference="Gray" /> + + <!-- Generic color names (legacy) --> <color name="white" diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png Binary files differnew file mode 100644 index 0000000000..9a81c5f94b --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png Binary files differnew file mode 100644 index 0000000000..88012cf8d1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png Binary files differnew file mode 100644 index 0000000000..ab02e7d42d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png Binary files differnew file mode 100644 index 0000000000..63b4bd2127 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png Binary files differnew file mode 100644 index 0000000000..4200182b0c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png Binary files differnew file mode 100644 index 0000000000..e12887f489 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png diff --git a/indra/newview/skins/default/textures/icons/CopyBright.png b/indra/newview/skins/default/textures/icons/CopyBright.png Binary files differnew file mode 100644 index 0000000000..8d21c47295 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/CopyBright.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png b/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png Binary files differnew file mode 100644 index 0000000000..aeba6b70f7 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png b/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png Binary files differnew file mode 100644 index 0000000000..d668fd8dfa --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png Binary files differnew file mode 100644 index 0000000000..8f8caa10d8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png Binary files differnew file mode 100644 index 0000000000..42a209dda5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png Binary files differnew file mode 100644 index 0000000000..644edf0ef6 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png Binary files differnew file mode 100644 index 0000000000..629c05ecb8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png Binary files differnew file mode 100644 index 0000000000..ecf66c0ee1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png Binary files differnew file mode 100644 index 0000000000..26123938fa --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg Binary files differdeleted file mode 100644 index 3bb7f7183c..0000000000 --- a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg +++ /dev/null diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png Binary files differnew file mode 100644 index 0000000000..3a2ed399b2 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png Binary files differnew file mode 100644 index 0000000000..789f59a491 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png Binary files differnew file mode 100644 index 0000000000..4fb56c389c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png Binary files differnew file mode 100644 index 0000000000..ae04a256a4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png diff --git a/indra/newview/skins/default/textures/map_ui_collapse_icon.png b/indra/newview/skins/default/textures/map_ui_collapse_icon.png Binary files differnew file mode 100644 index 0000000000..e4de49d4af --- /dev/null +++ b/indra/newview/skins/default/textures/map_ui_collapse_icon.png diff --git a/indra/newview/skins/default/textures/map_ui_expand_icon.png b/indra/newview/skins/default/textures/map_ui_expand_icon.png Binary files differnew file mode 100644 index 0000000000..08734b4cc0 --- /dev/null +++ b/indra/newview/skins/default/textures/map_ui_expand_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 03e23b5ba3..4429a1677e 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -67,8 +67,6 @@ with the same filename but different name <texture name="Audio_Off" file_name="icons/Audio_Off.png" preload="false" /> <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" /> - <texture name="Avaline_Icon" file_name="icons/avaline_default_icon.jpg" preload="true" /> - <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" /> <texture name="BackButton_Off" file_name="icons/back_arrow_off.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" /> @@ -191,6 +189,7 @@ with the same filename but different name <texture name="Conv_log_inbox" file_name="icons/Conv_log_inbox.png" preload="false" /> <texture name="Copy" file_name="icons/Copy.png" preload="false" /> + <texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" /> <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> @@ -447,6 +446,13 @@ with the same filename but different name <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" /> <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" /> + <texture name="ClipboardSmallMenu_Disabled" file_name="icons/ClipboardSmallMenu_Disabled.png" preload="false" /> + <texture name="ClipboardSmallMenu_Off" file_name="icons/ClipboardSmallMenu_Off.png" preload="false" /> + <texture name="ClipboardSmallMenu_Press" file_name="icons/ClipboardSmallMenu_Press.png" preload="false" /> + <texture name="ClipboardMenu_Disabled" file_name="icons/ClipboardMenu_Disabled.png" preload="false" /> + <texture name="ClipboardMenu_Off" file_name="icons/ClipboardMenu_Off.png" preload="false" /> + <texture name="ClipboardMenu_Press" file_name="icons/ClipboardMenu_Press.png" preload="false" /> + <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" /> <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" /> <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" /> @@ -505,6 +511,19 @@ with the same filename but different name <texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" /> <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" /> + <texture name="Profile_Group_Visibility_Off" file_name="icons/profile_group_visibility_eye_off.png" preload="true"/> + <texture name="Profile_Group_Visibility_Off_Pressed" file_name="icons/profile_group_visibility_eye_off_pressed.png" preload="true"/> + <texture name="Profile_Group_Visibility_On" file_name="icons/profile_group_visibility_eye_on.png" preload="true"/> + <texture name="Profile_Group_Visibility_On_Pressed" file_name="icons/profile_group_visibility_eye_on_pressed.png" preload="true"/> + <texture name="Profile_Friend_Offline" file_name="icons/Profile_Friend_Offline.png" preload="true"/> + <texture name="Profile_Friend_Online" file_name="icons/Profile_Friend_Online.png" preload="true"/> + <texture name="Profile_Perm_Find_Disabled" file_name="icons/Profile_Perm_Find_Disabled.png" preload="true"/> + <texture name="Profile_Perm_Find_Enabled" file_name="icons/Profile_Perm_Find_Enabled.png" preload="true"/> + <texture name="Profile_Perm_Objects_Disabled" file_name="icons/Profile_Perm_Objects_Disabled.png" preload="true"/> + <texture name="Profile_Perm_Objects_Enabled" file_name="icons/Profile_Perm_Objects_Enabled.png" preload="true"/> + <texture name="Profile_Perm_Online_Disabled" file_name="icons/Profile_Perm_Online_Disabled.png" preload="true"/> + <texture name="Profile_Perm_Online_Enabled" file_name="icons/Profile_Perm_Online_Enabled.png" preload="true"/> + <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" /> @@ -803,6 +822,8 @@ with the same filename but different name <texture name="map_infohub.tga" /> <texture name="map_telehub.tga" /> <texture name="map_track_16.tga" /> + <texture name="map_ui_collapse_icon.png" /> + <texture name="map_ui_expand_icon.png" /> <texture name="notify_caution_icon.tga" /> diff --git a/indra/newview/skins/default/xui/da/panel_me.xml b/indra/newview/skins/default/xui/da/panel_me.xml deleted file mode 100644 index f98ced5f91..0000000000 --- a/indra/newview/skins/default/xui/da/panel_me.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Min profil" name="panel_me"> - <tab_container name="tabs"> - <panel label="MIN PROFIL" name="panel_profile"/> - <panel label="MINE FAVORITTER" name="panel_picks"/> - </tab_container> -</panel> diff --git a/indra/newview/skins/default/xui/da/panel_region_texture.xml b/indra/newview/skins/default/xui/da/panel_region_texture.xml index 45946fd222..c8a3ad328e 100644 --- a/indra/newview/skins/default/xui/da/panel_region_texture.xml +++ b/indra/newview/skins/default/xui/da/panel_region_texture.xml @@ -7,8 +7,8 @@ ukendt </text> <text name="detail_texture_text"> - Terræn teksturer (kræver 512x512, 24 bit .tga filer) - </text> + Terræn teksturer (kræver 1024x1024, 24 bit .tga filer) + </text> <text name="height_text_lbl"> 1 (Lav) </text> diff --git a/indra/newview/skins/default/xui/da/panel_side_tray.xml b/indra/newview/skins/default/xui/da/panel_side_tray.xml deleted file mode 100644 index 66c3e69904..0000000000 --- a/indra/newview/skins/default/xui/da/panel_side_tray.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<!-- Side tray cannot show background because it is always - partially on screen to hold tab buttons. --> -<side_tray name="sidebar"> - <sidetray_tab description="Åbn/luk sidebar" name="sidebar_openclose" tab_title="Åbn/luk sidebar"/> - <sidetray_tab description="Hjem." name="sidebar_home" tab_title="Hjem"> - <panel label="hjem" name="panel_home"/> - </sidetray_tab> - <sidetray_tab description="Redigér din profile og favoritter." name="sidebar_me" tab_title="Min profil"> - <panel_container name="panel_container"> - <panel label="Mig" name="panel_me"/> - </panel_container> - </sidetray_tab> - <sidetray_tab description="Find venner, kontakter og personer tæt på." name="sidebar_people" tab_title="Personer"> - <panel_container name="panel_container"> - <panel label="Gruppe profil" name="panel_group_info_sidetray"/> - <panel label="Blokerede beboere og objekter" name="panel_block_list_sidetray"/> - </panel_container> - </sidetray_tab> - <sidetray_tab description="Find steder du vil hen og steder du har været før." label="Steder" name="sidebar_places" tab_title="Steder"> - <panel label="Steder" name="panel_places"/> - </sidetray_tab> - <sidetray_tab description="Browse din beholdning." name="sidebar_inventory" tab_title="Min beholdning"> - <panel label="Redigér beholdning" name="sidepanel_inventory"/> - </sidetray_tab> - <sidetray_tab description="Ændre dit nuværende udseende" name="sidebar_appearance" tab_title="Mit udseende"> - <panel label="Redigér udseende" name="sidepanel_appearance"/> - </sidetray_tab> -</side_tray> diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml index 5f1bf73f26..e4f99d14e9 100644 --- a/indra/newview/skins/default/xui/da/strings.xml +++ b/indra/newview/skins/default/xui/da/strings.xml @@ -443,9 +443,6 @@ Prøv venligst om lidt igen. <string name="GroupNameNone"> (ingen) </string> - <string name="AvalineCaller"> - Avaline opkalder [ORDER] - </string> <string name="AssetErrorNone"> Ingen fejl </string> diff --git a/indra/newview/skins/default/xui/de/floater_preview_texture.xml b/indra/newview/skins/default/xui/de/floater_preview_texture.xml index eacd11c3e6..b386d0288c 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> In Inventar kopieren </floater.string> - <text name="desc txt"> - Beschreibung: - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - Vorschau Seitenverhältnis - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Mit einem vordefinierten Seitenverhältnis anzeigen"> - <combo_item name="Unconstrained"> - keines - </combo_item> - <combo_item name="1:1" tool_tip="Gruppeninsignien oder Beschreibung"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="[SECOND_LIFE]-Profil"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Anzeigen und Suchergebnisse, Landmarken"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="Über Land"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Profilauswahl"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Verwerfen" name="Discard"/> - <button label="Speichern unter" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Beschreibung: + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + Vorschau Seitenverhältnis + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Mit einem vordefinierten Seitenverhältnis anzeigen"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Verwerfen" name="Discard"/> + <button label="Speichern unter" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_profile.xml b/indra/newview/skins/default/xui/de/floater_profile.xml new file mode 100644 index 0000000000..eb03463930 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="Interessen" name="panel_profile_interests"/> + <panel label="Auswahlen" name="panel_profile_picks"/> + <panel label="Anzeige" name="panel_profile_classifieds"/> + <panel label="Echtes Leben" name="panel_profile_firstlife"/> + <panel label="Hinweise" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Profiländerungen speichern und schließen"/> + <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml index f0152ad8cd..636f320a95 100644 --- a/indra/newview/skins/default/xui/de/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> E-Mail senden </string> + <string name="facebook_progress_str"> + Auf Facebook posten + </string> <string name="profile_progress_str"> Posten </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Speichern auf Computer </string> + <string name="facebook_succeeded_str"> + Bild hochgeladen + </string> <string name="profile_succeeded_str"> Bild hochgeladen </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Auf Computer gespeichert! </string> + <string name="facebook_failed_str"> + Fehler beim Hochladen des Bilds in Ihre Facebook-Chronik. + </string> <string name="profile_failed_str"> Fehler beim Hochladen des Bilds in Ihr Profil. </string> diff --git a/indra/newview/skins/default/xui/de/menu_name_field.xml b/indra/newview/skins/default/xui/de/menu_name_field.xml new file mode 100644 index 0000000000..1d293c9361 --- /dev/null +++ b/indra/newview/skins/default/xui/de/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Anzeigenamen kopieren" name="copy_display"/> + <menu_item_call label="Agent-Namen kopieren" name="copy_name"/> + <menu_item_call label="Agent-ID kopieren" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 359a835630..a72784f70b 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2698,6 +2698,9 @@ Wählen Sie eine kleinere Landfläche. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/de/panel_edit_classified.xml b/indra/newview/skins/default/xui/de/panel_edit_classified.xml index bd270697ea..8adacb4a5f 100644 --- a/indra/newview/skins/default/xui/de/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/de/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="Abbrechen" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_friends.xml b/indra/newview/skins/default/xui/de/panel_facebook_friends.xml index f6a8fda23e..1a0bbc7d30 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_friends.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_friends"> - <string name="facebook_friends_empty" value="Sie haben gegenwärtig keine Facebook-Freunde, die gleichzeitig Einwohner von Second Life sind. Laden Sie Ihre Facebook-Freunde ein, Second Life beizutreten!"/> - <string name="facebook_friends_no_connected" value="Sie sind gegenwärtig nicht mit Facebook verbunden. Um eine Verbindung herzustellen und diese Funktion zu aktivieren, gehen Sie zur Registerkarte „Status“."/> + <string name="facebook_friends_empty" value="Sie haben gegenwärtig keine Facebook-Freunde, die ebenfalls Second Life-Einwohner sind. Laden Sie Ihre Facebook-Freunde ein, Second Life beizutreten!"/> + <string name="facebook_friends_no_connected" value="Sie sind gegenwärtig nicht mit Facebook verbunden. Um eine Verbindung herzustellen und diese Funktion zu aktivieren, wechseln Sie zur Registerkarte "Status"."/> <accordion name="friends_accordion"> <accordion_tab name="tab_second_life_friends" title="SL-Freunde"/> <accordion_tab name="tab_suggested_friends" title="Diese Personen als SL-Freunde hinzufügen"/> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_photo.xml b/indra/newview/skins/default/xui/de/panel_facebook_photo.xml index bc48931129..fac9fe9984 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_photo.xml @@ -2,10 +2,10 @@ <panel name="panel_facebook_photo"> <combo_box name="resolution_combobox" tool_tip="Bildauflösung"> <combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/> - <combo_box.item label="640x480" name="640x480"/> - <combo_box.item label="800x600" name="800x600"/> - <combo_box.item label="1024x768" name="1024x768"/> - <combo_box.item label="1200x630" name="1200x630"/> + <combo_box.item label="640 x 480" name="640x480"/> + <combo_box.item label="800 x 600" name="800x600"/> + <combo_box.item label="1024 x 768" name="1024x768"/> + <combo_box.item label="1200 x 630" name="1200x630"/> </combo_box> <combo_box name="filters_combobox" tool_tip="Bildfilter"> <combo_box.item label="Kein Filter" name="NoFilter"/> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_status.xml b/indra/newview/skins/default/xui/de/panel_facebook_status.xml index 23c9d3b75f..1fefef548e 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_status.xml @@ -13,7 +13,7 @@ </text> </panel> <text name="status_caption_label"> - Was machst du gerade? + Was machen Sie gerade? </text> <button label="Posten" name="post_status_btn"/> <button label="Abbrechen" name="cancel_status_btn"/> diff --git a/indra/newview/skins/default/xui/de/panel_group_general.xml b/indra/newview/skins/default/xui/de/panel_group_general.xml index 9fec5a242d..e50124c37e 100644 --- a/indra/newview/skins/default/xui/de/panel_group_general.xml +++ b/indra/newview/skins/default/xui/de/panel_group_general.xml @@ -46,7 +46,7 @@ Bewegen Sie die Maus über die Optionen, um weitere Informationen anzuzeigen. <check_box label="Jeder kann beitreten" name="open_enrollement" tool_tip="Festlegen, ob der Gruppenbeitritt ohne Einladung zulässig ist."/> <check_box label="Kosten für Beitritt" name="check_enrollment_fee" tool_tip="Festlegen, ob Neumitglieder eine Beitrittsgebühr zahlen müssen"/> <spinner label="L$" name="spin_enrollment_fee" tool_tip="Wenn Beitrittsgebühr aktiviert ist, müssen neue Mitglieder diesen Betrag zahlen."/> - <combo_box name="group_mature_check" tool_tip="Inhaltseinstufungen kennzeichnen die in einer Gruppe zulässigen Inhalte und Verhaltensweisen"> + <combo_box name="group_mature_check" tool_tip="Legt fest, ob Ihre Gruppe als moderat eingestufte Informationen enthält"> <combo_item name="select_mature"> - Inhaltseinstufung auswählen - </combo_item> diff --git a/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml new file mode 100644 index 0000000000..fc911a64df --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Unbekannt"/> + <button name="info_btn" tool_tip="Mehr Infos"/> + <button name="profile_btn" tool_tip="Profil anzeigen"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_me.xml b/indra/newview/skins/default/xui/de/panel_me.xml deleted file mode 100644 index f49446fbbf..0000000000 --- a/indra/newview/skins/default/xui/de/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mein Profil" name="panel_me"> - <panel label="MEINE AUSWAHLEN" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/de/panel_people.xml b/indra/newview/skins/default/xui/de/panel_people.xml index 81de679429..e4a4c1033e 100644 --- a/indra/newview/skins/default/xui/de/panel_people.xml +++ b/indra/newview/skins/default/xui/de/panel_people.xml @@ -40,6 +40,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte]. <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Online"/> <accordion_tab name="tab_all" title="Alle"/> + <accordion_tab name="tab_suggested_friends" title="Potenzielle Freunde"/> </accordion> </panel> <panel label="GRUPPEN" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/de/panel_profile_classified.xml b/indra/newview/skins/default/xui/de/panel_profile_classified.xml new file mode 100644 index 0000000000..5c11a01977 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Moderat + </panel.string> + <panel.string name="type_pg"> + Generelle Inhalte + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] Teleportieren, [MAP] Karten, [PROFILE] Profil + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Aktiviert + </panel.string> + <panel.string name="auto_renew_off"> + Deaktiviert + </panel.string> + <panel.string name="location_notice"> + (wird nach dem Speichern aktualisiert) + </panel.string> + <string name="publish_label"> + Veröffentlichen + </string> + <string name="save_label"> + Speichern + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Standort:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Inhaltsart:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Kategorie:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Erstellungsdatum:"/> + <text_editor name="creation_date" tool_tip="Erstellungsdatum" value="[date]"/> + <text name="price_for_listing_label" value="Preis für Auflistung:"/> + <text_editor name="price_for_listing" tool_tip="Preis für Auflistung."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Klicks:"/> + <text_editor name="click_through_text" tool_tip="Click-Through-Daten" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Autom. erneuern:"/> + <text name="auto_renew" value="Aktiviert"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Beschreibung:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Titel: + </text> + <text name="description_label"> + Beschreibung: + </text> + <text name="location_label"> + Standort: + </text> + <text name="classified_location_edit"> + Laden... + </text> + <button label="Aktuellen Standort verwenden" name="set_to_curr_location_btn"/> + <text name="category_label" value="Kategorie:"/> + <text name="content_type_label" value="Inhaltsart:"/> + <icons_combo_box label="Generelle Inhalte" name="content_type_edit"> + <icons_combo_box.item label="Moderate Inhalte" name="mature_ci" value="Adult"/> + <icons_combo_box.item label="Generelle Inhalte" name="pg_ci" value="PG"/> + </icons_combo_box> + <check_box label="Jede Woche automatisch erneuern" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Preis für Auflistung:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Preis für Auflistung." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Teleportieren" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Karte" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Bearbeiten" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Abbrechen" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml new file mode 100644 index 0000000000..83549cb138 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anzeige" name="panel_profile_classifieds"> + <string name="no_classifieds" value="Keine Anzeigen"/> + <button label="Neu..." name="new_btn"/> + <button label="Löschen..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Laden... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/de/floater_picks.xml b/indra/newview/skins/default/xui/de/panel_profile_firstlife.xml index 2521920e83..0f65090209 100644 --- a/indra/newview/skins/default/xui/de/floater_picks.xml +++ b/indra/newview/skins/default/xui/de/panel_profile_firstlife.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Auswahlen"/> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/de/panel_profile_interests.xml b/indra/newview/skins/default/xui/de/panel_profile_interests.xml new file mode 100644 index 0000000000..0f36f76aa0 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interessen" name="panel_profile_interests"> + <text name="I Want To:"> + Ich möchte: + </text> + <check_box label="Erstellen" name="chk0"/> + <check_box label="Erkunden" name="chk1"/> + <check_box label="Treffen" name="chk2"/> + <check_box label="Angestellt werden" name="chk6"/> + <check_box label="Gruppe" name="chk3"/> + <check_box label="Kaufen" name="chk4"/> + <check_box label="Verkaufen" name="chk5"/> + <check_box label="Anstellen" name="chk7"/> + <line_editor name="want_to_edit"> + (wird geladen...) + </line_editor> + <text name="Skills:"> + Fähigkeiten: + </text> + <check_box label="Texturen" name="schk0"/> + <check_box label="Architektur" name="schk1"/> + <check_box label="Modellierung" name="schk3"/> + <check_box label="Eventplanung" name="schk2"/> + <check_box label="Scripting" name="schk4"/> + <check_box label="Benutzerdefinierte Charaktere" name="schk5"/> + <line_editor name="skills_edit"> + (wird geladen...) + </line_editor> + <text name="Languages:"> + Sprachen: + </text> + <line_editor name="languages_edit"> + (wird geladen...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_notes.xml b/indra/newview/skins/default/xui/de/panel_profile_notes.xml new file mode 100644 index 0000000000..05c46ff858 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anmerkungen & Privatsphäre" name="panel_notes"> + <text name="status_message" value="Private Anmerkungen zu diesem Avatar:"/> + <text name="status_message2" value="Dieser Avatar darf:"/> + <check_box label="Sehen, wenn ich online bin" name="status_check"/> + <check_box label="Mich auf der Weltkarte sehen" name="map_check"/> + <check_box label="Meine Objekte bearbeiten, löschen oder nehmen" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_pick.xml b/indra/newview/skins/default/xui/de/panel_profile_pick.xml new file mode 100644 index 0000000000..1f44ba8b1b --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (wird nach dem Speichern aktualisiert) + </panel.string> + <line_editor name="pick_location"> + Laden... + </line_editor> + <button label="Teleportieren" name="teleport_btn"/> + <button label="Auf Karte anzeigen" name="show_on_map_btn"/> + <button label="Standort festlegen" name="set_to_curr_location_btn" tool_tip="Aktuellen Standort verwenden"/> + <button label="Auswahl speichern" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_picks.xml b/indra/newview/skins/default/xui/de/panel_profile_picks.xml new file mode 100644 index 0000000000..96403715e4 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Auswahlen" name="panel_picks"> + <string name="no_picks" value="Keine Auswahl"/> + <text name="Tell everyone about your favorite places in Second Life."> + Erzählen Sie von Ihren Lieblingsorten in Second Life. + </text> + <button label="Neu..." name="new_btn"/> + <button label="Löschen..." name="delete_btn"/> + <text name="picks_panel_text"> + Laden... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml new file mode 100644 index 0000000000..baaa58e1d7 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> + <string name="status_online"> + Zurzeit online + </string> + <string name="status_offline"> + Zurzeit offline + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=de + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=de + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Keine"/> + <string name="no_group_text" value="Keine"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Entwickler"/> + <string name="FSSupp" value="Support"/> + <string name="FSQualityAssurance" value="Fehlersuche"/> + <string name="FSGW" value="Gateway"/> + <text name="name_label" value="Name:"/> + <button label="Name:" name="set_name" tool_tip="Anzeigenamen festlegen"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(wird geladen...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Status unbekannt"/> + <text name="label" value="Second Life-Geburtsdatum:"/> + <text name="label2" value="Konto:"/> + <text name="partner_label" value="Partner:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Gruppen:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="In Gruppe einladen"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="Info:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Objekt geben:"/> + <text name="Give inventory" tool_tip="Legen Sie hier Inventarobjekte ab, um Sie dieser Person zu geben."> + Inventarobjekt hier ablegen. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Auf Karte anzeigen" label_selected="Auf Karte anzeigen" name="show_on_map_btn" tool_tip="Einwohner auf Karte lokalisieren"/> + <button label="Bezahlen" label_selected="Bezahlen" name="pay" tool_tip="Geld an den Einwohner zahlen"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Teleportation anbieten" label_selected="Teleportation anbieten" name="teleport" tool_tip="Dem Einwohner eine Teleportation anbieten"/> + <button label="Instant Message" label_selected="Instant Message" name="im" tool_tip="Instant Message-Sitzung öffnen"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Freund hinzufügen" label_selected="Freund hinzufügen" name="add_friend" tool_tip="Dem Einwohner die Freundschaft anbieten"/> + <button label="Blockieren" name="block" tool_tip="Diesen Einwohner blockieren"/> + <button label="Blockierung aufheben" name="unblock" tool_tip="Diesen Einwohner nicht mehr blockieren"/> + </layout_panel> + </layout_stack> + <check_box label="In Suche anzeigen" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_web.xml b/indra/newview/skins/default/xui/de/panel_profile_web.xml new file mode 100644 index 0000000000..a03918f4b5 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Ladezeit: [TIME] Sekunden"/> + <line_editor name="url_edit"> + (wird geladen..) + </line_editor> + <flyout_button label="Laden" name="load" tool_tip="Lädt diese Profilseite im integrierten Webbrowser."> + <flyout_button.item label="Im Viewer-Browser öffnen" name="open_item"/> + <flyout_button.item label="In externem Browser öffnen" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Webprofil ausklappen"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_region_terrain.xml b/indra/newview/skins/default/xui/de/panel_region_terrain.xml index 7801be30e4..42ba5b5269 100644 --- a/indra/newview/skins/default/xui/de/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/de/panel_region_terrain.xml @@ -10,8 +10,8 @@ <spinner label="Obere Terraingrenze" name="terrain_raise_spin"/> <spinner label="Untere Terraingrenze" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Terraintexturen (erfordert 24-Bit-.tga-Dateien mit einer Größe von 512x512) - </text> + Terraintexturen (erfordert 24-Bit-.tga-Dateien mit einer Größe von 1024x1024) + </text> <text name="height_text_lbl"> 1 (niedrig) </text> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 97ace4fc18..0120f7e5bd 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -356,6 +356,24 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden. <string name="TestingDisconnect"> Verbindungsabbruch wird getestet </string> + <string name="SocialFacebookConnecting"> + Mit Facebook verbinden... + </string> + <string name="SocialFacebookPosting"> + Posten... + </string> + <string name="SocialFacebookDisconnecting"> + Facebook-Verbindung trennen... + </string> + <string name="SocialFacebookErrorConnecting"> + Problem beim Verbinden mit Facebook + </string> + <string name="SocialFacebookErrorPosting"> + Problem beim Posten auf Facebook + </string> + <string name="SocialFacebookErrorDisconnecting"> + Problem beim Trennen der Facebook-Verbindung + </string> <string name="SocialFlickrConnecting"> Verbinden mit Flickr... </string> @@ -673,9 +691,6 @@ nächsten Eigentümer angehängt werden. <string name="GroupNameNone"> (keiner) </string> - <string name="AvalineCaller"> - Avaline-Anfrufer [ORDER] - </string> <string name="AssetErrorNone"> Kein Fehler </string> @@ -2578,9 +2593,21 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich unter http://suppo <string name="NoPicksClassifiedsText"> Sie haben keine Auswahl oder Anzeigen erstelllt. Klicken Sie auf die „Plus"-Schaltfläche, um eine Auswahl oder Anzeige zu erstellen. </string> + <string name="NoPicksText"> + Sie haben keine Auswahl erstellt. Klicken Sie auf die Schaltfläche "Neu", um eine Auswahl zu erstellen. + </string> + <string name="NoClassifiedsText"> + Sie haben keine Anzeigen erstellt. Klicken Sie auf die Schaltfläche "Neu", um eine Anzeige zu erstellen. + </string> <string name="NoAvatarPicksClassifiedsText"> Der Einwohner hat keine Auswahl oder Anzeigen </string> + <string name="NoAvatarPicksText"> + Der Einwohner hat keine Auswahl + </string> + <string name="NoAvatarClassifiedsText"> + Der Einwohner hat keine Anzeigen + </string> <string name="PicksClassifiedsLoadingText"> Wird geladen... </string> @@ -4558,6 +4585,9 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ <string name="share_alert"> Objekte aus dem Inventar hier her ziehen </string> + <string name="facebook_post_success"> + Sie haben auf Facebook gepostet. + </string> <string name="flickr_post_success"> Sie haben auf Flickr gepostet. </string> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index dee5e29a3c..4678d65b85 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1893,7 +1893,29 @@ Only large parcels can be listed in search. left="110" name="parcel_enable_voice_channel_local" width="300" /> - </panel> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + mouse_opaque="false" + name="media" + top_pad="10" + width="100"> + Media: + </text> + <check_box + height="16" + label="Obscure MOAP" + layout="topleft" + left="110" + left_pad="0" + name="obscure_moap" + tool_tip="Media on a prim located outside the parcel should not play automatically for an agent within this parcel and vice versa." + width="300" /> + </panel> <panel border="true" follows="all" diff --git a/indra/newview/skins/default/xui/en/floater_picks.xml b/indra/newview/skins/default/xui/en/floater_classified.xml index 984894b016..5b14c827d0 100644 --- a/indra/newview/skins/default/xui/en/floater_picks.xml +++ b/indra/newview/skins/default/xui/en/floater_classified.xml @@ -2,20 +2,19 @@ <floater positioning="cascading" can_close="true" - can_resize="true" + can_resize="false" height="572" help_topic="sidebar_me" min_width="333" min_height="440" - name="floater_picks" + name="floater_classified" save_rect="true" - save_visibility="true" - reuse_instance="true" - title="Picks" + save_visibility="false" + title="Classified" width="333" > <panel - class="panel_me" + class="panel_classified_info" name="main_panel" - filename="panel_me.xml" + filename="panel_classified_info.xml" follows="all"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml index bba30626b2..632daaec7e 100644 --- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml +++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml @@ -88,6 +88,7 @@ spellcheck="true" text_readonly_color="white" text_type="ascii_with_newline" + commit_on_focus_lost="true" top_pad="5" width="290" wrap="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_display_name.xml b/indra/newview/skins/default/xui/en/floater_display_name.xml index 9a9fd32a77..3c8f415860 100644 --- a/indra/newview/skins/default/xui/en/floater_display_name.xml +++ b/indra/newview/skins/default/xui/en/floater_display_name.xml @@ -23,7 +23,7 @@ use_ellipses="true" width="380" wrap="true"> - The name you give your avatar is called your Display Name. You can change it once a week. + Your display name is what other people see above your head. It is different from your login name. You can change it once a week. </text> <text type="string" @@ -85,19 +85,10 @@ width="120" /> <button height="23" - label="Reset" - layout="topleft" - font="SansSerif" - left_pad="5" - name="reset_btn" - tool_tip="Make Display Name the same as Username" - width="120" /> - <button - height="23" label="Cancel" font="SansSerif" layout="topleft" - left_pad="5" + left_pad="125" name="cancel_btn" width="120" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index b8893e11d9..9639e70544 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -16,11 +16,35 @@ width="200"> <floater.string name="ToolTipMsg"> - [REGION](Double-click to open Map, shift-drag to pan) + [PARCEL_NAME_MSG][PARCEL_SALE_PRICE_MSG][PARCEL_SALE_AREA_MSG][PARCEL_OWNER_MSG][REGION_NAME_MSG][TOOL_TIP_HINT_MSG] + </floater.string> + <floater.string + name="ParcelNameMsg"> + [PARCEL_NAME] + </floater.string> + <floater.string + name="ParcelSalePriceMsg"> + Price: L$[PRICE] (L$[PRICE_PER_SQM]/m²) + </floater.string> + <floater.string + name="ParcelSaleAreaMsg"> + Area: [AREA]m² + </floater.string> + <floater.string + name="ParcelOwnerMsg"> + Owner: [PARCEL_OWNER] + </floater.string> + <floater.string + name="RegionNameMsg"> + Region: [REGION_NAME] </floater.string> <floater.string - name="AltToolTipMsg"> - [REGION](Double-click to teleport, shift-drag to pan) + name="ToolTipHintMsg"> + Double-click to open map + </floater.string> + <floater.string + name="AltToolTipHintMsg"> + Double-click to teleport </floater.string> <floater.string name="mini_map_caption"> Mini-map @@ -37,105 +61,73 @@ <text type="string" length="1" - bottom="218" label="N" layout="topleft" - left="0" name="floater_map_north" - right="10" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> N </text> <text type="string" length="1" - bottom="218" label="E" layout="topleft" - left="0" name="floater_map_east" - right="10" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> E </text> <text type="string" length="1" - bottom="205" label="W" layout="topleft" - left="0" name="floater_map_west" - right="11" - text_color="1 1 1 0.7" - top="175"> + text_color="1 1 1 0.7"> W </text> <text type="string" length="1" - bottom="218" label="S" layout="topleft" - left="0" name="floater_map_south" - right="10" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> S </text> <text type="string" length="1" - bottom="218" label="SE" layout="topleft" - left="0" name="floater_map_southeast" - right="20" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> SE </text> <text type="string" length="1" - bottom="218" label="NE" layout="topleft" - left="0" name="floater_map_northeast" - right="20" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> NE </text> <text type="string" length="1" - bottom="218" label="SW" layout="topleft" - left="0" name="floater_map_southwest" - right="20" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> SW </text> <text type="string" length="1" - bottom="218" label="NW" layout="topleft" - left="0" name="floater_map_northwest" - right="20" - text_color="1 1 1 0.7" - top="189"> + text_color="1 1 1 0.7"> NW </text> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index e499ddbc2f..21c894d3af 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -830,6 +830,7 @@ <combo_item name="physics_medium"> Medium </combo_item> <combo_item name="physics_low"> Low </combo_item> <combo_item name="physics_lowest"> Lowest </combo_item> + <combo_item name="physics_bounding_box"> Bounding Box </combo_item> <combo_item name="load_from_file"> From file </combo_item> </combo_box> <line_editor diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml index e1e7e1c8c8..048cf7df62 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -17,94 +17,122 @@ name="Copy"> Copy To Inventory </floater.string> - <text - type="string" - length="1" - follows="left|top" - font="SansSerif" - height="19" - layout="topleft" - left="10" - name="desc txt" - top="21" - width="90"> - Description: - </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top|right" - font="SansSerif" - height="19" - layout="topleft" - left_pad="0" - max_length_bytes="127" - name="desc" - width="190" /> - <text - type="string" - halign="right" - length="1" - follows="right|bottom" - height="16" - layout="topleft" - left="110" - name="dimensions" - top="255" - width="200"> - [WIDTH]px x [HEIGHT]px - </text> - <text - type="string" - halign="right" - length="1" - follows="right|bottom" - height="16" - layout="topleft" - left_delta="-110" - name="aspect_ratio" - top_pad="5" - width="200"> - Preview aspect ratio - </text> - <combo_box - allow_text_entry="true" - top_delta="-3" - follows="right|bottom" - height="23" - left_pad="10" - max_chars="20" - mouse_opaque="true" - enabled="true" - width="108" - name="combo_aspect_ratio" - tool_tip="Preview at a fixed aspect ratio"> - </combo_box> - <button - follows="right|bottom" - height="22" - label="OK" - layout="topleft" - left="6" - name="Keep" - top_pad="5" - width="110" /> - <button - follows="right|bottom" - height="22" - label="Discard" - layout="topleft" - left_pad="5" - name="Discard" - top_delta="0" - width="110" /> - <button - follows="right|bottom" - height="22" - label="Save As" - layout="topleft" - left_pad="5" - name="save_tex_btn" - top_delta="0" - width="110" /> + <layout_stack + animate="false" + name="preview_stack" + top_pad="15" + left="0" + follows="all" + orientation="vertical" + height="350" + width="370" + layout="topleft"> + <layout_panel + name="texture_panel" + height="305" + top_pad="0" + left="0" + follows="left|top" + layout="topleft"> + <text + type="string" + length="1" + follows="left|top" + font="SansSerif" + height="19" + layout="topleft" + left="10" + name="desc txt" + top="6" + width="90"> + Description: + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top|right" + font="SansSerif" + height="19" + layout="topleft" + left_pad="0" + max_length_bytes="127" + name="desc" + width="190" /> + <text + type="string" + halign="right" + length="1" + follows="right|bottom" + height="16" + layout="topleft" + left="110" + name="dimensions" + bottom="-40" + width="200"> + [WIDTH]px x [HEIGHT]px + </text> + <text + type="string" + halign="right" + length="1" + follows="right|bottom" + height="16" + layout="topleft" + left_delta="-110" + name="aspect_ratio" + top_pad="5" + width="200"> + Preview aspect ratio + </text> + <combo_box + allow_text_entry="true" + top_delta="-3" + follows="right|bottom" + height="23" + left_pad="10" + max_chars="20" + mouse_opaque="true" + enabled="true" + width="108" + name="combo_aspect_ratio" + tool_tip="Preview at a fixed aspect ratio"> + </combo_box> + </layout_panel> + <layout_panel + name="buttons_panel" + height="45" + bottom="-40" + left="0" + follows="right|bottom" + auto_resize="false" + layout="topleft"> + <button + follows="right|bottom" + height="22" + label="OK" + layout="topleft" + left="6" + name="Keep" + top_pad="0" + width="110" /> + <button + follows="right|bottom" + height="22" + label="Discard" + layout="topleft" + left_pad="5" + name="Discard" + top_delta="0" + width="110" /> + <button + follows="right|bottom" + height="22" + label="Save As" + layout="topleft" + left_pad="5" + name="save_tex_btn" + top_delta="0" + width="110" /> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile.xml b/indra/newview/skins/default/xui/en/floater_profile.xml new file mode 100644 index 0000000000..32ab811a6e --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater + name="avatarinfo" + height="510" + width="510" + layout="topleft" + can_close="true" + can_resize="true" + help_topic="panel_my_profile_tab" + min_height="510" + min_width="510" + positioning="centered" + save_rect="true" + title="Profile" +> + <panel + name="panel_profile_view" + top="0" + left="0" + height="500" + width="505" + follows="all" + class="panel_profile" + > + <tab_container + name="panel_profile_tabs" + top_pad="5" + left="0" + height="500" + width="505" + follows="all" + layout="topleft" + halign="center" + tab_min_width="81" + tab_height="30" + tab_position="top" + > + <panel + name="panel_profile_secondlife" + label="BIO" + layout="topleft" + class="panel_profile_secondlife" + filename="panel_profile_secondlife.xml" + help_topic="profile_secondlife_tab" + /> + <panel + name="panel_profile_web" + label="FEED" + layout="topleft" + class="panel_profile_web" + filename="panel_profile_web.xml" + help_topic="profile_web_tab" + /> + <panel + name="panel_profile_picks" + label="PICKS" + layout="topleft" + class="panel_profile_picks" + filename="panel_profile_picks.xml" + help_topic="profile_picks_tab" + /> + <panel + name="panel_profile_classifieds" + label="CLASSIFIEDS" + layout="topleft" + class="panel_profile_classifieds" + filename="panel_profile_classifieds.xml" + help_topic="profile_classified_tab" + /> + <panel + name="panel_profile_firstlife" + label="REAL LIFE" + layout="topleft" + class="panel_profile_firstlife" + filename="panel_profile_firstlife.xml" + help_topic="profile_firstlife_tab" + /> + <panel + name="panel_profile_notes" + label="MY NOTES" + layout="topleft" + class="panel_profile_notes" + filename="panel_profile_notes.xml" + help_topic="profile_notes_tab" + /> + </tab_container> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile_permissions.xml b/indra/newview/skins/default/xui/en/floater_profile_permissions.xml new file mode 100644 index 0000000000..9f3b4d9a00 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile_permissions.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="false" + show_title="false" + can_minimize="false" + can_close="false" + header_height="10" + bg_opaque_image="Window_NoTitle_Foreground" + bg_alpha_image="Window_NoTitle_Background" + height="115" + layout="topleft" + name="profile_permissions" + width="300"> + <string + name="description_string" + value="Allow [AGENT_NAME] to:" /> + <text + name="perm_description" + value="Allow agent to:" + top="1" + left="12" + right="-6" + height="16" + follows="top|left" + layout="topleft" + font.style="BOLD" + /> + <check_box + name="online_check" + label="See when I am online" + top_pad="5" + left="16" + height="16" + width="293" + follows="top|left" + layout="topleft" + /> + <check_box + name="map_check" + label="Find me on the world map" + top_pad="5" + left="16" + height="16" + width="293" + follows="top|left" + layout="topleft" + /> + <check_box + name="objects_check" + label="Edit, delete or take my objects from my land" + top_pad="5" + left="16" + height="16" + width="293" + follows="top|left" + layout="topleft" + /> + <button + name="perms_btn_ok" + label="OK" + top_pad="5" + left="42" + height="20" + width="100" + follows="top|left" + layout="topleft"/> + <button + name="perms_btn_cancel" + label="Cancel" + top_delta="0" + left_pad="12" + height="20" + width="100" + follows="top|left" + layout="topleft"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile_texture.xml b/indra/newview/skins/default/xui/en/floater_profile_texture.xml new file mode 100644 index 0000000000..3b351a3325 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile_texture.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="false" + show_title="false" + can_minimize="false" + can_close="false" + header_height="10" + height="223" + width="200" + layout="topleft" + min_height="128" + min_width="128" + name="profile_texture"> + <layout_stack + name="preview_stack" + top="0" + left="0" + right="-1" + bottom="-1" + follows="all" + orientation="vertical" + layout="topleft" + animate="false"> + <layout_panel + name="texture_panel" + height="196" + follows="left|top" + auto_resize="true" + layout="topleft"> + <icon + name="profile_pic" + image_name="Generic_Person_Large" + layout="topleft" + follows="all" + top="5" + left="5" + bottom="-1" + right="-5"/> + </layout_panel> + <layout_panel + name="buttons_panel" + height="26" + auto_resize="false" + layout="topleft"> + <layout_stack + name="buttons_stack" + top="0" + left="0" + right="-1" + bottom="-1" + follows="all" + orientation="horizontal" + layout="topleft" + animate="false"> + <layout_panel + follows="all" + layout="topleft" + name="resizer_left" + auto_resize="true" + width="1"> + </layout_panel> + <layout_panel + follows="all" + layout="topleft" + name="close_panel" + auto_resize="false" + width="112"> + <button + follows="top|left" + height="22" + label="Close" + layout="topleft" + left="1" + top="0" + width="110" + name="close_btn"/> + </layout_panel> + <layout_panel + follows="all" + layout="topleft" + name="resizer_right" + auto_resize="true" + width="1"> + </layout_panel> + </layout_stack> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index d07e3cb31b..343e72f057 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -11,6 +11,11 @@ name="Screenshot"> Screenshot </floater.string> + <floater.string + name="chat_report_format"> +Time: [MSG_TIME] +Text: [MSG_DESCRIPTION] + </floater.string> <texture_picker allow_no_texture="true" default_image_name="None" @@ -19,7 +24,7 @@ layout="topleft" left="60" name="screenshot" - top="15" + top="20" width="220" /> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 0abee2ff80..ade79b8884 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2,7 +2,7 @@ <floater positioning="cascading" legacy_header_height="18" - height="600" + height="609" layout="topleft" bg_opaque_image="Window_NoTitle_Foreground" bg_alpha_image="Window_NoTitle_Background" @@ -68,7 +68,7 @@ </floater.string> <floater.string name="status_selectcount"> - [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] + [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] [secondlife:///app/openfloater/object_weights More info] </floater.string> <floater.string name="status_remaining_capacity"> @@ -763,11 +763,12 @@ font="SansSerifSmall" layout="topleft" left="10" - name="selection_count" + name="selection_faces" top_delta="0" visible="false" width="280"> - </text> + Faces selected: [FACES_STRING] + </text> <text text_color="LtGray_50" type="string" @@ -777,11 +778,10 @@ font="SansSerifSmall" layout="topleft" left="10" - name="remaining_capacity" + name="selection_count" top_pad="0" visible="false" width="280"> - [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info] </text> <!-- <text --> <!-- text_color="LtGray_50" --> @@ -820,7 +820,7 @@ width="282"/> <tab_container follows="left|top" - height="410" + height="426" halign="center" left="0" name="Object Info Tabs" @@ -1430,16 +1430,40 @@ even though the user gets a free copy. tool_tip="Causes object to not collide with other objects or avatars" top_pad="0" width="123" /> - <text + <view_border + bevel_style="none" + follows="top|left" + height="0" + layout="topleft" + left_delta="0" + name="object_horizontal" + top_pad="10" + width="95" /> + <menu_button + menu_filename="menu_copy_paste_pos.xml" + follows="top|left" + height="11" + image_disabled="ClipboardSmallMenu_Disabled" + image_selected="ClipboardSmallMenu_Press" + image_unselected="ClipboardSmallMenu_Off" + layout="topleft" + left_delta="0" + top_pad="13" + name="clipboard_pos_btn" + tool_tip="Paste options" + width="19"/> + <text type="string" length="1" follows="left|top" height="10" layout="topleft" name="label position" - top_pad="10" + tool_tip="Position (meters)" + left_pad="8" + top_delta="0" width="121"> - Position (meters) + Position (m) </text> <spinner follows="left|top" @@ -1449,12 +1473,12 @@ even though the user gets a free copy. label="X" label_width="10" layout="topleft" - left_delta="0" + left_delta="-27" max_val="512" min_val="-256" name="Pos X" text_enabled_color="1 0 0.3 .7" - top_pad="5" + top_pad="8" width="87" /> <spinner follows="left|top" @@ -1481,21 +1505,36 @@ even though the user gets a free copy. layout="topleft" left_delta="0" max_val="4096" + min_val="-32" name="Pos Z" text_enabled_color="0 0.8 1 .65" top_pad="3" width="87" /> + <menu_button + menu_filename="menu_copy_paste_size.xml" + follows="top|left" + height="11" + image_disabled="ClipboardSmallMenu_Disabled" + image_selected="ClipboardSmallMenu_Press" + image_unselected="ClipboardSmallMenu_Off" + layout="topleft" + left_delta="0" + top_pad="13" + name="clipboard_size_btn" + tool_tip="Paste options" + width="19"/> <text type="string" length="1" follows="left|top" height="10" layout="topleft" - left_delta="0" + left_pad="8" + top_delta="0" name="label size" - top_pad="6" + tool_tip="Size (meters)" width="121"> - Size (meters) + Size (m) </text> <spinner follows="left|top" @@ -1505,12 +1544,12 @@ even though the user gets a free copy. label="X" label_width="10" layout="topleft" - left_delta="0" + left_delta="-27" max_val="64" min_val="0.01" name="Scale X" text_enabled_color="1 1 1 1" - top_pad="5" + top_pad="8" width="87" /> <spinner follows="left|top" @@ -1542,17 +1581,31 @@ even though the user gets a free copy. text_enabled_color="1 1 1 1" top_pad="3" width="87" /> + <menu_button + menu_filename="menu_copy_paste_rot.xml" + follows="top|left" + height="11" + image_disabled="ClipboardSmallMenu_Disabled" + image_selected="ClipboardSmallMenu_Press" + image_unselected="ClipboardSmallMenu_Off" + layout="topleft" + left_delta="0" + top_pad="13" + name="clipboard_rot_btn" + tool_tip="Paste options" + width="19"/> <text type="string" length="1" follows="left|top" height="10" layout="topleft" - left_delta="0" + left_pad="8" + top_delta="0" name="label rotation" - top_pad="10" + tool_tip="Rotation (degrees)" width="121"> - Rotation (degrees) + Rotation (°) </text> <spinner decimal_digits="2" @@ -1563,12 +1616,12 @@ even though the user gets a free copy. label="X" label_width="10" layout="topleft" - left_delta="0" + left_delta="-27" max_val="9999" min_val="-9999" name="Rot X" text_enabled_color="1 1 1 1" - top_pad="5" + top_pad="8" width="87" /> <spinner decimal_digits="2" @@ -1614,13 +1667,23 @@ even though the user gets a free copy. width="150"> Prim Type </text>--> + + <view_border + bevel_style="none" + follows="top|left" + layout="topleft" + name="object_vertical" + left="117" + top="6" + height="500" + width="0"/> <combo_box height="19" layout="topleft" name="comboBaseType" top="6" left="125" - width="150"> + width="125"> <combo_box.item label="Box" name="Box" @@ -1654,13 +1717,26 @@ even though the user gets a free copy. name="Sculpted" value="Sculpted" /> </combo_box> + <menu_button + menu_filename="menu_copy_paste_object.xml" + follows="top|left" + height="15" + image_disabled="ClipboardMenu_Disabled" + image_selected="ClipboardMenu_Press" + image_unselected="ClipboardMenu_Off" + layout="topleft" + left_pad="8" + top_delta="2" + name="clipboard_obj_params_btn" + tool_tip="Paste options" + width="22"/> <text type="string" length="1" follows="left|top" height="10" layout="topleft" - left_delta="0" + left="125" name="text cut" top_pad="5" width="150"> @@ -1700,7 +1776,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text hollow" - top_pad="6" + top_pad="7" width="68"> Hollow </text> @@ -1748,7 +1824,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="Hollow Shape" - top_pad="4" + top_pad="7" width="150"> Hollow Shape </text> @@ -1784,7 +1860,7 @@ even though the user gets a free copy. layout="topleft" left_delta="0" name="text twist" - top_pad="5" + top_pad="7" width="150"> Twist (begin/end) </text> @@ -1826,12 +1902,12 @@ even though the user gets a free copy. layout="topleft" left="125" name="scale_taper" - top_pad="3" + top_pad="7" width="150"> Taper </text> <text - visible="false" + visible="false" type="string" length="1" follows="left|top" @@ -1879,7 +1955,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text topshear" - top_pad="3" + top_pad="5" width="141"> Top Shear </text> @@ -1922,12 +1998,12 @@ even though the user gets a free copy. layout="topleft" left="125" name="advanced_cut" - top_pad="3" + top_pad="7" width="150"> Profile Cut (begin/end) </text> <text - visible="false" + visible="false" type="string" length="1" follows="left|top" @@ -1986,7 +2062,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text taper2" - top_pad="3" + top_pad="7" width="150"> Taper </text> @@ -2029,7 +2105,7 @@ even though the user gets a free copy. layout="topleft" left="125" name="text radius delta" - top_pad="2" + top_pad="7" width="78"> Radius </text> @@ -2157,6 +2233,19 @@ even though the user gets a free copy. <panel.string name="None">None</panel.string> <panel.string name="Prim">Prim</panel.string> <panel.string name="Convex Hull">Convex Hull</panel.string> + <menu_button + menu_filename="menu_copy_paste_features.xml" + follows="top|left" + height="15" + image_disabled="ClipboardMenu_Disabled" + image_selected="ClipboardMenu_Press" + image_unselected="ClipboardMenu_Off" + layout="topleft" + left="258" + top="8" + name="clipboard_features_params_btn" + tool_tip="Paste options" + width="22"/> <text type="string" length="1" @@ -2309,6 +2398,15 @@ even though the user gets a free copy. name="FlexForceZ" top_pad="4" width="128" /> + <view_border + bevel_style="none" + follows="top|left" + height="0" + layout="topleft" + left="8" + name="object_horizontal" + top_pad="10" + width="278" /> <check_box height="16" @@ -2317,7 +2415,7 @@ even though the user gets a free copy. left="10" name="Light Checkbox Ctrl" tool_tip="Causes object to emit light" - top_pad="15" + top_pad="8" width="60" /> <color_swatch can_apply_immediately="true" @@ -2344,6 +2442,19 @@ even though the user gets a free copy. name="light texture control" tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)" width="32" /> + <menu_button + menu_filename="menu_copy_paste_light.xml" + follows="top|left" + height="15" + image_disabled="ClipboardMenu_Disabled" + image_selected="ClipboardMenu_Press" + image_unselected="ClipboardMenu_Off" + layout="topleft" + left="258" + top_delta="0" + name="clipboard_light_params_btn" + tool_tip="Paste options" + width="22"/> <spinner follows="left|top" height="19" @@ -2353,7 +2464,7 @@ even though the user gets a free copy. layout="topleft" left="10" name="Light Intensity" - top_pad="3" + top_pad="26" width="128" /> <spinner bottom_delta="0" decimal_digits="3" @@ -2575,7 +2686,7 @@ even though the user gets a free copy. border_visible="true" bevel_style="in" follows="left|top|right" - height="325" + height="335" layout="topleft" left="10" name="contents_inventory" diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 83407069d2..c965a4427c 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -14,6 +14,31 @@ single_instance="true" title="WORLD MAP" width="650"> + <string + name="collapse_icon" + value="map_ui_collapse_icon.png"/> + <string + name="expand_icon" + value="map_ui_expand_icon.png"/> + <string + name="collapse_tooltip" + value="Hide map controls"/> + <string + name="expand_tooltip" + value="Show map controls"/> + <layout_stack + animate="false" + follows="all" + name="floater_map_stack" + tab_group="1" + top="16" + left="0" + right="-1" + bottom="-1"> + <layout_panel + name="map_lp" + width="385" + height="575"> <panel filename="panel_world_map.xml" follows="all" @@ -21,17 +46,48 @@ layout="topleft" left="10" name="objects_mapview" - top="25" + top="6" width="375" /> + <panel + follows="top|right" + height="30" + layout="topleft" + left_pad="-29" + name="expand_btn_panel" + background_visible="true" + bg_opaque_color="FloaterFocusBackgroundColor" + bg_alpha_color="FloaterDefaultBackgroundColor" + background_opaque="true" + tool_tip="Hide map controls" + top="350" + width="30"> + <icon + follows="top|right" + height="16" + width="16" + top="7" + left="7" + scale_image="false" + image_name="map_ui_collapse_icon.png" + layout="topleft" + mouse_opaque="true" + name="expand_collapse_icon" + tool_tip="Hide map controls" /> + </panel> + </layout_panel> + <layout_panel + height="575" + width="265" + expanded_min_dim="265" + name="controls_lp"> <panel - name="layout_panel_1" - height="22" - width="238" - follows="right|top" - top="25" - left_pad="5" - background_visible="true" - bg_alpha_color="DkGray2"> + name="layout_panel_1" + height="22" + width="238" + follows="right|top" + top="6" + background_visible="true" + bg_alpha_color="DkGray2"> <text text_color="White" font="SansSerifLarge" @@ -43,17 +99,17 @@ layout="topleft" left="15" name="events_label" - top="3" width="215"> Legend </text> </panel> -<panel - follows="right|top" - height="126" - top_pad="0" - width="238" - name="layout_panel_2"> + <panel + follows="right|top" + height="126" + top_pad="4" + width="238" + left="1" + name="layout_panel_2"> <button follows="right|top" height="22" @@ -677,6 +733,7 @@ name="zoom_icon" top_pad="7" width="16" ></icon> + <!-- NOTE: min_val for zoom slider is hardcoded for performance reasons --> <slider follows="left|bottom" height="16" @@ -684,10 +741,12 @@ initial_value="-2" left_pad="0" layout="topleft" - max_val="0" + max_val="4" min_val="-8" name="zoom slider" show_text="false" width="200" /> </panel> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index ef4f19cd4c..fceb9b2184 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -85,6 +85,8 @@ use_ellipses="true" /> <text follows="left|top|right" + trusted_content="false" + always_show_icons="true" height="35" left="8" name="user_details" diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index 26b1c86c53..3b91b9df7a 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -33,6 +33,13 @@ function="Object.EnableTouch" name="EnableTouch"/> </menu_item_call> + <menu_item_call + label="Show in inventory" + layout="topleft" + name="Show original"> + <menu_item_call.on_click + function="Object.ShowOriginal" /> + </menu_item_call> <menu_item_separator layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml index 05ab4d35a0..9f394a4c74 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml @@ -96,6 +96,13 @@ name="Pay"> <on_click function="AvatarIcon.Action" parameter="pay" /> </menu_item_call> + <menu_item_call + label="Report Abuse" + layout="topleft" + name="Report Abuse"> + <on_click function="AvatarIcon.Action" parameter="report_abuse" /> + <on_enable function="AvatarIcon.Enable" parameter="report_abuse" /> + </menu_item_call> <menu_item_check label="Block Voice" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml index 500b6fffc2..20f3ad080b 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -290,4 +290,11 @@ <menu_item_call.on_visible function="EnableMuteParticle" /> </menu_item_call> + <menu_item_separator/> + <menu_item_call label="View Profile" + layout="topleft" + name="show_avatar_profile"> + <menu_item_call.on_click + function="Avatar.ToggleMyProfile" /> + </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index ed362b36e5..59e6106a28 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -132,6 +132,13 @@ <on_click function="Avatar.DoToSelected" parameter="pay" /> <on_enable function="Avatar.EnableItem" parameter="can_pay" /> </menu_item_call> + <menu_item_call + label="Report Abuse" + layout="topleft" + name="report_abuse"> + <on_click function="Avatar.DoToSelected" parameter="report_abuse" /> + <on_enable function="Avatar.EnableItem" parameter="report_abuse" /> + </menu_item_call> <menu_item_check label="Block Voice" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml new file mode 100644 index 0000000000..4c12180daf --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Color Menu"> + <menu_item_call + label="Copy" + layout="topleft" + name="params_copy" + visible="true"> + <on_click function="PanelFace.menuDoToSelected" parameter="color_copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="params_paste" + visible="true"> + <on_click function="PanelFace.menuDoToSelected" parameter="color_paste" /> + <on_enable function="PanelFace.menuEnable" parameter="color_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml new file mode 100644 index 0000000000..4823d74a26 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Features Menu"> + <menu_item_call + label="Copy" + layout="topleft" + name="params_copy" + visible="true"> + <on_click function="PanelVolume.menuDoToSelected" parameter="features_copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="params_paste" + visible="true"> + <on_click function="PanelVolume.menuDoToSelected" parameter="features_paste" /> + <on_enable function="PanelVolume.menuEnable" parameter="features_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml new file mode 100644 index 0000000000..5de23dfee3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Light Menu"> + <menu_item_call + label="Copy" + layout="topleft" + name="params_copy" + visible="true"> + <on_click function="PanelVolume.menuDoToSelected" parameter="light_copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="params_paste" + visible="true"> + <on_click function="PanelVolume.menuDoToSelected" parameter="light_paste" /> + <on_enable function="PanelVolume.menuEnable" parameter="light_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml new file mode 100644 index 0000000000..bdc4537a9d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Object Menu"> + <menu_item_call + label="Copy" + layout="topleft" + name="params_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="params_copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="params_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="params_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="params_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml new file mode 100644 index 0000000000..3ea95b281f --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Position Menu"> + <menu_item_call + label="Copy all" + layout="topleft" + name="psr_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> + <on_enable function="PanelObject.menuEnable" parameter="psr_copy" /> + </menu_item_call> + <menu_item_call + label="Copy position" + layout="topleft" + name="pos_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="pos_copy" /> + </menu_item_call> + <menu_item_call + label="Paste all" + layout="topleft" + name="psr_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> + </menu_item_call> + <menu_item_call + label="Paste position" + layout="topleft" + name="pos_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="pos_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="pos_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml new file mode 100644 index 0000000000..06ce80f897 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Rotation Menu"> + <menu_item_call + label="Copy all" + layout="topleft" + name="psr_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> + <on_enable function="PanelObject.menuEnable" parameter="rot_paste" /> + </menu_item_call> + <menu_item_call + label="Copy rotation" + layout="topleft" + name="rot_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="rot_copy" /> + </menu_item_call> + <menu_item_call + label="Paste all" + layout="topleft" + name="psr_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> + </menu_item_call> + <menu_item_call + label="Paste rotation" + layout="topleft" + name="rot_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="rot_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="rot_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml new file mode 100644 index 0000000000..7082a0e65b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Size Menu"> + <menu_item_call + label="Copy all" + layout="topleft" + name="psr_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> + <on_enable function="PanelObject.menuEnable" parameter="psr_copy" /> + </menu_item_call> + <menu_item_call + label="Copy size" + layout="topleft" + name="size_copy" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="size_copy" /> + </menu_item_call> + <menu_item_call + label="Paste all" + layout="topleft" + name="psr_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> + </menu_item_call> + <menu_item_call + label="Paste size" + layout="topleft" + name="size_paste" + visible="true"> + <on_click function="PanelObject.menuDoToSelected" parameter="size_paste" /> + <on_enable function="PanelObject.menuEnable" parameter="size_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml new file mode 100644 index 0000000000..f358affc23 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Texture Menu"> + <menu_item_call + label="Copy" + layout="topleft" + name="params_copy" + visible="true"> + <on_click function="PanelFace.menuDoToSelected" parameter="texture_copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="params_paste" + visible="true"> + <on_click function="PanelFace.menuDoToSelected" parameter="texture_paste" /> + <on_enable function="PanelFace.menuEnable" parameter="texture_paste" /> + </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml index 5cae643e44..359c093eff 100644 --- a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml @@ -9,7 +9,7 @@ layout="topleft" name="activate"> <on_click - function="Gesture.Action.ToogleActiveState" /> + function="Gesture.Action.ToggleActiveState" /> </menu_item_call> <menu_item_call label="Rename" diff --git a/indra/newview/skins/default/xui/en/menu_im_conversation.xml b/indra/newview/skins/default/xui/en/menu_im_conversation.xml index 43287c6ec3..b38fae4404 100644 --- a/indra/newview/skins/default/xui/en/menu_im_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_im_conversation.xml @@ -79,6 +79,13 @@ </menu_item_call> <menu_item_separator layout="topleft"/> + <menu_item_call + label="Report Abuse" + layout="topleft" + name="Report Abuse"> + <on_click function="Avatar.GearDoToSelected" parameter="report_abuse" /> + <on_enable function="Avatar.EnableGearItem" parameter="report_abuse" /> + </menu_item_call> <menu_item_check label="Block Voice" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 78ca170813..aa3d0ae071 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -912,6 +912,25 @@ function="Inventory.DoToSelected" parameter="apply_settings_parcel" /> </menu_item_call> + <menu_item_separator + layout="topleft" + name="Subfolder Separator" /> + <menu_item_call + label="Create folder from selected" + layout="topleft" + name="New folder from selected"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="new_folder_from_selected" /> + </menu_item_call> + <menu_item_call + label="Ungroup folder items" + layout="topleft" + name="Ungroup folder items"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="ungroup_folder_items" /> + </menu_item_call> <menu_item_separator layout="topleft" name="Marketplace Separator" /> diff --git a/indra/newview/skins/default/xui/en/menu_mini_map.xml b/indra/newview/skins/default/xui/en/menu_mini_map.xml index ea263d05ce..2715c916d4 100644 --- a/indra/newview/skins/default/xui/en/menu_mini_map.xml +++ b/indra/newview/skins/default/xui/en/menu_mini_map.xml @@ -8,63 +8,109 @@ top="724" visible="false" width="128"> - <menu_item_call - label="Zoom Close" - name="Zoom Close"> - <menu_item_call.on_click - function="Minimap.Zoom" + <menu_item_check + label="Zoom very close" + name="Zoom very close"> + <menu_item_check.on_check + function="Minimap.Zoom.Check" + parameter="very close" /> + <menu_item_check.on_click + function="Minimap.Zoom.Set" + parameter="very close" /> + </menu_item_check> + <menu_item_check + label="Zoom close" + name="Zoom close"> + <menu_item_check.on_check + function="Minimap.Zoom.Check" parameter="close" /> - </menu_item_call> - <menu_item_call - label="Zoom Medium" - name="Zoom Medium"> - <menu_item_call.on_click - function="Minimap.Zoom" + <menu_item_check.on_click + function="Minimap.Zoom.Set" + parameter="close" /> + </menu_item_check> + <menu_item_check + label="Zoom medium" + name="Zoom medium"> + <menu_item_check.on_check + function="Minimap.Zoom.Check" parameter="medium" /> - </menu_item_call> - <menu_item_call - label="Zoom Far" - name="Zoom Far"> - <menu_item_call.on_click - function="Minimap.Zoom" + <menu_item_check.on_click + function="Minimap.Zoom.Set" + parameter="medium" /> + </menu_item_check> + <menu_item_check + label="Zoom far" + name="Zoom far"> + <menu_item_check.on_check + function="Minimap.Zoom.Check" parameter="far" /> - </menu_item_call> - <menu_item_call - label="Zoom Default" - name="Zoom Default"> - <menu_item_call.on_click - function="Minimap.Zoom" - parameter="default" /> - </menu_item_call> + <menu_item_check.on_click + function="Minimap.Zoom.Set" + parameter="far" /> + </menu_item_check> <menu_item_separator /> <menu_item_check - label="Rotate Map" - name="Rotate Map"> + label="North at top" + name="North at top"> <menu_item_check.on_check - control="MiniMapRotate" /> + function="Minimap.MapOrientation.Check" + parameter="north_at_top" /> <menu_item_check.on_click - function="ToggleControl" - parameter="MiniMapRotate" /> + function="Minimap.MapOrientation.Set" + parameter="north_at_top" /> </menu_item_check> <menu_item_check - label="Auto Center" - name="Auto Center"> + label="Camera at top" + name="Camera at top"> <menu_item_check.on_check - control="MiniMapAutoCenter" /> + function="Minimap.MapOrientation.Check" + parameter="camera_at_top" /> <menu_item_check.on_click - function="ToggleControl" - parameter="MiniMapAutoCenter" /> + function="Minimap.MapOrientation.Set" + parameter="camera_at_top" /> + </menu_item_check> + <menu_item_separator /> + <menu_item_check + label="Show parcel boundaries" + name="Show parcel boundaries"> + <menu_item_check.on_check + control="MiniMapShowPropertyLines" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="MiniMapShowPropertyLines" /> </menu_item_check> <menu_item_separator /> + <menu_item_check + label="Auto-center map" + name="Auto-center map"> + <menu_item_check.on_check + control="MiniMapAutoCenter" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="MiniMapAutoCenter" /> + </menu_item_check> + <menu_item_separator /> + <menu_item_call + label="Re-center map" + name="Re-center map"> + <menu_item_call.on_click + function="Minimap.Center.Activate" /> + </menu_item_call> <menu_item_call - label="Stop Tracking" - name="Stop Tracking"> + label="Stop tracking" + name="Stop tracking"> <menu_item_call.on_click function="Minimap.Tracker" parameter="task_properties" /> </menu_item_call> <menu_item_separator /> <menu_item_call + label="About Land" + name="About Land"> + <menu_item_call.on_click + function="Minimap.AboutLand" /> + </menu_item_call> + <menu_item_call label="World Map" name="World Map"> <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/menu_profile_other.xml b/indra/newview/skins/default/xui/en/menu_profile_other.xml new file mode 100644 index 0000000000..4db4d0922b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_profile_other.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Avatar Profile Menu"> + <menu_item_call + label="IM" + layout="topleft" + name="im"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="im"/> + </menu_item_call> + <menu_item_call + label="Offer Teleport" + name="offer_teleport"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="offer_teleport"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="offer_teleport"/> + </menu_item_call> + <menu_item_call + label="Request Teleport" + name="request_teleport"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="request_teleport"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="request_teleport"/> + </menu_item_call> + <menu_item_call + label="Voice call" + layout="topleft" + name="voice_call"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="voice_call"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="voice_call"/> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + label="View chat history..." + layout="topleft" + name="chat_history"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="chat_history"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="chat_history"/> + </menu_item_call> + <menu_item_separator name="separator_chat_history"/> + <menu_item_call + label="Add Friend" + layout="topleft" + name="add_friend"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="add_friend"/> + <menu_item_call.on_visible + function="Profile.EnableItem" + parameter="add_friend"/> + </menu_item_call> + <menu_item_call + label="Remove Friend" + layout="topleft" + name="remove_friend"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="remove_friend"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="remove_friend"/> + </menu_item_call> + <menu_item_call + label="Invite to group..." + layout="topleft" + name="invite_to_group"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="invite_to_group"/> + </menu_item_call> + <menu_item_separator name="separator_invite_to_group"/> + <menu_item_call + label="Permissions" + layout="topleft" + name="agent_permissions"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="agent_permissions"/> + <menu_item_call.on_visible + function="Profile.EnableItem" + parameter="agent_permissions"/> + </menu_item_call> + <menu_item_call + label="Map" + layout="topleft" + name="map"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="can_show_on_map"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="can_show_on_map"/> + </menu_item_call> + <menu_item_call + label="Share" + layout="topleft" + name="share"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="share"/> + </menu_item_call> + <menu_item_call + label="Pay" + layout="topleft" + name="pay"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="pay"/> + </menu_item_call> + <menu_item_check + label="Block/Unblock" + layout="topleft" + name="block_unblock"> + <menu_item_check.on_click + function="Profile.Commit" + parameter="toggle_block_agent"/> + <menu_item_check.on_check + function="Profile.CheckItem" + parameter="toggle_block_agent"/> + <menu_item_check.on_enable + function="Profile.EnableItem" + parameter="toggle_block_agent"/> + </menu_item_check> + <menu_item_separator name="separator_copy_options"/> + <menu_item_call + label="Copy Display Name" + layout="topleft" + name="copy_display_name"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_display_name"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="copy_display_name"/> + </menu_item_call> + <menu_item_call + label="Copy Agent Name" + layout="topleft" + name="copy_name"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_username"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="copy_username"/> + </menu_item_call> + <menu_item_call + label="Copy Agent Id" + layout="topleft" + name="copy_id"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_user_id"/> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_profile_self.xml b/indra/newview/skins/default/xui/en/menu_profile_self.xml new file mode 100644 index 0000000000..d0bd4000f8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_profile_self.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Avatar Profile Menu Self"> + <menu_item_call + label="Edit Display Name" + layout="topleft" + name="edit_display_name"> + <on_click + function="Profile.Commit" + parameter="edit_display_name"/> + </menu_item_call> + <menu_item_call + label="Edit Partner" + layout="topleft" + name="edit_partner"> + <on_click + function="Profile.Commit" + parameter="edit_partner"/> + </menu_item_call> + <menu_item_call + label="Upload Photo" + layout="topleft" + name="upload_photo"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="upload_photo"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="upload_photo"/> + </menu_item_call> + <menu_item_call + label="Change Photo" + layout="topleft" + name="change_photo"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="change_photo"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="change_photo"/> + </menu_item_call> + <menu_item_call + label="Remove Photo" + layout="topleft" + name="remove_photo"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="remove_photo"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="remove_photo"/> + </menu_item_call> + <menu_item_separator name="separator_copy_options"/> + <menu_item_call + label="Copy Display Name" + layout="topleft" + name="copy_display_name"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_display_name"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="copy_display_name"/> + </menu_item_call> + <menu_item_call + label="Copy Agent Name" + layout="topleft" + name="copy_name"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_username"/> + <menu_item_call.on_enable + function="Profile.EnableItem" + parameter="copy_username"/> + </menu_item_call> + <menu_item_call + label="Copy Agent Id" + layout="topleft" + name="copy_id"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_user_id"/> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml index e8b6116026..5ca8be2123 100644 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -29,7 +29,14 @@ name="remove_friend"> <menu_item_call.on_click function="Url.RemoveFriend" /> - </menu_item_call> + </menu_item_call> + <menu_item_call + label="Report Abuse" + layout="topleft" + name="report_abuse"> + <menu_item_call.on_click + function="Url.ReportAbuse" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1caa0908ea..58584345a9 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -47,8 +47,7 @@ label="Picks..." name="Picks"> <menu_item_call.on_click - function="Floater.ToggleOrBringToFront" - parameter="picks" /> + function="ShowAgentProfilePicks" /> </menu_item_call> <menu_item_call label="Experiences..." @@ -423,7 +422,9 @@ </menu_item_call> <menu_item_call label="Stop animations" - name="Stop Animating My Avatar"> + name="Stop Animating My Avatar" + allow_key_repeat="true" + shortcut="alt|shift|A"> <menu_item_call.on_click function="Tools.StopAllAnimations" /> </menu_item_call> @@ -2647,6 +2648,12 @@ function="World.EnvPreset" function="Advanced.ForceErrorBadMemoryAccess" /> </menu_item_call> <menu_item_call + label="Force Bad Memory Access in Coroutine" + name="Force Bad Memory Access in Coroutine"> + <menu_item_call.on_click + function="Advanced.ForceErrorBadMemoryAccessCoro" /> + </menu_item_call> + <menu_item_call label="Force Infinite Loop" name="Force Infinite Loop"> <menu_item_call.on_click @@ -3326,6 +3333,18 @@ function="World.EnvPreset" function="Advanced.DropPacket" /> </menu_item_call> </menu> + <menu + create_jump_keys="true" + label="Cache" + name="Cache" + tear_off="true"> + <menu_item_call + label="Purge Disk Cache" + name="Purge Disk Cache"> + <menu_item_call.on_click + function="Advanced.PurgeDiskCache" /> + </menu_item_call> + </menu> <menu_item_call label="Dump Scripted Camera" name="Dump Scripted Camera"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index aa93601669..1ddec93668 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1496,7 +1496,19 @@ Insufficient funds to create classified. <notification icon="alertmodal.tga" - name="DeleteAvatarPick" + name="ProfileDeleteClassified" + type="alertmodal"> +Delete classified <nolink>[CLASSIFIED]</nolink>? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="ProfileDeletePick" type="alertmodal"> Delete pick <nolink>[PICK]</nolink>? <tag>confirm</tag> @@ -1507,6 +1519,32 @@ Delete pick <nolink>[PICK]</nolink>? </notification> <notification + icon="alert.tga" + name="ProfileUnpublishedClassified" + type="alertmodal"> + You have unpublished classifieds. They will be lost if you close the window. + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alert.tga" + name="ProfileUnsavedChanges" + type="alertmodal"> + You have usaved changes. + <tag>confirm</tag> + <tag>save</tag> + <usetemplate + canceltext="Cancel" + name="yesnocancelbuttons" + notext="Discard" + yestext="Save"/> + </notification> + + <notification icon="alertmodal.tga" name="DeleteOutfits" type="alertmodal"> @@ -3907,7 +3945,7 @@ Are you sure you want to return objects owned by [USER_NAME]? Couldn't set region textures: Terrain texture [TEXTURE_NUM] has an invalid bit depth of [TEXTURE_BIT_DEPTH]. -Replace texture [TEXTURE_NUM] with a 24-bit 512x512 or smaller image then click "Apply" again. +Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. <tag>fail</tag> </notification> @@ -3918,7 +3956,7 @@ Replace texture [TEXTURE_NUM] with a 24-bit 512x512 or smaller image then click Couldn't set region textures: Terrain texture [TEXTURE_NUM] is too large at [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y]. -Replace texture [TEXTURE_NUM] with a 24-bit 512x512 or smaller image then click "Apply" again. +Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. </notification> <notification @@ -9040,6 +9078,29 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran <notification icon="alertmodal.tga" + name="FacePasteFailed" + type="alertmodal"> +Paste failed. [REASON] + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="FacePasteTexturePermissions" + type="alertmodal"> + You applied a texture with limited permissions, object will inherit permissions from texture. + <usetemplate + ignoretext="Paste: You applied a texture with limited permissions" + name="notifyignore"/> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="ConfirmLeaveCall" type="alertmodal"> Are you sure you want to leave this call? @@ -11640,7 +11701,7 @@ This Region does not support environmental settings. <notification icon="alertmodal.tga" - label="Save Outfit" + label="Save Environmental Settings" name="SaveSettingAs" type="alertmodal"> <unique/> @@ -11819,4 +11880,38 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB </form> </notification> + <notification + icon="alertmodal.tga" + label="Create subfolder" + name="CreateSubfolder" + type="alertmodal"> + <unique/> + Name the new folder: + <tag>confirm</tag> + <form name="form"> + <input name="message" type="text"> + [DESC] + </input> + <button + default="true" + index="0" + name="OK" + text="OK"/> + <button + index="1" + name="Cancel" + text="Cancel"/> + </form> + </notification> + <notification + icon="alertmodal.tga" + name="SameFolderRequired" + type="alert"> + Selected items must be in the same folder. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index aa1b929412..54f038c24f 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -155,6 +155,7 @@ right="-3" mouse_opaque="true" name="speaking_indicator" + tool_tip="Voice volume" visible="true" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml index d4a2745d1d..04a0bc800d 100644 --- a/indra/newview/skins/default/xui/en/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -38,28 +38,15 @@ name="auto_renew_off"> Disabled </panel.string> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back_btn" - left="10" - tab_stop="false" - top="2" - width="30" - use_draw_context_alpha="false" /> <text follows="top|left|right" font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="4" + left="12" name="title" text_color="LtGray" - top="0" + top="2" value="Classified Info" use_ellipses="true" width="275" /> @@ -420,7 +407,7 @@ height="23" label="Teleport" layout="topleft" - left="0" + left="2" name="teleport_btn" top="0" width="101" /> @@ -443,24 +430,6 @@ top="0" width="100" /> </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="edit_btn_lp" - auto_resize="true" - width="101"> - <button - follows="bottom|left|right" - height="23" - label="Edit" - layout="topleft" - name="edit_btn" - top="0" - width="101" /> - </layout_panel> </layout_stack> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml deleted file mode 100644 index e846edf1d4..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ /dev/null @@ -1,354 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - bevel_style="in" - follows="left|top|right|bottom" - height="569" - label="Edit Classified" - layout="topleft" - left="0" - min_height="350" - name="panel_edit_classified" - help_topic="profile_edit_classified" - top="0" - width="333"> - <panel.string - name="location_notice"> - (will update after save) - </panel.string> - <string name="publish_label"> - Publish - </string> - <string name="save_label"> - Save - </string> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back_btn" - left="10" - tab_stop="false" - top="2" - width="30" - use_draw_context_alpha="false" /> - <text - type="string" - length="1" - follows="top" - font="SansSerifHugeBold" - height="26" - layout="topleft" - left_pad="4" - name="title" - text_color="LtGray" - top="0" - width="250"> - Edit Classified - </text> - <scroll_container - color="DkGray2" - follows="all" - height="502" - layout="topleft" - left="8" - top_pad="10" - name="profile_scroll" - reserve_scroll_corner="false" - opaque="true" - width="312"> - <panel - name="scroll_content_panel" - follows="left|top" - min_height="300" - layout="topleft" - top="0" - background_visible="false" - height="690" - left="0" - width="285"> - <panel - name="snapshot_panel" - layout="topleft" - follows="left|top|right" - height="197" - left="10" - top="10" - width="272"> - <texture_picker - fallback_image="default_land_picture.j2c" - follows="left|top|right" - height="197" - width="272" - layout="topleft" - top="0" - left="0" - name="classified_snapshot" /> - <icon - height="197" - image_name="spacer24.tga" - layout="topleft" - name="edit_icon" - label="" - tool_tip="Click to select an image" - top="0" - left="0" - width="272" /> - </panel> - <text - type="string" - length="1" - follows="left|top" - height="15" - font="SansSerifSmall" - font.style="BOLD" - layout="topleft" - left="10" - top="215" - name="Name:" - text_color="white" - width="280"> - Title: - </text> - <line_editor - follows="left|top|right" - font="SansSerif" - height="20" - layout="topleft" - left="10" - top_pad="2" - max_length_bytes="30" - name="classified_name" - prevalidate_callback="ascii" - text_color="black" - width="273" /> - <text - type="string" - length="1" - follows="left|top" - height="15" - font="SansSerifSmall" - font.style="BOLD" - layout="topleft" - left="10" - top_pad="20" - name="description_label" - text_color="white" - width="280"> - Description: - </text> - <text_editor - follows="left|top|right" - height="100" - width="273" - layout="topleft" - left="10" - top_pad="2" - max_length="256" - name="classified_desc" - text_color="black" - word_wrap="true" /> - <text - type="string" - length="1" - font="SansSerifSmall" - font.style="BOLD" - follows="left|top" - height="15" - layout="topleft" - left="10" - name="location_label" - text_color="white" - top_pad="20" - width="280"> - Location: - </text> - <text - type="string" - length="1" - follows="left|top" - height="30" - layout="topleft" - left="10" - name="classified_location" - right="-10" - top_pad="2" - width="280" - word_wrap="true"> - loading... - </text> - <button - follows="left|top" - height="23" - label="Set to Current Location" - layout="topleft" - left="10" - top_pad="5" - name="set_to_curr_location_btn" - width="200" /> - <text - follows="left|top" - font.style="BOLD" - height="10" - layout="topleft" - left="10" - name="category_label" - text_color="white" - top_pad="15" - value="Category:" - width="250" /> - <combo_box - follows="left|top" - height="23" - label="" - left="10" - name="category" - top_pad="5" - width="156" /> - <text - follows="left|top" - font.style="BOLD" - height="10" - layout="topleft" - left="10" - name="content_type_label" - text_color="white" - top_pad="15" - value="Content type:" - width="250" /> - <icons_combo_box - follows="left|top" - height="23" - label="General Content" - layout="topleft" - left="10" - name="content_type" - top_pad="5" - width="156"> - <icons_combo_box.drop_down_button - image_overlay="Parcel_PG_Light" - image_overlay_alignment="left" - imgoverlay_label_space="3" - pad_left="3"/> - <icons_combo_box.item - label="Moderate Content" - name="mature_ci" - value="Mature"> - <item.columns - halign="center" - type="icon" - value="Parcel_M_Light" - width="20"/> - </icons_combo_box.item> - <icons_combo_box.item - label="General Content" - name="pg_ci" - value="PG"> - <item.columns - halign="center" - type="icon" - value="Parcel_PG_Light" - width="20"/> - </icons_combo_box.item> - </icons_combo_box> - <check_box - height="16" - label="Auto renew each week" - layout="topleft" - left="10" - name="auto_renew" - top_pad="15" - width="250" /> - <text - follows="left|top" - height="10" - layout="topleft" - left="10" - name="price_for_listing_label" - text_color="white" - top_pad="15" - value="Price for listing:" - width="250" /> - <spinner - decimal_digits="0" - follows="left|top" - halign="left" - height="23" - increment="1" - label_width="20" - label="L$" - v_pad="10" - layout="topleft" - left="10" - value="50" - min_val="50" - max_val="99999" - name="price_for_listing" - top_pad="5" - tool_tip="Price for listing." - width="105" /> - </panel> - </scroll_container> - <panel - follows="left|right|bottom" - height="23" - label="bottom_panel" - layout="topleft" - left="8" - name="bottom_panel" - top_pad="5" - width="303"> - - <layout_stack - follows="bottom|left|right" - height="23" - layout="topleft" - name="bottom_panel_ls" - left="1" - orientation="horizontal" - top_pad="0" - width="309"> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left="0" - name="save_changes_btn_lp" - auto_resize="true" - width="156"> - <button - follows="bottom|left|right" - height="23" - label="[LABEL]" - layout="topleft" - name="save_changes_btn" - left="1" - top="0" - width="155" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="show_on_map_btn_lp" - auto_resize="true" - width="157"> - <button - follows="bottom|left|right" - height="23" - label="Cancel" - layout="topleft" - name="cancel_btn" - left="1" - top="0" - width="156" /> - </layout_panel> - </layout_stack> - </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml deleted file mode 100644 index 357a5559bf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ /dev/null @@ -1,239 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - bevel_style="in" - follows="left|top|right|bottom" - height="569" - label="Edit Pick" - layout="topleft" - left="0" - min_height="350" - name="panel_edit_pick" - help_topic="profile_edit_pick" - top="0" - width="333"> - <panel.string - name="location_notice"> - (will update after save) - </panel.string> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back_btn" - left="10" - tab_stop="false" - top="4" - width="30" - use_draw_context_alpha="false" /> - <text - type="string" - length="1" - follows="top" - font="SansSerifHugeBold" - height="26" - layout="topleft" - left_pad="4" - name="title" - text_color="LtGray" - top="4" - width="250"> - Edit Pick - </text> - <scroll_container - color="DkGray2" - follows="all" - height="501" - layout="topleft" - left="8" - top_pad="9" - name="profile_scroll" - opaque="true" - width="312"> - <panel - name="scroll_content_panel" - follows="left|top|right" - min_height="300" - layout="topleft" - top="0" - background_visible="false" - height="500" - left="0" - width="285"> - <texture_picker - fallback_image="default_land_picture.j2c" - follows="left|top|right" - height="197" - width="272" - layout="topleft" - no_commit_on_selection="true" - top="10" - left="11" - name="pick_snapshot" /> - <icon - height="197" - image_name="spacer24.tga" - layout="topleft" - name="edit_icon" - label="" - tool_tip="Click to select an image" - top="10" - left="11" - width="286" /> - <text - type="string" - length="1" - follows="left|top|right" - height="15" - font="SansSerifSmall" - font.style="BOLD" - layout="topleft" - left="10" - top="215" - name="Name:" - text_color="white" - width="280"> - Title: - </text> - <line_editor - follows="left|top|right" - font="SansSerif" - height="20" - layout="topleft" - left="10" - top_pad="2" - max_length_bytes="63" - name="pick_name" - text_color="black" - width="273" /> - <text - type="string" - length="1" - follows="left|top|right" - height="15" - font="SansSerifSmall" - font.style="BOLD" - layout="topleft" - left="10" - top_pad="20" - name="description_label" - text_color="white" - width="280"> - Description: - </text> - <text_editor - follows="left|top|right" - height="100" - width="273" - hide_scrollbar="false" - layout="topleft" - left="10" - top_pad="2" - max_length="1023" - name="pick_desc" - spellcheck="true" - text_color="black" - word_wrap="true" /> - <text - type="string" - length="1" - font="SansSerifSmall" - font.style="BOLD" - follows="left|top|right" - height="15" - layout="topleft" - left="10" - name="location_label" - text_color="white" - top_pad="20" - width="280"> - Location: - </text> - <text - type="string" - length="1" - follows="left|top|right" - height="50" - layout="topleft" - left="10" - name="pick_location" - top_pad="2" - width="280" - word_wrap="true"> - loading... - </text> - <button - follows="left|top" - height="23" - label="Set to Current Location" - layout="topleft" - left="8" - top_pad="0" - name="set_to_curr_location_btn" - width="200" /> - </panel> - </scroll_container> - <panel - follows="left|right|bottom" - height="23" - label="bottom_panel" - layout="topleft" - left="8" - name="bottom_panel" - top_pad="5" - width="315"> - - <layout_stack - follows="bottom|left|right" - height="23" - layout="topleft" - name="layout_stack1" - left="0" - orientation="horizontal" - top_pad="0" - width="313"> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="topleft" - left="0" - name="layout_panel1" - auto_resize="true" - width="150"> - <button - follows="bottom|left|right" - height="23" - label="Save Pick" - layout="topleft" - name="save_changes_btn" - top="0" - left="1" - width="149" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="topleft" - left_pad="4" - name="layout_panel2" - auto_resize="true" - width="146"> - <button - follows="bottom|left|right" - height="23" - label="Cancel" - layout="topleft" - name="cancel_btn" - top="0" - left="1" - width="145" /> - </layout_panel> - </layout_stack> - - </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml deleted file mode 100644 index 2c7c8133d1..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ /dev/null @@ -1,472 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - class="edit_profile_panel" - follows="all" - height="585" - label="Profile Edit" - layout="topleft" - left="0" - name="edit_profile_panel" - top="0" - width="313"> - <string - name="CaptionTextAcctInfo"> - [ACCTTYPE] -[PAYMENTINFO] [AGEVERIFICATION] - </string> - <string - name="RegisterDateFormat"> - [REG_DATE] ([AGE]) - </string> - <string - name="AcctTypeResident" - value="Resident" /> - <string - name="AcctTypeTrial" - value="Trial" /> - <string - name="AcctTypeCharterMember" - value="Charter Member" /> - <string - name="AcctTypeEmployee" - value="Linden Lab Employee" /> - <string - name="PaymentInfoUsed" - value="Payment Info Used" /> - <string - name="PaymentInfoOnFile" - value="Payment Info On File" /> - <string - name="NoPaymentInfoOnFile" - value="No Payment Info On File" /> - <string - name="AgeVerified" - value="Age-verified" /> - <string - name="NotAgeVerified" - value="Not Age-verified" /> - <string - name="partner_edit_link_url"> - http://www.secondlife.com/account/partners.php?lang=en - </string> - <string - name="my_account_link_url"> - http://secondlife.com/my - </string> - <string - name="no_partner_text" - value="None" /> - <scroll_container - color="DkGray2" - follows="all" - height="537" - min_height="300" - layout="topleft" - left="8" - width="292" - name="profile_scroll" - reserve_scroll_corner="true" - opaque="true" - top="10"> - <panel - name="scroll_content_panel" - follows="left|top|right" - layout="topleft" - top="0" - height="537" - min_height="300" - left="0" - width="292"> - <panel - name="data_panel" - follows="left|top|right" - layout="topleft" - top="0" - height="537" - min_height="300" - left="0" - width="292"> - <text - top="5" - follows="top|left" - height="13" - layout="topleft" - left="10" - name="display_name_label" - text_color="LtGray" - value="Display Name:" - width="80" /> - <text - top="5" - follows="top|left" - height="13" - layout="topleft" - left="10" - name="solo_username_label" - text_color="LtGray" - value="Username:" - visible="false" - width="80" /> - <button - name="set_name" - layout="topleft" - follows="top|left" - image_overlay="Edit_Wrench" - top="21" - left="10" - height="23" - width="23" - tool_tip="Set Display Name"/> - <text - follows="top|left" - font="SansSerifBigBold" - height="20" - layout="topleft" - left="10" - name="solo_user_name" - text_color="white" - top_delta="3" - translate="false" - value="TestString PleaseIgnore" - use_ellipses="true" - visible="false" - width="275" /> - <text - follows="top|left" - font="SansSerifBigBold" - height="20" - layout="topleft" - left="43" - name="user_name" - text_color="white" - top_delta="0" - translate="false" - value="TestString PleaseIgnore" - use_ellipses="true" - visible="true" - width="250" /> - <text - follows="top|left" - font="SansSerifBold" - height="20" - layout="topleft" - left_delta="0" - name="user_name_small" - text_color="white" - top_delta="-4" - translate="false" - value="TestString PleaseIgnore" - use_ellipses="true" - visible="false" - wrap="true" - width="245" /> - <text - follows="top|left" - height="13" - layout="topleft" - left="10" - name="user_label" - text_color="LtGray" - top_pad="8" - value="Username:" - width="70" /> - <text - follows="top|left" - height="20" - layout="topleft" - left_pad="0" - name="user_slid" - text_color="EmphasisColor" - font="SansSerifBold" - top_delta="-2" - translate="false" - use_ellipses="true" - value="teststring.pleaseignore" - wrap="true" - width="205" /> - <panel - name="lifes_images_panel" - follows="left|top|right" - height="244" - layout="topleft" - top="65" - left="0" - width="292"> - <panel - follows="left|top" - height="117" - layout="topleft" - left="10" - name="second_life_image_panel" - top="0" - width="282"> - <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left="0" - top="10" - name="second_life_photo_title_text" - text_color="white" - value="[SECOND_LIFE]:" - width="100" /> - <texture_picker - allow_no_texture="true" - default_image_name="None" - enabled="false" - fallback_image="default_profile_picture.j2c" - follows="top|left" - height="124" - layout="topleft" - left="1" - name="2nd_life_pic" - top_pad="0" - width="102" /> - </panel> - <icon - height="102" - image_name="spacer24.tga" - layout="topleft" - name="2nd_life_edit_icon" - label="" - left="11" - top_pad="-92" - tool_tip="Click to select an image" - width="102" /> - </panel> - <text_editor - type="string" - length="1" - follows="left|top|right" - font="SansSerifSmall" - height="102" - layout="topleft" - left="123" - top="90" - max_length="512" - name="sl_description_edit" - width="157" - word_wrap="true"> - </text_editor> - <panel - follows="left|top" - height="117" - layout="topleft" - top_pad="5" - left="10" - name="first_life_image_panel" - width="285"> - <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left="0" - top_pad="10" - name="real_world_photo_title_text" - text_color="white" - value="Real World:" - width="100" /> - <texture_picker - allow_no_texture="true" - default_image_name="None" - enabled="false" - fallback_image="Generic_Person_Large" - follows="top|left" - height="124" - layout="topleft" - left="1" - name="real_world_pic" - top_pad="0" - width="102" /> - </panel> - <icon - height="102" - image_name="spacer24.tga" - layout="topleft" - name="real_world_edit_icon" - label="" - left="11" - top_pad="-92" - tool_tip="Click to select an image" - width="102" /> - <text_editor - type="string" - length="1" - follows="left|top|right" - font="SansSerifSmall" - height="102" - layout="topleft" - left="123" - max_length="512" - top="223" - name="fl_description_edit" - width="157" - word_wrap="true"> - </text_editor> - <text - type="string" - length="1" - follows="left|top" - font="SansSerifSmall" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_homepage_text" - text_color="white" - top_pad="10" - width="100"> - Homepage: - </text> - <line_editor - follows="left|top|right" - font="SansSerifSmall" - height="20" - layout="topleft" - left="10" - top_pad="0" - value="http://" - name="homepage_edit" - width="272"> - </line_editor> - <text - follows="left|top" - font="SansSerifSmall" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_acc_status_text" - text_color="white" - top_pad="10" - value="My Account:" - width="100" /> - <text_editor - allow_scroll="false" - bg_visible="false" - follows="left|top|right" - h_pad="0" - height="28" - layout="topleft" - left="10" - name="acc_status_text" - read_only="true" - top_pad="5" - v_pad="0" - value="Resident. No payment info on file." - width="200" - word_wrap="true" /> - <text - type="string" - follows="left|top" - font="SansSerifSmall" - height="15" - layout="topleft" - left="10" - name="my_account_link" - value="[[URL] Go to My Dashboard]" - width="200" /> - <text - follows="left|top" - font="SansSerifSmall" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_partner_text" - text_color="white" - top_pad="10" - value="My Partner:" - width="150" /> - <panel - follows="left|top|right" - height="15" - layout="topleft" - left="10" - name="partner_data_panel" - width="200"> - <text - follows="left|top|right" - height="12" - initial_value="(retrieving)" - layout="topleft" - left="0" - name="partner_text" - top="0" - use_ellipses="true" - width="280"/> - </panel> - <text - follows="left|top" - height="15" - layout="topleft" - link="true" - left="10" - name="partner_edit_link" - value="[[URL] Edit]" - width="70" /> - </panel> - </panel> - </scroll_container> - <panel - follows="bottom|left|right" - height="28" - left="0" - name="profile_me_buttons_panel" - top_pad="0" - width="313"> - - <layout_stack - follows="bottom|left|right" - height="28" - layout="topleft" - name="bottom_panel_ls" - left="7" - orientation="horizontal" - top_pad="0" - width="295"> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - name="save_changes_btn_lp" - top="0" - auto_resize="true" - width="153"> - <button - follows="bottom|left|right" - height="23" - label="Save Changes" - layout="topleft" - left="1" - name="save_btn" - top="0" - width="152" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="show_on_map_btn_lp" - top="0" - auto_resize="true" - width="154"> - <button - follows="bottom|left|right" - height="23" - label="Cancel" - layout="topleft" - left="1" - name="cancel_btn" - top="0" - width="153" /> - </layout_panel> - </layout_stack> - </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml new file mode 100644 index 0000000000..b72af7221e --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="group_list_item" + top="0" + left="0" + height="16" + width="320" + follows="top|right|left" + layout="topleft" +> + <icon + name="hovered_icon" + top="0" + left="0" + height="16" + width="320" + follows="top|right|left" + layout="topleft" + image_name="ListItem_Over" + visible="false" + /> + <icon + name="selected_icon" + top="0" + left="0" + height="16" + width="320" + follows="top|right|left" + layout="topleft" + image_name="ListItem_Select" + visible="false" + /> + <group_icon + name="group_icon" + top="2" + left="5" + height="14" + width="14" + image_name="Generic_Group" + mouse_opaque="true" + use_draw_context_alpha="false" + /> + <text + name="group_name" + value="Unknown" + top="2" + left_pad="5" + right="-2" + height="16" + follows="left|right" + layout="topleft" + parse_urls="false" + text_color="ScrollUnselectedColor" + use_ellipses="true" + /> + <button + name="visibility_hide_btn" + tool_tip="Hide group on my profile" + top_delta="-3" + left_pad="3" + right="-53" + height="20" + width="20" + follows="right" + image_pressed="Profile_Group_Visibility_Off_Pressed" + image_unselected="Profile_Group_Visibility_Off" + tab_stop="false" + visible="false" + /> + <button + name="visibility_show_btn" + tool_tip="Show group on my profile" + top_delta="0" + right_delta="0" + height="20" + width="20" + follows="right" + image_pressed="Profile_Group_Visibility_On_Pressed" + image_unselected="Profile_Group_Visibility_On" + tab_stop="false" + visible="false" + /> + <button + name="info_btn" + tool_tip="More info" + top_delta="2" + left_pad="3" + right="-30" + height="16" + width="16" + follows="right" + image_pressed="Info_Press" + image_unselected="Info_Over" + tab_stop="false" + /> + <!--*TODO: Should only appear on rollover--> + <button + name="profile_btn" + tool_tip="View profile" + top_delta="-2" + left_pad="5" + right="-3" + height="20" + width="20" + follows="right" + layout="topleft" + image_overlay="Web_Profile_Off" + tab_stop="false" + /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_me.xml b/indra/newview/skins/default/xui/en/panel_me.xml deleted file mode 100644 index 23e7814cad..0000000000 --- a/indra/newview/skins/default/xui/en/panel_me.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - border="false" - follows="all" - height="570" - label="My Profile" - layout="topleft" - left="0" - name="panel_me" - top="0" - width="333"> - <panel - class="panel_picks" - filename="panel_picks.xml" - label="MY PICKS" - help_topic="panel_my_picks_tab" - name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml deleted file mode 100644 index 99c47eb825..0000000000 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ /dev/null @@ -1,190 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - follows="all" - height="570" - layout="topleft" - left="0" - min_height="350" - name="panel_pick_info" - help_topic="profile_pick_info" - top="0" - width="333"> - <button - follows="top|left" - height="24" - image_hover_unselected="BackButton_Over" - image_pressed="BackButton_Press" - image_unselected="BackButton_Off" - layout="topleft" - name="back_btn" - left="10" - tab_stop="false" - top="2" - width="30" - use_draw_context_alpha="false" /> - <text - follows="top|left|right" - font="SansSerifHugeBold" - height="26" - layout="topleft" - left_pad="4" - name="title" - text_color="LtGray" - top="2" - value="Pick Info" - use_ellipses="true" - width="275" /> - <scroll_container - color="DkGray2" - opaque="true" - follows="all" - height="503" - layout="topleft" - left="8" - top_pad="10" - name="profile_scroll" - width="312"> - <panel - name="scroll_content_panel" - follows="left|top|right" - min_height="300" - layout="topleft" - top="0" - background_visible="false" - height="400" - left="0" - width="285"> - <texture_picker - fallback_image="default_land_picture.j2c" - enabled="false" - follows="left|top|right" - height="197" - layout="topleft" - left="11" - name="pick_snapshot" - top="10" - width="272" /> - <text_editor - allow_scroll="false" - bg_visible="false" - follows="left|top|right" - h_pad="0" - height="35" - width="280" - layout="topleft" - font="SansSerifBig" - font.style="BOLD" - left="10" - top_pad="10" - name="pick_name" - read_only="true" - text_color="white" - v_pad="0" - value="[name]" - use_ellipses="true" /> - <text_editor - allow_scroll="false" - bg_visible="false" - follows="left|top|right" - h_pad="0" - height="25" - layout="topleft" - left="10" - name="pick_location" - read_only="true" - width="280" - word_wrap="true" - v_pad="0" - value="[loading...]" /> - <text_editor - bg_readonly_color="DkGray2" - follows="all" - height="100" - width="280" - parse_urls="true" - layout="topleft" - left="10" - top_pad="2" - max_length="1023" - name="pick_desc" - read_only="true" - text_readonly_color="white" - value="[description]" - wrap="true" /> - </panel> - </scroll_container> - <panel - follows="left|right|bottom" - height="23" - layout="topleft" - top_pad="5" - left="8" - name="buttons"> - - <layout_stack - follows="bottom|left|right" - height="23" - layout="topleft" - name="layout_stack1" - left="0" - orientation="horizontal" - top_pad="0" - width="312"> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left="0" - name="layout_panel1" - auto_resize="true" - width="101"> - <button - follows="bottom|left|right" - height="23" - label="Teleport" - layout="topleft" - name="teleport_btn" - top="0" - width="101" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="show_on_map_btn_lp" - auto_resize="true" - width="100"> - <button - follows="bottom|left|right" - height="23" - label="Map" - layout="topleft" - name="show_on_map_btn" - top_pad="0" - width="100" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="23" - layout="bottomleft" - left_pad="3" - name="edit_btn_lp" - auto_resize="true" - width="101"> - <button - follows="bottom|left|right" - height="23" - label="Edit" - layout="topleft" - name="edit_btn" - top_pad="0" - width="101" /> - </layout_panel> - </layout_stack> - </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml deleted file mode 100644 index 8def96cada..0000000000 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ /dev/null @@ -1,227 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel -bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - follows="all" - height="571" - label="Picks" - layout="topleft" - left="8" - name="panel_picks" - top_pad="0" - width="313"> - <string - name="no_picks" - value="No Picks" /> - <string - name="no_classifieds" - value="No Classifieds" /> - <text - type="string" - follows="all" - height="535" - layout="topleft" - left="6" - name="picks_panel_text" - wrap="true" - top="10" - width="313"/> - <accordion - fit_parent="true" - follows="all" - height="514" - layout="topleft" - left="0" - name="accordion" - top="0" - single_expansion="true" - width="313"> - <accordion_tab - layout="topleft" - height="235" - min_height="150" - name="tab_picks" - title="Picks" - visible="false"> - <flat_list_view - color="DkGray2" - follows="all" - layout="topleft" - left="0" - name="picks_list" - opaque="true" - top="0" - width="313" /> - </accordion_tab> - <accordion_tab - layout="topleft" - height="235" - name="tab_classifieds" - title="Classifieds" - visible="false"> - <flat_list_view - color="DkGray2" - follows="all" - layout="topleft" - left="0" - name="classifieds_list" - opaque="true" - top="0" - width="313" /> - </accordion_tab> - </accordion> - <panel - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - bevel_style="none" - enabled="false" - follows="bottom|left|right" - left="1" - height="27" - label="bottom_panel" - layout="topleft" - name="edit_panel" - top_pad="0" - width="312"> - - <layout_stack - follows="bottom|left|right" - height="23" - layout="bottomleft" - name="edit_panel_ls" - left="10" - orientation="horizontal" - top_pad="0" - width="293"> - - <layout_panel - follows="bottom|left" - height="18" - layout="bottomleft" - left="0" - name="gear_menu_btn" - auto_resize="true" - width="51"> - <button - follows="bottom|left" - height="18" - image_disabled="AddItem_Disabled" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - layout="topleft" - left="0" - name="new_btn" - tool_tip="Create a new pick or classified at the current location" - top="0" - width="18" /> - </layout_panel> - - <layout_panel - follows="bottom|right" - height="18" - layout="bottomleft" - name="trash_btn_lp" - auto_resize="true" - width="18"> - <button - follows="bottom|right" - height="18" - image_disabled="TrashItem_Disabled" - image_selected="TrashItem_Press" - image_unselected="TrashItem_Off" - layout="topleft" - name="trash_btn" - top="0" - width="18" /> - </layout_panel> - - </layout_stack> - </panel> - - <panel - bg_opaque_color="DkGray" - background_visible="true" - background_opaque="true" - follows="bottom|left|right" - layout="topleft" - left="0" - height="30" - name="buttons_cucks" - top_pad="0" - width="313"> - - <layout_stack - follows="bottom|left|right" - height="28" - layout="topleft" - left="2" - name="buttons_cucks_ls" - orientation="horizontal" - top="0" - width="313"> - - <layout_panel - follows="bottom|left|right" - height="28" - layout="topleft" - left="0" - name="info_btn_lp" - auto_resize="true" - top="0" - width="95"> - <button - enabled="false" - follows="top|left|right" - height="23" - label="Info" - layout="topleft" - name="info_btn" - tab_stop="false" - tool_tip="Show pick information" - width="95" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="28" - layout="bottomleft" - left_pad="2" - name="teleport_btn_lp" - auto_resize="true" - width="117"> - <button - enabled="false" - follows="top|left|right" - height="23" - label="Teleport" - layout="topleft" - name="teleport_btn" - tab_stop="false" - tool_tip="Teleport to the corresponding area" - width="117" /> - </layout_panel> - - <layout_panel - follows="bottom|left|right" - height="28" - layout="bottomleft" - name="show_on_map_btn_lp" - auto_resize="true" - left_pad="2" - width="90"> - <button - enabled="false" - follows="top|left|right" - height="23" - label="Map" - layout="topleft" - name="show_on_map_btn" - tab_stop="false" - tool_tip="Show the corresponding area on the World Map" - width="88" /> - </layout_panel> - </layout_stack> - </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_classified.xml b/indra/newview/skins/default/xui/en/panel_profile_classified.xml new file mode 100644 index 0000000000..c9e8b242d4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classified.xml @@ -0,0 +1,830 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_classified" + top="0" + left="0" + height="420" + width="315" + follows="all" + layout="topleft" + help_topic="panel_profile_classified" + min_height="250" +> + <panel.string + name="type_mature" + > + Moderate + </panel.string> + <panel.string + name="type_pg" + > + General Content + </panel.string> + <panel.string + name="l$_price" + > + L$[PRICE] + </panel.string> + <panel.string + name="click_through_text_fmt" + > + [TELEPORT] teleport, [MAP] map, [PROFILE] profile + </panel.string> + <panel.string + name="date_fmt" + > + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string + name="auto_renew_on" + > + Enabled + </panel.string> + <panel.string + name="auto_renew_off" + > + Disabled + </panel.string> + <panel.string + name="location_notice" + > + (will update after save) + </panel.string> + <string + name="publish_label" + > + Publish + </string> + <string + name="save_label" + > + Save + </string> + + <layout_stack + name="main_classifieds_stack" + top="0" + bottom="-1" + left="0" + width="310" + follows="all" + layout="topleft" + orientation="vertical" + animate="false" + > + <layout_panel + follows="all" + width="310" + height="300" + layout="topleft" + name="scroll_layout_panel" + auto_resize="true"> + <scroll_container + name="profile_scroll" + top="0" + left="0" + height="300" + width="310" + follows="all" + layout="topleft" + color="DkGray2" + opaque="true" + reserve_scroll_corner="false" + > + <panel + name="info_scroll_content_panel" + top="0" + left="0" + height="562" + width="280" + follows="left|top|right" + layout="topleft" + background_visible="false" + min_height="200" + > + <texture_picker + name="classified_snapshot" + enabled="false" + top="0" + left="10" + height="161" + width="260" + follows="left|top" + layout="topleft" + fallback_image="default_land_picture.j2c" + /> + <icon + name="edit_icon" + label="" + tool_tip="Click to select an image" + top="0" + left="0" + height="161" + width="260" + layout="topleft" + follows="left|top" + image_name="spacer24.tga" + visible="false" + /> + <layout_stack + name="info_panel" + top="145" + left="0" + height="375" + width="310" + follows="all" + layout="topleft" + visible="true" + animate="false" + orientation="vertical" + > + <layout_panel + name="main_info_panel" + top="0" + left="0" + height="160" + width="280" + follows="all" + layout="topleft" + auto_resize="false" + > + <text_editor + name="classified_name" + top="0" + left="10" + height="35" + width="270" + follows="left|top|right" + layout="topleft" + allow_scroll="false" + bg_visible="false" + font="SansSerifBig" + font.style="BOLD" + h_pad="0" + read_only="true" + text_color="white" + use_ellipses="true" + v_pad="0" + > + [name] + </text_editor> + <text + name="classified_location_label" + value="Location:" + top_pad="-2" + left="10" + height="10" + width="250" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="classified_location" + value="[loading...]" + top_pad="5" + left="10" + height="30" + width="280" + follows="left|top" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + read_only="true" + v_pad="0" + word_wrap="true" + /> + <text + name="content_type_label" + value="Content Type:" + top_pad="10" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <icon + name="content_type_moderate" + top_pad="-11" + left_pad="0" + height="16" + width="18" + follows="top|left" + layout="topleft" + image_name="Parcel_M_Light" + /> + <icon + name="content_type_general" + top_delta="0" + left_delta="0" + height="16" + width="18" + follows="top|left" + layout="topleft" + image_name="Parcel_PG_Light" + /> + <text_editor + name="content_type" + value="[content type]" + top_delta="1" + left_pad="2" + height="18" + width="130" + follows="left|top|right" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + read_only="true" + v_pad="0" + /> + <text + name="category_label" + value="Category:" + top_pad="0" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="category" + value="[category]" + top_pad="-10" + left_pad="0" + height="18" + width="150" + follows="left|top|right" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + parse_urls="true" + read_only="true" + v_pad="0" + /> + <text + name="creation_date_label" + value="Creation date:" + top_pad="0" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="creation_date" + value="[date]" + tool_tip="Creation date" + top_pad="-10" + left_pad="0" + height="16" + width="150" + follows="left|top" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + halign="left" + read_only="true" + v_pad="0" + /> + <text + name="price_for_listing_label" + value="Price for listing:" + top_pad="5" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="price_for_listing" + tool_tip="Price for listing." + top_pad="-10" + left_pad="0" + height="16" + width="105" + follows="left|top" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + halign="left" + read_only="true" + v_pad="0" + > + [PRICE] + </text_editor> + </layout_panel> + <layout_panel + name="clickthrough_layout_panel" + top="0" + left="0" + height="16" + width="290" + follows="all" + layout="topleft" + auto_resize="false" + > + <text + name="click_through_label" + value="Clicks:" + top_pad="0" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="click_through_text" + value="[clicks]" + tool_tip="Click through data" + top_pad="-10" + left_pad="0" + height="16" + width="150" + follows="left|top" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + halign="left" + read_only="true" + v_pad="0" + /> + </layout_panel> + <layout_panel + name="auto_renew_layout_panel" + top="0" + left="0" + height="16" + width="290" + follows="all" + layout="topleft" + auto_resize="false" + > + <text + name="auto_renew_label" + value="Auto renew:" + top="0" + left="10" + height="10" + width="140" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text + name="auto_renew" + value="Enabled" + top_pad="-10" + left_pad="0" + height="16" + width="150" + follows="top|left" + layout="topleft" + /> + </layout_panel> + <layout_panel + name="descr_layout_panel" + top="0" + left="0" + height="220" + width="290" + follows="all" + layout="topleft" + auto_resize="true" + > + <text + name="classified_desc_label" + value="Description:" + top="0" + left="10" + height="10" + width="250" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <text_editor + name="classified_desc" + trusted_content="false" + value="[description]" + top_pad="7" + left="10" + height="200" + width="280" + follows="all" + layout="topleft" + allow_scroll="false" + bg_visible="false" + h_pad="0" + max_length="1023" + parse_urls="true" + read_only="true" + v_pad="0" + word_wrap="true" + /> + </layout_panel> + </layout_stack> + <panel + name="edit_panel" + top="145" + left="0" + height="420" + width="320" + follows="left|top|right" + layout="topleft" + visible="false" + > + <text + name="Name:" + top="0" + left="10" + height="15" + width="280" + follows="left|top" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Title: + </text> + <line_editor + name="classified_name_edit" + top_pad="2" + left="10" + height="20" + width="273" + follows="left|top|right" + layout="topleft" + font="SansSerif" + max_length_bytes="30" + prevalidate_callback="ascii" + commit_on_focus_lost="false" + text_color="black" + /> + <text + name="description_label" + top_pad="10" + left="10" + height="15" + width="280" + follows="left|top" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Description: + </text> + <text_editor + name="classified_desc_edit" + top_pad="2" + left="10" + height="100" + width="273" + follows="left|top|right" + layout="topleft" + max_length="256" + text_color="black" + word_wrap="true" + /> + <text + name="location_label" + top_pad="10" + left="10" + height="15" + width="280" + follows="left|top" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Location: + </text> + <text + name="classified_location_edit" + top_pad="2" + left="10" + right="-10" + height="30" + width="280" + follows="left|top" + layout="topleft" + length="1" + type="string" + word_wrap="true" + > + loading... + </text> + <button + name="set_to_curr_location_btn" + label="Set to Current Location" + top_pad="5" + left="10" + height="23" + width="200" + follows="left|top" + layout="topleft" + /> + <text + name="category_label" + value="Category:" + top_pad="10" + left="10" + height="10" + width="120" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <combo_box + name="category_edit" + label="" + top_delta="-3" + left_pad="0" + height="23" + width="156" + follows="left|top" + /> + <text + name="content_type_label" + value="Content type:" + top_pad="15" + left="10" + height="10" + width="120" + follows="left|top" + layout="topleft" + font.style="BOLD" + text_color="white" + /> + <icons_combo_box + name="content_type_edit" + label="General Content" + top_delta="-3" + left_pad="0" + height="23" + width="156" + follows="left|top" + layout="topleft" + > + <icons_combo_box.drop_down_button + image_overlay="Parcel_PG_Light" + image_overlay_alignment="left" + imgoverlay_label_space="3" + pad_left="3" + /> + <icons_combo_box.item + name="mature_ci" + label="Moderate Content" + value="Mature" + > + <item.columns + value="Parcel_M_Light" + width="20" + halign="center" + type="icon" + /> + </icons_combo_box.item> + <icons_combo_box.item + name="pg_ci" + label="General Content" + value="PG" + > + <item.columns + value="Parcel_PG_Light" + width="20" + halign="center" + type="icon" + /> + </icons_combo_box.item> + </icons_combo_box> + <check_box + name="auto_renew_edit" + label="Auto renew each week" + top_pad="10" + left="10" + height="16" + width="250" + layout="topleft" + /> + </panel> + </panel> + </scroll_container> + </layout_panel> + + <layout_panel + follows="all" + width="310" + height="25" + layout="topleft" + name="util_buttons_lp" + auto_resize="true"> + <layout_stack + name="util_buttons_stack" + bottom="-1" + left="1" + right="-1" + height="25" + follows="left|bottom|right" + layout="topleft" + orientation="horizontal" + animate="false" + > + <layout_panel + follows="all" + layout="topleft" + name="util_resizer_left" + auto_resize="true" + user_resize="false" + width="1"/> + + <layout_panel + follows="all" + height="25" + layout="topleft" + left="0" + name="teleport_btn_lp" + auto_resize="false" + top="0" + width="85"> + <button + name="teleport_btn" + label="Teleport" + top="0" + left="0" + height="23" + max_width="101" + width="85" + follows="bottom|left|right" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + height="25" + layout="bottomleft" + left_pad="2" + name="map_btn_lp" + auto_resize="false" + max_width="101" + width="85"> + <button + name="show_on_map_btn" + label="Map" + top="0" + left="0" + height="23" + width="85" + follows="bottom|left|right" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + height="25" + layout="bottomleft" + left_pad="2" + name="edit_btn_lp" + auto_resize="false" + max_width="101" + width="85"> + <button + name="edit_btn" + label="Edit" + top="0" + left="0" + height="23" + width="85" + follows="bottom|left|right" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="topleft" + name="util_resizer_right" + auto_resize="true" + width="1"> + </layout_panel> + </layout_stack> + </layout_panel> + <layout_panel + follows="all" + width="310" + height="41" + layout="topleft" + name="publish_layout_panel" + auto_resize="false"> + <view_border + bevel_style="none" + height="0" + follows="left|top|right" + layout="topleft" + left="0" + name="publish_emphasis_border" + top="5" + width="310"/> + <layout_stack + name="publish_stack" + left="1" + right="-1" + top="11" + height="25" + follows="left|top|right" + layout="topleft" + orientation="horizontal" + animate="false" + > + <layout_panel + follows="all" + layout="topleft" + name="pbl_resizer_left" + auto_resize="true" + user_resize="false" + width="1"/> + + <layout_panel + follows="all" + layout="topleft" + name="save_btn_lp" + auto_resize="false" + width="134"> + <button + name="save_changes_btn" + label="[LABEL]" + top="0" + left="0" + left_pad="5" + height="23" + width="134" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="cancel_btn_lp" + auto_resize="false" + width="134"> + <button + name="cancel_btn" + label="Cancel" + top="0" + left="0" + height="23" + width="134" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="topleft" + name="pbl_resizer_right" + auto_resize="true" + width="1"> + </layout_panel> + + </layout_stack> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml new file mode 100644 index 0000000000..2b2f60e0c2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_classifieds" + label="Classified" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <string + name="no_classifieds" + value="No Classifieds" + /> + + <layout_stack + name="main_stack" + top="0" + left="0" + right="-1" + bottom="-1" + follows="all" + layout="topleft" + animate="false" + orientation="vertical"> + <layout_panel + name="buttons_header" + follows="all" + layout="topleft" + height="50" + auto_resize="false" + user_resize="false"> + <button + name="new_btn" + label="New..." + tool_tip="Create a new classified at the current location" + enabled="false" + top="25" + left="5" + height="20" + width="70" + follows="left|top" + layout="topleft" + visible="true" + /> + <button + name="delete_btn" + label="Delete..." + tool_tip="Delete currently selected classified" + enabled="false" + left_pad="5" + height="20" + width="70" + follows="left|top" + layout="topleft" + visible="true" + /> + </layout_panel> + <layout_panel + name="main_body" + follows="all" + layout="topleft" + height="430" + auto_resize="true" + user_resize="false"> + <tab_container + name="tab_classifieds" + top="0" + bottom="-1" + left="4" + right="-4" + follows="all" + layout="topleft" + halign="left" + tab_position="left" + tab_width="150" + use_ellipses="true" + /> + + <layout_stack + name="indicator_stack" + top="220" + left="0" + right="-1" + height="28" + follows="top|left|right" + layout="topleft" + animate="false" + orientation="horizontal"> + <layout_panel + name="indicator_spacer_left" + follows="all" + layout="topleft" + width="100" + auto_resize="true" + user_resize="false"> + </layout_panel> + <layout_panel + name="buttons_header" + follows="all" + layout="topleft" + width="25" + auto_resize="false" + user_resize="false"> + <loading_indicator + name="progress_indicator" + top="1" + left="1" + height="23" + width="23" + follows="top|left" + layout="topleft" + visible="false" + /> + </layout_panel> + <layout_panel + name="indicator_spacer_right" + follows="all" + layout="topleft" + width="100" + auto_resize="true" + user_resize="false"> + </layout_panel> + </layout_stack> + <text + name="classifieds_panel_text" + top="250" + left="110" + right="-110" + height="25" + follows="left|top|right" + layout="topleft" + halign="center" + mouse_opaque="false" + wrap="true" + > + Loading... + </text> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml new file mode 100644 index 0000000000..ca1e405a62 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_firstlife" + label="Profile" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <loading_indicator + name="progress_indicator" + top="5" + right="-10" + height="23" + width="23" + follows="top|right" + layout="topleft" + visible="false" + /> + <icon + name="real_world_pic" + image_name="Generic_Person_Large" + follows="top|left" + layout="topleft" + top="10" + left="8" + height="160" + width="160"/> + <loading_indicator + name="image_upload_indicator" + top="79" + left="77" + height="23" + width="23" + follows="top|left" + layout="topleft" + visible="false"/> + <button + name="fl_upload_image" + label="Upload Photo" + top="102" + left="175" + height="20" + width="120" + follows="top|left" + layout="topleft"/> + <button + name="fl_change_image" + label="Change Photo" + top_pad="5" + left="175" + height="20" + width="120" + follows="top|left" + layout="topleft"/> + <button + name="fl_remove_image" + label="Remove Photo" + top_pad="5" + left_delta="0" + height="20" + width="120" + follows="top|left" + layout="topleft"/> + <text_editor + name="fl_description_edit" + trusted_content="false" + enabled="false" + top="180" + left="6" + right="-6" + height="224" + follows="all" + layout="topleft" + bg_readonly_color="Transparent" + border_visible="true" + max_length="65000" + parse_urls="true" + word_wrap="true" + /> + <button + name="fl_save_changes" + label="Save" + top_pad="5" + right="-108" + height="20" + width="80" + enabled="false" + follows="right|bottom" + layout="topleft"/> + <button + name="fl_discard_changes" + label="Discard" + top_delta="0" + right="-4" + height="20" + width="100" + enabled="false" + follows="right|bottom" + layout="topleft"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_notes.xml b/indra/newview/skins/default/xui/en/panel_profile_notes.xml new file mode 100644 index 0000000000..16e7365042 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_notes.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_notes" + label="Notes & Privacy" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <loading_indicator + name="progress_indicator" + top="3" + right="-10" + height="23" + width="23" + follows="top|right" + layout="topleft" + visible="false" + /> + <text + name="status_message" + value="Make notes about this person here. No one else can see your notes." + top="6" + left="6" + right="-6" + height="16" + follows="left|top|right" + layout="topleft" + font.style="BOLD" + /> + <text_editor + name="notes_edit" + enabled="false" + top="28" + left="6" + right="-6" + bottom="-26" + follows="all" + layout="topleft" + max_length="65530" + word_wrap="true" + /> + <button + name="notes_save_changes" + label="Save" + bottom="-1" + right="-108" + height="20" + width="80" + enabled="false" + follows="bottom|right" + layout="topleft"/> + <button + name="notes_discard_changes" + label="Discard" + bottom="-1" + right="-4" + height="20" + width="100" + enabled="false" + follows="bottom|right" + layout="topleft"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_pick.xml b/indra/newview/skins/default/xui/en/panel_profile_pick.xml new file mode 100644 index 0000000000..3e91640093 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_pick.xml @@ -0,0 +1,314 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_pick_info" + top="0" + left="0" + height="360" + width="310" + follows="all" + layout="topleft" + help_topic="profile_pick_info" +> + <panel.string + name="location_notice" + > + (will update after save) + </panel.string> + + <layout_stack + name="main_pick_stack" + left="1" + right="-1" + top="0" + bottom="-1" + follows="all" + layout="topleft" + orientation="vertical" + animate="false"> + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="main_pick_lp" + auto_resize="true" + height="314"> + <texture_picker + name="pick_snapshot" + top="10" + left="10" + height="161" + width="260" + follows="left|top" + layout="topleft" + fallback_image="default_land_picture.j2c" + /> + <text + name="title_label" + top_pad="-15" + left="10" + height="15" + width="280" + follows="left|top" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Title: + </text> + <line_editor + name="pick_name" + enabled="false" + top_pad="2" + left="10" + height="20" + width="290" + follows="left|right|top" + layout="topleft" + /> + <text + name="description_label" + top_pad="10" + left="10" + height="15" + width="280" + follows="left|top" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Description: + </text> + <text_editor + name="pick_desc" + trusted_content="false" + always_show_icons="true" + enabled="false" + top_pad="2" + left="10" + height="45" + width="290" + follows="all" + layout="topleft" + allow_html="true" + border_visible="true" + h_pad="4" + max_length="1023" + v_pad="3" + word_wrap="true" + /> + <text + name="location_label" + bottom="-25" + left="10" + height="15" + width="280" + follows="left|right|bottom" + layout="topleft" + font="SansSerifSmall" + font.style="BOLD" + length="1" + text_color="white" + type="string" + > + Location: + </text> + <line_editor + name="pick_location" + enabled="false" + bottom="-1" + left="10" + height="23" + width="290" + follows="left|right|bottom" + layout="topleft" + length="1" + type="string" + > + Loading... + </line_editor> + </layout_panel> + + + <layout_panel + follows="all" + layout="bottomleft" + name="save_changes_lp" + auto_resize="false" + height="25"> + <layout_stack + name="save_changes_stack" + left="1" + right="-1" + top="0" + height="25" + follows="left|top|right" + layout="topleft" + orientation="horizontal" + animate="false"> + + <layout_panel + follows="all" + layout="topleft" + name="util_resizer_left" + auto_resize="true" + width="1"> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="map_btn_lp" + auto_resize="false" + width="100"> + <button + name="show_on_map_btn" + label="Show on Map" + left="0" + top="0" + height="23" + width="100" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="tp_btn_lp" + auto_resize="false" + width="100"> + <button + name="teleport_btn" + label="Teleport" + left="0" + top="0" + height="23" + width="100" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="topleft" + name="util_resizer_right" + auto_resize="true" + width="1"> + </layout_panel> + + </layout_stack> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + name="save_changes_lp" + auto_resize="false" + height="41"> + <view_border + bevel_style="none" + height="0" + follows="left|top|right" + layout="topleft" + left="0" + name="save_emphasis_border" + top="5" + width="310"/> + <layout_stack + name="save_changes_stack" + left="1" + right="-1" + top="11" + height="25" + follows="left|top|right" + layout="topleft" + orientation="horizontal" + animate="false"> + + <layout_panel + follows="all" + layout="topleft" + name="save_resizer_left" + auto_resize="true" + width="1"> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="create_btn_lp" + auto_resize="false" + width="130"> + <button + name="create_changes_btn" + label="Create Pick" + left="0" + top="0" + height="23" + width="130" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="save_btn_lp" + auto_resize="false" + width="130"> + <button + name="save_changes_btn" + label="Save Pick" + left="0" + top="0" + height="23" + width="130" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="bottomleft" + left_pad="2" + name="cancel_btn_lp" + auto_resize="false" + width="130"> + <button + name="cancel_changes_btn" + label="Cancel" + left="0" + top="0" + height="23" + width="130" + follows="left|top" + layout="topleft" + /> + </layout_panel> + + <layout_panel + follows="all" + layout="topleft" + name="save_resizer_right" + auto_resize="true" + width="1"> + </layout_panel> + + </layout_stack> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_picks.xml b/indra/newview/skins/default/xui/en/panel_profile_picks.xml new file mode 100644 index 0000000000..44d5c448c0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_picks.xml @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_picks" + label="Picks" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <string + name="no_picks" + value="No Picks" + /> + + <layout_stack + name="main_stack" + top="0" + left="0" + right="-1" + bottom="-1" + follows="all" + layout="topleft" + animate="false" + orientation="vertical"> + <layout_panel + name="buttons_header" + follows="all" + layout="topleft" + height="50" + auto_resize="false" + user_resize="false"> + <text + name="header_text" + top="5" + left="5" + right="-5" + height="16" + follows="left|top|right" + layout="topleft" + halign="center" + > + Tell everyone about your favorite places in Second Life. + </text> + <button + name="new_btn" + label="New..." + tool_tip="Create a new pick at the current location" + enabled="false" + top_pad="4" + left="5" + height="20" + width="70" + follows="left|top" + layout="topleft" + visible="false" + /> + <button + name="delete_btn" + label="Delete..." + tool_tip="Delete currently selected pick" + enabled="false" + left_pad="5" + height="20" + width="70" + follows="left|top" + layout="topleft" + visible="false" + /> + </layout_panel> + <layout_panel + name="main_body" + follows="all" + layout="topleft" + height="430" + auto_resize="true" + user_resize="false"> + <tab_container + name="tab_picks" + top="0" + bottom="-5" + left="4" + right="-4" + tab_width="150" + follows="all" + layout="topleft" + halign="left" + tab_position="left" + use_ellipses="true" + /> + + <layout_stack + name="indicator_stack" + top="220" + left="0" + right="-1" + height="28" + follows="top|left|right" + layout="topleft" + animate="false" + orientation="horizontal"> + <layout_panel + name="indicator_spacer_left" + follows="all" + layout="topleft" + width="100" + auto_resize="true" + user_resize="false"> + </layout_panel> + <layout_panel + name="buttons_header" + follows="all" + layout="topleft" + width="25" + auto_resize="false" + user_resize="false"> + <loading_indicator + name="progress_indicator" + top="1" + left="1" + height="23" + width="23" + follows="top|left" + layout="topleft" + visible="false" + /> + </layout_panel> + <layout_panel + name="indicator_spacer_right" + follows="all" + layout="topleft" + width="100" + auto_resize="true" + user_resize="false"> + </layout_panel> + </layout_stack> + <text + name="picks_panel_text" + top="250" + left="100" + right="-100" + height="25" + follows="left|top|right" + layout="topleft" + halign="center" + mouse_opaque="false" + wrap="true" + > + Loading... + </text> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml new file mode 100644 index 0000000000..551b477876 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -0,0 +1,549 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile" + label="Profile" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <string + name="date_format" + value="SL birthdate: [mth,datetime,slt] [day,datetime,slt], [year,datetime,slt]" /> + <string + name="age_format" + value="[AGE]" /> + <string + name="partner_text" + value="Partner: [LINK]" /> + <string + name="CaptionTextAcctInfo"> +Account: [ACCTTYPE] +[PAYMENTINFO] + </string> + + <layout_stack + name="image_stack" + top="8" + left="6" + bottom="-1" + width="160" + border_size="0" + follows="left|top|bottom" + layout="topleft" + animate="false" + orientation="vertical"> + <layout_panel + name="image_panel" + follows="all" + layout="topleft" + width="160" + height="160" + auto_resize="false" + user_resize="false"> + + <icon + name="2nd_life_pic" + image_name="Generic_Person_Large" + layout="topleft" + follows="all" + interactable="true" + top="0" + left="2" + bottom="-1" + right="-1"/> + + <loading_indicator + name="image_upload_indicator" + top="69" + left="69" + height="23" + width="23" + follows="top|left" + layout="topleft" + visible="false"/> + </layout_panel> + + <layout_panel + name="basics_panel" + follows="all" + layout="topleft" + height="54" + auto_resize="false" + user_resize="false" + > + <line_editor + name="user_name" + border_thickness="0" + use_bg_color="false" + background_image_disabled="" + background_image_focused="" + enabled="false" + value="(loading...)" + top="4" + left="3" + right="-1" + height="16" + follows="left|top|right" + layout="topleft"/> + + <line_editor + name="sl_birth_date" + border_thickness="0" + use_bg_color="false" + background_image_disabled="" + background_image_focused="" + enabled="false" + value="(loading...)" + top_pad="0" + left_delta="0" + right="-1" + height="16" + follows="left|top|right" + layout="topleft"/> + + <line_editor + name="user_age" + border_thickness="0" + use_bg_color="false" + background_image_disabled="" + background_image_focused="" + enabled="false" + value="(loading...)" + top_pad="0" + left_delta="0" + right="-1" + height="16" + follows="left|top|right" + layout="topleft"/> + </layout_panel> + <layout_panel + name="partner_layout" + follows="all" + layout="topleft" + height="30" + auto_resize="false" + user_resize="false" + visible="true"> + <text + type="string" + name="partner_link" + value="Partner: (loading...)" + top="0" + left="5" + right="-1" + height="28" + follows="left|top|right" + layout="topleft" + translate="false" + use_ellipses="true" + word_wrap="true" + visible="true"/> + </layout_panel> + + <layout_panel + name="partner_spacer_layout" + follows="all" + layout="topleft" + height="14" + auto_resize="false" + user_resize="false" + visible="true"> + </layout_panel> + + <layout_panel + name="frind_layout" + follows="all" + layout="topleft" + height="16" + auto_resize="false" + user_resize="false" + visible="false"> + <text + name="frind_text" + value="You are friends" + text_color="ConversationFriendColor" + top="0" + left="5" + right="-1" + height="16" + follows="left|top|right" + layout="topleft" + translate="false" + visible="true"/> + </layout_panel> + <layout_panel + name="online_layout" + follows="all" + layout="topleft" + height="16" + auto_resize="false" + user_resize="false" + visible="false"> + <icon + name="online_icon" + image_name="Profile_Friend_Online" + layout="topleft" + follows="left|top" + top="0" + left="5" + height="10" + width="10"/> + <text + name="online_text" + value="Online" + top="0" + left="18" + right="-1" + height="16" + follows="left|top|right" + layout="topleft" + translate="false" + visible="true"/> + </layout_panel> + <layout_panel + name="offline_layout" + follows="all" + layout="topleft" + height="16" + auto_resize="false" + user_resize="false" + visible="false"> + <icon + name="offline_icon" + image_name="Profile_Friend_Offline" + layout="topleft" + follows="left|top" + top="0" + left="5" + height="10" + width="10"/> + <text + name="offline_text" + value="Offline" + top="0" + left="18" + right="-1" + height="16" + follows="left|top|right" + layout="topleft" + translate="false" + visible="true"/> + </layout_panel> + <layout_panel + name="account_layout" + follows="all" + layout="topleft" + height="33" + auto_resize="false" + user_resize="false"> + <text + name="account_info" + value="Account: (loading...)" + top="0" + left="5" + right="-1" + height="16" + follows="left|top|right" + layout="topleft" + word_wrap="true"/> + </layout_panel> + <layout_panel + name="indicator_stack" + follows="all" + layout="topleft" + height="33" + auto_resize="false" + user_resize="false"> + <loading_indicator + name="progress_indicator" + left="67" + top="0" + height="23" + width="23" + follows="left|top" + layout="topleft" + visible="true"/> + </layout_panel> + <layout_panel + name="settings_panel" + follows="all" + layout="topleft" + height="50" + auto_resize="false" + user_resize="false"> + <!-- only for self --> + <text + name="search_label" + value="Show my profile in search:" + top="1" + left="6" + right="-1" + height="16" + follows="left|top|right" + layout="topleft"/> + <combo_box + name="show_in_search" + tool_tip="Let people see you in search results" + left="1" + top="18" + height="23" + width="140" + follows="left|top" + layout="topleft" + visible="true" + enabled="false"> + <combo_box.item + name="Hide" + label="Hide" + value="0" /> + <combo_box.item + name="Show" + label="Show" + value="1" /> + </combo_box> + </layout_panel> + + <layout_panel + name="menu_panel" + follows="all" + layout="topleft" + height="55" + auto_resize="false" + user_resize="false" + > + <menu_button + layout="topleft" + follows="left|top" + left="1" + top="25" + height="25" + width="140" + label="Actions" + halign="left" + image_unselected="DropDown_Off" + image_selected="DropDown_On" + image_pressed="DropDown_Press" + image_pressed_selected="DropDown_Press" + image_disabled="DropDown_Disabled" + name="agent_actions_menu" /> + </layout_panel> + </layout_stack> + + <layout_stack + name="main_stack" + top="8" + left="168" + bottom="-1" + right="-1" + follows="all" + layout="topleft" + animate="false" + orientation="vertical"> + <layout_panel + name="display_name_panel" + follows="all" + layout="topleft" + height="24" + auto_resize="false" + user_resize="false"> + <line_editor + name="display_name" + border_thickness="0" + use_bg_color="false" + background_image_disabled="" + background_image_focused="" + enabled="false" + value="(loading...)" + font="SansSerifBigLarge" + top="0" + left="6" + height="19" + right="-86" + follows="left|top|right" + layout="topleft"/> + + <icon + tool_tip="Friend can see my online status" + mouse_opaque="true" + name="can_see_online" + image_name="Profile_Perm_Online_Enabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-61" + height="24" + width="24" + left_pad="2" /> + + <icon + tool_tip="Friend can not see my online status" + mouse_opaque="true" + name="cant_see_online" + image_name="Profile_Perm_Online_Disabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-61" + height="24" + width="24" + left_pad="2" /> + + <icon + tool_tip="Friend can see me on map" + mouse_opaque="true" + name="can_see_on_map" + image_name="Profile_Perm_Find_Enabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-30" + height="24" + width="24" + left_pad="2" /> + + <icon + tool_tip="Friend can not see me on map" + mouse_opaque="true" + name="cant_see_on_map" + image_name="Profile_Perm_Find_Disabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-30" + height="24" + width="24" + left_pad="2" /> + + <icon + tool_tip="Friend can edit my objects" + mouse_opaque="true" + name="can_edit_objects" + image_name="Profile_Perm_Objects_Enabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-1" + height="24" + width="24" + left_pad="2" /> + + <icon + tool_tip="Friend can not edit my objects" + mouse_opaque="true" + name="cant_edit_objects" + image_name="Profile_Perm_Objects_Disabled" + layout="topleft" + follows="right|top" + interactable="true" + top="0" + right="-1" + height="24" + width="24" + left_pad="2" /> + + </layout_panel> + + <layout_panel + name="about_panel" + follows="all" + layout="topleft" + height="159" + auto_resize="true" + user_resize="false"> + <text_editor + name="sl_description_edit" + trusted_content="false" + always_show_icons="true" + commit_on_focus_lost="false" + enabled="false" + top="0" + left="2" + right="-1" + bottom="-1" + follows="all" + layout="topleft" + bg_readonly_color="Transparent" + border_visible="true" + font="SansSerifSmall" + h_pad="2" + max_length="65000" + parse_urls="true" + word_wrap="true" + /> + </layout_panel> + <layout_panel + name="about_buttons_panel" + follows="all" + layout="topleft" + height="34" + auto_resize="false" + user_resize="false"> + <button + name="save_description_changes" + label="Save" + top="1" + right="-105" + height="20" + width="80" + enabled="false" + follows="top|right" + layout="topleft"/> + <button + name="discard_description_changes" + label="Discard" + top="1" + right="-1" + height="20" + width="100" + enabled="false" + follows="top|right" + layout="topleft"/> + <view_border + bevel_style="none" + height="0" + layout="topleft" + left="0" + name="cost_text_border" + top_pad="9" + width="492"/> + </layout_panel> + + <layout_panel + name="groups_panel" + follows="all" + layout="topleft" + height="159" + auto_resize="true" + user_resize="false"> + <text + name="group_label" + value="Group memberships" + top="1" + left="2" + right="-1" + height="16" + follows="left|top|right" + layout="topleft"/> + <group_list + name="group_list" + top="18" + left="2" + right="-1" + bottom="-1" + follows="all" + layout="topleft" + border_visible="true" + color="ScrollBgWriteableColor" + for_agent="false"/> + + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_web.xml b/indra/newview/skins/default/xui/en/panel_profile_web.xml new file mode 100644 index 0000000000..e0cb4d3d06 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_web.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_web" + label="Web" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> + <panel.string + name="LoadTime" + value="Load Time: [TIME] seconds" + /> + <web_browser + name="profile_html" + top="10" + bottom="-18" + left="10" + right="-10" + follows="all" + layout="topleft" + start_url="" + /> + <text + name="status_text" + bottom="-4" + left="110" + right="-110" + follows="bottom|left|right" + layout="topleft" + halign="center" + parse_urls="false" + /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index 8243c2715d..2aaea04a6d 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -86,7 +86,7 @@ name="detail_texture_text" top="110" width="300"> - Terrain Textures (requires 512x512, 24 bit .tga files) + Terrain Textures (requires 1024x1024, 24 bit .tga files) </text> <texture_picker follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 90f32ae452..c7052bb737 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -11,6 +11,36 @@ name="Texture" top="0" width="295"> + <panel.string + name="paste_error_face_selection_mismatch"> + When multiple faces are copied, the target object must have the same number of faces selected. + </panel.string> + <panel.string + name="paste_error_object_face_count_mismatch"> + When all faces of an object are copied, the target object must have the same number of faces. + </panel.string> + <panel.string + name="paste_error_inventory_not_found"> + One or more texture not found in inventory. + </panel.string> + <panel.string + name="paste_options"> + Paste options + </panel.string> + + <menu_button + menu_filename="menu_copy_paste_color.xml" + follows="top|left" + height="15" + image_disabled="ClipboardMenu_Disabled" + image_selected="ClipboardMenu_Press" + image_unselected="ClipboardMenu_Off" + layout="topleft" + left="258" + top="8" + name="clipboard_color_params_btn" + tool_tip="Paste options" + width="22"/> <text type="string" length="1" @@ -36,7 +66,7 @@ name="colorswatch" tool_tip="Click to open color picker" top="20" - width="64" /> + width="54" /> <text type="string" length="1" @@ -84,7 +114,7 @@ left_delta="0" name="glow" top_pad="4" - width="80" /> + width="77" /> <check_box height="19" label="Full Bright" @@ -93,13 +123,22 @@ name="checkbox fullbright" top_pad="4" width="81" /> + <view_border + bevel_style="none" + follows="top|left" + height="0" + layout="topleft" + left="8" + name="object_horizontal" + top_pad="4" + width="278" /> <combo_box height="23" layout="topleft" left="10" name="combobox matmedia" - top_pad="5" - width="100"> + top_pad="17" + width="90"> <combo_box.item label="Materials" name="Materials" @@ -113,7 +152,7 @@ control_name="ComboMaterialType" height="50" layout="topleft" - left_pad="20" + left_pad="5" top_delta="-10" width="150" visible = "false" @@ -139,7 +178,20 @@ layout="topleft" top_pad="1" value="2"/> - </radio_group> + </radio_group> + <menu_button + menu_filename="menu_copy_paste_texture.xml" + follows="top|left" + height="15" + image_disabled="ClipboardMenu_Disabled" + image_selected="ClipboardMenu_Press" + image_unselected="ClipboardMenu_Off" + layout="topleft" + left="258" + top_delta="0" + name="clipboard_texture_params_btn" + tool_tip="Paste options" + width="22"/> <check_box control_name="SyncMaterialSettings" follows="top|left" @@ -150,7 +202,7 @@ left="8" name="checkbox_sync_settings" tool_tip="Adjust all maps repeats simultaneously" - top_pad="-16" + top_pad="19" width="160" /> <texture_picker can_apply_immediately="true" @@ -498,10 +550,7 @@ top_pad="4" tool_tip="Add Media" label="Choose..." - width="85"> - <button.commit_callback - function="BuildTool.AddMedia"/> - </button> + width="85"/> <button follows="top|left" height="18" @@ -511,10 +560,7 @@ tool_tip="Delete this media texture" top_delta="0" label="Remove" - width="85"> - <button.commit_callback - function="BuildTool.DeleteMedia"/> - </button> + width="85"/> <button follows="left|top" height="18" @@ -771,14 +817,14 @@ top_delta="16" width="260" /> <button - left="10" - top="222" + follows="left|top" + layout="topleft" + left="9" + top="204" height="20" label="Align" label_selected="Align current texture layers" - layout="topleft" name="button align textures" - top_delta="0" tool_tip="Align current texture layers" width="66" /> <web_browser diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 8a3e18707f..1c9d750aa6 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -459,7 +459,7 @@ label="Price: L$" label_width="73" width="150" - min_val="1" + min_val="0" height="20" max_val="999999999" tool_tip="Object cost." /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 8382e3970c..6f95e282ca 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -348,8 +348,6 @@ can be attached to notecards. <!-- Group name: text shown for LLUUID::null --> <string name="GroupNameNone">(none)</string> - <string name="AvalineCaller">Avaline Caller [ORDER]</string> - <!-- Asset errors. Used in llassetstorage.cpp, translation from error code to error message. --> <string name="AssetErrorNone">No error</string> <string name="AssetErrorRequestFailed">Asset request: failed</string> @@ -2342,6 +2340,14 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. An error occurred while opening Marketplace Listings. If you continue to receive this message, please contact Second Life support for assistance at http://support.secondlife.com </string> + <string name="InventoryMarketplaceConnectionError"> +Marketplace Listings failed to connect. +If you continue to receive this message, please contact Second Life support for assistance at http://support.secondlife.com + </string> + <string name="InventoryMarketplaceConnectionErrorReason"> +Marketplace Listings failed to connect. Reason: [REASON] +If you continue to receive this message, please contact Second Life support for assistance at http://support.secondlife.com + </string> <string name="InventoryMarketplaceListingsNoItemsTitle">Your Marketplace Listings folder is empty.</string> <string name="InventoryMarketplaceListingsNoItemsTooltip"></string> <string name="InventoryMarketplaceListingsNoItems"> @@ -2808,10 +2814,14 @@ If you continue to receive this message, please contact Second Life support for <string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string> <string name="ClassifiedUpdateAfterPublish">(will update after publish)</string> - <!-- panel picks --> - <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> - <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> - <string name="PicksClassifiedsLoadingText">Loading...</string> + <!-- panel picks --> + <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> + <string name="NoPicksText">You haven't created any Picks. Click the New button to create a Pick.</string> + <string name="NoClassifiedsText">You haven't created any Classifieds. Click the New button to create a Classified.</string> + <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> + <string name="NoAvatarPicksText">This person has no picks</string> + <string name="NoAvatarClassifiedsText">This person has no classifieds</string> + <string name="PicksClassifiedsLoadingText">Loading...</string> <!-- Multi Preview Floater --> <string name="MultiPreviewTitle">Preview</string> diff --git a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml index 4f3c177976..87f93e8fcf 100644 --- a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@ <check_box label="Gestos" name="check_gesture"/> <check_box label="Hitos" name="check_landmark"/> <check_box label="Notas" name="check_notecard"/> - <check_box label="Redes" name="check_mesh"/> + <check_box label="Meshs" name="check_mesh"/> <check_box label="Objetos" name="check_object"/> <check_box label="Scripts" name="check_script"/> <check_box label="Sonidos" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/es/floater_preview_texture.xml b/indra/newview/skins/default/xui/es/floater_preview_texture.xml index b0afd44750..2543508c40 100644 --- a/indra/newview/skins/default/xui/es/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/es/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Copiar al inventario </floater.string> - <text name="desc txt"> - Descripción: - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - Previsualizar la ratio de las proporciones - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Vista previa en una proporción concreta"> - <combo_item name="Unconstrained"> - Sin restricciones - </combo_item> - <combo_item name="1:1" tool_tip="Emblema del grupo o perfil del Mundo real"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="Perfil de [SECOND_LIFE]"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Clasificados (también en las listas de búsqueda), hitos"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="Acerca del terreno"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Destacados del perfil"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Descartar" name="Discard"/> - <button label="Guardar como" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Descripción: + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + Previsualizar la ratio de las proporciones + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Vista previa en una proporción concreta"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Descartar" name="Discard"/> + <button label="Guardar como" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_profile.xml b/indra/newview/skins/default/xui/es/floater_profile.xml new file mode 100644 index 0000000000..c9448a0d4e --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Perfil"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="Intereses" name="panel_profile_interests"/> + <panel label="Destacados" name="panel_profile_picks"/> + <panel label="Clasificado" name="panel_profile_classifieds"/> + <panel label="Vida real" name="panel_profile_firstlife"/> + <panel label="Notas" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Salvar cambios en el perfil y cerrar"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml index c2c996aa8a..2dfaecf3e3 100644 --- a/indra/newview/skins/default/xui/es/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> Enviando el correo electrónico </string> + <string name="facebook_progress_str"> + Publicando en Facebook + </string> <string name="profile_progress_str"> Publicando </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Guardando en el equipo </string> + <string name="facebook_succeeded_str"> + Imagen subida + </string> <string name="profile_succeeded_str"> Imagen subida </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> ¡Guardado en el equipo! </string> + <string name="facebook_failed_str"> + Error al subir la imagen a tu biografía de Facebook. + </string> <string name="profile_failed_str"> Error al subir la imagen a los comentarios de tu perfil. </string> diff --git a/indra/newview/skins/default/xui/es/menu_name_field.xml b/indra/newview/skins/default/xui/es/menu_name_field.xml new file mode 100644 index 0000000000..0d51fbffeb --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Copiar Nombre mostrado" name="copy_display"/> + <menu_item_call label="Copiar Nombre de agente" name="copy_name"/> + <menu_item_call label="Copiar ID de agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 54707116d4..36f27bc3c6 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2690,6 +2690,9 @@ Inténtalo seleccionando un trozo más pequeño de terreno. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/es/panel_edit_classified.xml b/indra/newview/skins/default/xui/es/panel_edit_classified.xml index ffad843732..09f87015cc 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="Cancelar" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/es/panel_facebook_place.xml b/indra/newview/skins/default/xui/es/panel_facebook_place.xml index 5139bd1d0b..29f6147f23 100644 --- a/indra/newview/skins/default/xui/es/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/es/panel_facebook_place.xml @@ -3,7 +3,7 @@ <text name="place_caption_label"> Cuenta algo del lugar donde te encuentras: </text> - <check_box initial_value="false" label="Incluir una vista general del lugar" name="add_place_view_cb"/> + <check_box initial_value="false" label="Incluye una vista general del lugar" name="add_place_view_cb"/> <button label="Publicar" name="post_place_btn"/> <button label="Cancelar" name="cancel_place_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/es/panel_group_general.xml b/indra/newview/skins/default/xui/es/panel_group_general.xml index a17814d15d..ef919f396e 100644 --- a/indra/newview/skins/default/xui/es/panel_group_general.xml +++ b/indra/newview/skins/default/xui/es/panel_group_general.xml @@ -46,7 +46,7 @@ Deja el cursor sobre las opciones para ver más ayuda. <check_box label="Cualquiera puede entrar" name="open_enrollement" tool_tip="Configura si se permite la entrada de nuevos miembros sin ser invitados."/> <check_box label="Cuota de entrada" name="check_enrollment_fee" tool_tip="Configura si hay que pagar una cuota para entrar al grupo"/> <spinner label="L$" left_delta="130" name="spin_enrollment_fee" tool_tip="Si la opción Cuota de entrada está marcada, los nuevos miembros han de pagar esta cuota para entrar al grupo." width="60"/> - <combo_box bottom_delta="-38" name="group_mature_check" tool_tip="La calificación de contenido designa el tipo de contenido y conducta que se permiten en un grupo" width="150"> + <combo_box bottom_delta="-38" name="group_mature_check" tool_tip="Establece si tu grupo contiene información clasificada como Moderada" width="150"> <combo_item name="select_mature"> - Selecciona el nivel de calificación - </combo_item> diff --git a/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml new file mode 100644 index 0000000000..4d682068d7 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Desconocido"/> + <button name="info_btn" tool_tip="Más información"/> + <button name="profile_btn" tool_tip="Ver el perfil"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_me.xml b/indra/newview/skins/default/xui/es/panel_me.xml deleted file mode 100644 index 850cd6ec71..0000000000 --- a/indra/newview/skins/default/xui/es/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mi perfil" name="panel_me"> - <panel label="MIS DESTACADOS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/es/panel_people.xml b/indra/newview/skins/default/xui/es/panel_people.xml index 73b9af3665..2aaf7e89be 100644 --- a/indra/newview/skins/default/xui/es/panel_people.xml +++ b/indra/newview/skins/default/xui/es/panel_people.xml @@ -40,6 +40,7 @@ <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Conectado"/> <accordion_tab name="tab_all" title="Todos"/> + <accordion_tab name="tab_suggested_friends" title="Personas de las que podrías querer ser amigo"/> </accordion> </panel> <panel label="GRUPOS" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/es/panel_profile_classified.xml b/indra/newview/skins/default/xui/es/panel_profile_classified.xml new file mode 100644 index 0000000000..679026d350 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Moderado + </panel.string> + <panel.string name="type_pg"> + Contenido general + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] teleportes, [MAP] mapa, [PROFILE] perfil + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Activados + </panel.string> + <panel.string name="auto_renew_off"> + Inhabilitado + </panel.string> + <panel.string name="location_notice"> + (se actualizará tras guardarlo) + </panel.string> + <string name="publish_label"> + Publicar + </string> + <string name="save_label"> + Guardar + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Pulsa para elegir una imagen"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Ubicación:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Tipo de contenido:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Categoría:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Fecha de creación:"/> + <text_editor name="creation_date" tool_tip="Fecha de creación" value="[date]"/> + <text name="price_for_listing_label" value="Precio por publicarlo:"/> + <text_editor name="price_for_listing" tool_tip="Precio por publicarlo."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Clics:"/> + <text_editor name="click_through_text" tool_tip="Información sobre Click through" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Renovación:"/> + <text name="auto_renew" value="Activados"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Descripción:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Título: + </text> + <text name="description_label"> + Descripción: + </text> + <text name="location_label"> + Ubicación: + </text> + <text name="classified_location_edit"> + cargando... + </text> + <button label="Configurar en mi posición" name="set_to_curr_location_btn"/> + <text name="category_label" value="Categoría:"/> + <text name="content_type_label" value="Tipo de contenido:"/> + <icons_combo_box label="Contenido general" name="content_type_edit"> + <icons_combo_box.item label="Contenido Moderado" name="mature_ci" value="Contenido para adultos"/> + <icons_combo_box.item label="Contenido general" name="pg_ci" value="General"/> + </icons_combo_box> + <check_box label="Renovar automáticamente cada semana" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Precio por publicarlo:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Precio por publicarlo." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Teleporte" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Mapa" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Editar" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Cancelar" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml new file mode 100644 index 0000000000..2520348094 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Clasificado" name="panel_profile_classifieds"> + <string name="no_classifieds" value="No hay clasificados"/> + <button label="Nuevo..." name="new_btn"/> + <button label="Eliminar..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Cargando... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/fr/floater_picks.xml b/indra/newview/skins/default/xui/es/panel_profile_firstlife.xml index f058ff668b..0fb502e441 100644 --- a/indra/newview/skins/default/xui/fr/floater_picks.xml +++ b/indra/newview/skins/default/xui/es/panel_profile_firstlife.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Favoris"/> +<panel label="Perfil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/es/panel_profile_interests.xml b/indra/newview/skins/default/xui/es/panel_profile_interests.xml new file mode 100644 index 0000000000..86dd63390c --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Intereses" name="panel_profile_interests"> + <text name="I Want To:"> + Quiero: + </text> + <check_box label="Construye" name="chk0"/> + <check_box label="Explora" name="chk1"/> + <check_box label="Conoce" name="chk2"/> + <check_box label="Encuentra empleo" name="chk6"/> + <check_box label="Agrupa" name="chk3"/> + <check_box label="Compra" name="chk4"/> + <check_box label="Vende" name="chk5"/> + <check_box label="Contrata" name="chk7"/> + <line_editor name="want_to_edit"> + (cargando...) + </line_editor> + <text name="Skills:"> + Habilidades: + </text> + <check_box label="Texturas" name="schk0"/> + <check_box label="Arquitectura" name="schk1"/> + <check_box label="Modelo" name="schk3"/> + <check_box label="Planificación de eventos" name="schk2"/> + <check_box label="Preparación de scripts" name="schk4"/> + <check_box label="Personajes personalizados" name="schk5"/> + <line_editor name="skills_edit"> + (cargando...) + </line_editor> + <text name="Languages:"> + Idiomas: + </text> + <line_editor name="languages_edit"> + (cargando...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_notes.xml b/indra/newview/skins/default/xui/es/panel_profile_notes.xml new file mode 100644 index 0000000000..4cc14e1487 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notas y Privacidad" name="panel_notes"> + <text name="status_message" value="Notas privadas en este avatar:"/> + <text name="status_message2" value="Permitir que este avatar:"/> + <check_box label="Ver cuándo estoy conectado" name="status_check"/> + <check_box label="Encontrarme en el mapa del mundo" name="map_check"/> + <check_box label="Edita, borrar o tomar mis objetos" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_pick.xml b/indra/newview/skins/default/xui/es/panel_profile_pick.xml new file mode 100644 index 0000000000..4e9f5bbdd5 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (se actualizará tras guardarlo) + </panel.string> + <line_editor name="pick_location"> + Cargando... + </line_editor> + <button label="Teleporte" name="teleport_btn"/> + <button label="Mostrar en el mapa" name="show_on_map_btn"/> + <button label="Establecer ubicación" name="set_to_curr_location_btn" tool_tip="Configurar en mi posición"/> + <button label="Guardar" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_picks.xml b/indra/newview/skins/default/xui/es/panel_profile_picks.xml new file mode 100644 index 0000000000..0641b72c13 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Destacados" name="panel_picks"> + <string name="no_picks" value="No hay destacados"/> + <text name="Tell everyone about your favorite places in Second Life."> + Cuéntale a todos sobre tus lugares favoritos de Second Life. + </text> + <button label="Nuevo..." name="new_btn"/> + <button label="Eliminar..." name="delete_btn"/> + <text name="picks_panel_text"> + Cargando... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml new file mode 100644 index 0000000000..541593660d --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Perfil" name="panel_profile"> + <string name="status_online"> + Actualmente en línea + </string> + <string name="status_offline"> + Actualmente sin conexión + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Ninguno"/> + <string name="no_group_text" value="Ninguno"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Desarrollador"/> + <string name="FSSupp" value="Soporte"/> + <string name="FSQualityAssurance" value="Buscador de fallos"/> + <string name="FSGW" value="Portal"/> + <text name="name_label" value="Nombre:"/> + <button label="Nombre:" name="set_name" tool_tip="Configurar nombre mostrado"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(cargando...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Status Desconocido"/> + <text name="label" value="Fecha de nacimiento en Second Life:"/> + <text name="label2" value="Cuenta:"/> + <text name="partner_label" value="Compañero/a:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Grupos:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Invitar al grupo"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="Acerca de:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Dar objeto:"/> + <text name="Give inventory" tool_tip="Soltar elementos de inventario aquí para dárselos a esta persona."> + Soltar aquí el nuevo elemento de inventario. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Encontrar en el mapa" label_selected="Encontrar en el mapa" name="show_on_map_btn" tool_tip="Mostrar al Residente en el mapa"/> + <button label="Pagar" label_selected="Pagar" name="pay" tool_tip="Pagar a este Residente"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Ofrecer teleporte" label_selected="Ofrecer teleporte" name="teleport" tool_tip="Ofrecer teleporte al residente"/> + <button label="Mensaje instantáneo" label_selected="Mensaje instantáneo" name="im" tool_tip="Abrir una sesión de mensajes instantáneos"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Añadir como amigo" label_selected="Añadir como amigo" name="add_friend" tool_tip="Ofrecer amistad a este Residente"/> + <button label="Bloquear" name="block" tool_tip="Bloquear al residente"/> + <button label="Desbloquear" name="unblock" tool_tip="Desbloquear al residente"/> + </layout_panel> + </layout_stack> + <check_box label="Mostrar en la búsqueda" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_web.xml b/indra/newview/skins/default/xui/es/panel_profile_web.xml new file mode 100644 index 0000000000..f9a8f4b113 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Tiempo de carga: [TIME] segundos"/> + <line_editor name="url_edit"> + (cargando..) + </line_editor> + <flyout_button label="Cargar" name="load" tool_tip="Cargar esta página de perfil con el navegador incorporado."> + <flyout_button.item label="Abrir navegador in-viewer" name="open_item"/> + <flyout_button.item label="Abrir navegador externo" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Perfil web emergente"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_region_terrain.xml b/indra/newview/skins/default/xui/es/panel_region_terrain.xml index cb6c03dbb5..9aba5299cb 100644 --- a/indra/newview/skins/default/xui/es/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/es/panel_region_terrain.xml @@ -12,8 +12,8 @@ del terreno" name="terrain_raise_spin"/> <spinner bottom_delta="-34" label="Límite de bajada del terreno" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Texturas del terreno (requiere archivos .tga de 512x512, 24 bits) - </text> + Texturas del terreno (requiere archivos .tga de 1024x1024, 24 bits) + </text> <text name="height_text_lbl"> 1 (bajo) </text> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 4b7f6a0081..5a03e65b49 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -348,6 +348,24 @@ Intenta iniciar sesión de nuevo en unos instantes. <string name="TestingDisconnect"> Probando la desconexión del visor </string> + <string name="SocialFacebookConnecting"> + Conectando con Facebook... + </string> + <string name="SocialFacebookPosting"> + Publicando... + </string> + <string name="SocialFacebookDisconnecting"> + Desconectando de Facebook... + </string> + <string name="SocialFacebookErrorConnecting"> + Problema al conectar con Facebook + </string> + <string name="SocialFacebookErrorPosting"> + Problema al publicar en Facebook + </string> + <string name="SocialFacebookErrorDisconnecting"> + Problema al desconectar de Facebook + </string> <string name="SocialFlickrConnecting"> Conectándose a Flickr... </string> @@ -662,9 +680,6 @@ pueden adjuntarse a las notas. <string name="GroupNameNone"> (ninguno) </string> - <string name="AvalineCaller"> - Avaline: [ORDER] - </string> <string name="AssetErrorNone"> No hay ningún error </string> @@ -2549,9 +2564,21 @@ Si sigues recibiendo el mismo mensaje, solicita ayuda al personal de asistencia <string name="NoPicksClassifiedsText"> No has creado destacados ni clasificados. Pulsa el botón Más para crear uno. </string> + <string name="NoPicksText"> + No has creado destacados. Haz clic en el botón Más para crear uno. + </string> + <string name="NoClassifiedsText"> + No has creado clasificados. Haz clic en el botón Nuevo para crear un anuncio clasificado. + </string> <string name="NoAvatarPicksClassifiedsText"> El usuario no tiene clasificados ni destacados </string> + <string name="NoAvatarPicksText"> + El usuario no tiene destacados + </string> + <string name="NoAvatarClassifiedsText"> + El usuario no tiene clasificados + </string> <string name="PicksClassifiedsLoadingText"> Cargando... </string> @@ -4469,6 +4496,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. <string name="share_alert"> Arrastra los ítems desde el invenbtario hasta aquí </string> + <string name="facebook_post_success"> + Has publicado en Facebook. + </string> <string name="flickr_post_success"> Has publicado en Flickr. </string> diff --git a/indra/newview/skins/default/xui/fr/floater_facebook.xml b/indra/newview/skins/default/xui/fr/floater_facebook.xml index f5097e7a88..f6e8696e53 100644 --- a/indra/newview/skins/default/xui/fr/floater_facebook.xml +++ b/indra/newview/skins/default/xui/fr/floater_facebook.xml @@ -10,6 +10,6 @@ Erreur </text> <text name="connection_loading_text"> - Chargement... + En cours de chargement... </text> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml index d63d9903ec..46703fe612 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Copier dans l'inventaire </floater.string> - <text name="desc txt"> - Description : - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - Rapport d'aspect fixe - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Prévisualiser avec un rapport d'aspect fixe"> - <combo_item name="Unconstrained"> - Sans contraintes - </combo_item> - <combo_item name="1:1" tool_tip="Logo du groupe ou profil dans la vie réelle"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="Profil [SECOND_LIFE]"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Petites annonces, repères"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="À propos du terrain"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Favoris du profil"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Jeter" name="Discard"/> - <button label="Enregistrer sous" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Description : + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + Rapport d'aspect fixe + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Prévisualiser avec un rapport d'aspect fixe"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Jeter" name="Discard"/> + <button label="Enregistrer sous" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_profile.xml b/indra/newview/skins/default/xui/fr/floater_profile.xml new file mode 100644 index 0000000000..c4af79e946 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="Centres d'intérêt" name="panel_profile_interests"/> + <panel label="Favoris" name="panel_profile_picks"/> + <panel label="Petite annonce" name="panel_profile_classifieds"/> + <panel label="Vie réelle" name="panel_profile_firstlife"/> + <panel label="Remarques" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Enregistrer les changements apportés au profil et fermer"/> + <button label="Annuler" label_selected="Annuler" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml index 8eb05dd945..adb98a68d2 100644 --- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> Envoi par e-mail </string> + <string name="facebook_progress_str"> + Publication sur Facebook + </string> <string name="profile_progress_str"> Publication </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Enregistrement sur l'ordinateur </string> + <string name="facebook_succeeded_str"> + Image chargée + </string> <string name="profile_succeeded_str"> Image chargée </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Enregistrement sur l'ordinateur effectué ! </string> + <string name="facebook_failed_str"> + Échec de chargement de l'image dans votre journal Facebook. + </string> <string name="profile_failed_str"> Échec de chargement de l'image sur le flux de votre profil. </string> diff --git a/indra/newview/skins/default/xui/fr/menu_name_field.xml b/indra/newview/skins/default/xui/fr/menu_name_field.xml new file mode 100644 index 0000000000..6c3fba4110 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Copier le Nom d'affichage" name="copy_display"/> + <menu_item_call label="Copier le Nom de l'agent" name="copy_name"/> + <menu_item_call label="Copier l'ID de l'agent" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index e84de375d8..09905f4e5d 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2683,6 +2683,9 @@ Veuillez sélectionner un terrain plus petit. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_classified.xml b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml index 7b58f2e825..b892d25f26 100644 --- a/indra/newview/skins/default/xui/fr/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="Annuler" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml b/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml index 319737a2af..0e36c2092c 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_friends"> - <string name="facebook_friends_empty" value="Vous n'avez actuellement aucun ami Facebook qui est également résident de Second Life. Invitez vos amis Facebook à rejoindre Second Life !"/> + <string name="facebook_friends_empty" value="Vous n'avez actuellement aucun ami Facebook qui est également résident de Second Life. Invitez vos amis Facebook à rejoindre Second Life aujourd'hui !"/> <string name="facebook_friends_no_connected" value="Vous n'êtes pas connecté(e) à Facebook. Allez à l'onglet Statut pour vous connecter et activer cette fonctionnalité."/> <accordion name="friends_accordion"> <accordion_tab name="tab_second_life_friends" title="Amis SL"/> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml b/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml index 3236f35b55..cc4045bc74 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml @@ -4,14 +4,14 @@ <combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/> <combo_box.item label="640 x 480" name="640x480"/> <combo_box.item label="800 x 600" name="800x600"/> - <combo_box.item label="1 024 x 768" name="1024x768"/> - <combo_box.item label="1 200 x 630" name="1200x630"/> + <combo_box.item label="1024 x 768" name="1024x768"/> + <combo_box.item label="1200 x 630" name="1200x630"/> </combo_box> - <combo_box name="filters_combobox" tool_tip="Filtres d'image"> + <combo_box name="filters_combobox" tool_tip="Filtres d’image"> <combo_box.item label="Aucun filtre" name="NoFilter"/> </combo_box> <button label="Actualiser" name="new_snapshot_btn" tool_tip="Cliquer pour actualiser"/> - <button label="Aperçu" name="big_preview_btn" tool_tip="Cliquer pour activer/désactiver l'aperçu"/> + <button label="Aperçu" name="big_preview_btn" tool_tip="Cliquer pour basculer l'aperçu"/> <text name="caption_label"> Commentaire (facultatif) : </text> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_status.xml b/indra/newview/skins/default/xui/fr/panel_facebook_status.xml index 9afa42d2aa..dc8e4b9ecc 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_status.xml @@ -6,7 +6,7 @@ Pas connecté(e) à Facebook. </text> <panel name="panel_buttons"> - <button label="Connexion..." name="connect_btn"/> + <button label="Connexion en cours..." name="connect_btn"/> <button label="Déconnexion" name="disconnect_btn"/> <text name="account_learn_more_label"> [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Apprenez comment publier sur Facebook] diff --git a/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml new file mode 100644 index 0000000000..b1b32af7c6 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Inconnu"/> + <button name="info_btn" tool_tip="En savoir plus"/> + <button name="profile_btn" tool_tip="Voir le profil"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_me.xml b/indra/newview/skins/default/xui/fr/panel_me.xml deleted file mode 100644 index 5676986228..0000000000 --- a/indra/newview/skins/default/xui/fr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mon profil" name="panel_me"> - <panel label="MES FAVORIS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_people.xml b/indra/newview/skins/default/xui/fr/panel_people.xml index 3be6bae52a..e096b5cfe0 100644 --- a/indra/newview/skins/default/xui/fr/panel_people.xml +++ b/indra/newview/skins/default/xui/fr/panel_people.xml @@ -40,6 +40,7 @@ Pour rechercher des résidents avec qui passer du temps, utilisez [secondlife:// <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="En ligne"/> <accordion_tab name="tab_all" title="Tout"/> + <accordion_tab name="tab_suggested_friends" title="Personnes avec lesquelles vous aimeriez peut-être devenir ami(e)"/> </accordion> </panel> <panel label="GROUPES" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_classified.xml b/indra/newview/skins/default/xui/fr/panel_profile_classified.xml new file mode 100644 index 0000000000..b223684c60 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Modéré + </panel.string> + <panel.string name="type_pg"> + Contenu Général + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] téléporter, [MAP] carte, [PROFILE] profile + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Activé + </panel.string> + <panel.string name="auto_renew_off"> + Désactivé + </panel.string> + <panel.string name="location_notice"> + (mise à jour après enregistrement) + </panel.string> + <string name="publish_label"> + Publier + </string> + <string name="save_label"> + Enregistrer + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Cliquer pour sélectionner une image"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Endroit :"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Type de contenu :"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Catégorie :"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Date de création :"/> + <text_editor name="creation_date" tool_tip="Date de création" value="[date]"/> + <text name="price_for_listing_label" value="Coût de l'annonce :"/> + <text_editor name="price_for_listing" tool_tip="Coût de l’annonce."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Clics :"/> + <text_editor name="click_through_text" tool_tip="Parcourir les données en cliquant" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Renouv. auto :"/> + <text name="auto_renew" value="Activé"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Description :"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Titre : + </text> + <text name="description_label"> + Description : + </text> + <text name="location_label"> + Endroit : + </text> + <text name="classified_location_edit"> + en cours de chargement... + </text> + <button label="Définir sur l’emplacement actuel" name="set_to_curr_location_btn"/> + <text name="category_label" value="Catégorie :"/> + <text name="content_type_label" value="Type de contenu :"/> + <icons_combo_box label="Contenu Général" name="content_type_edit"> + <icons_combo_box.item label="Contenu Modéré" name="mature_ci" value="Adulte"/> + <icons_combo_box.item label="Contenu Général" name="pg_ci" value="PG"/> + </icons_combo_box> + <check_box label="Renouvellement auto toutes les semaines" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Coût de l'annonce :"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Coût de l’annonce." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Téléportation" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Carte" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Modifier" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Annuler" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml new file mode 100644 index 0000000000..adb3501422 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Petite annonce" name="panel_profile_classifieds"> + <string name="no_classifieds" value="Pas de petites annonces"/> + <button label="Nouveau..." name="new_btn"/> + <button label="Supprimer..." name="delete_btn"/> + <text name="classifieds_panel_text"> + En cours de chargement... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/es/floater_picks.xml b/indra/newview/skins/default/xui/fr/panel_profile_firstlife.xml index 255aa5dcdc..0f65090209 100644 --- a/indra/newview/skins/default/xui/es/floater_picks.xml +++ b/indra/newview/skins/default/xui/fr/panel_profile_firstlife.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destacados"/> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_interests.xml b/indra/newview/skins/default/xui/fr/panel_profile_interests.xml new file mode 100644 index 0000000000..e8212817d2 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Centres d'intérêt" name="panel_profile_interests"> + <text name="I Want To:"> + Je veux : + </text> + <check_box label="Construire" name="chk0"/> + <check_box label="Explorer" name="chk1"/> + <check_box label="Rencontrer" name="chk2"/> + <check_box label="Être recruté" name="chk6"/> + <check_box label="Grouper" name="chk3"/> + <check_box label="Acheter" name="chk4"/> + <check_box label="Vendre" name="chk5"/> + <check_box label="Louer" name="chk7"/> + <line_editor name="want_to_edit"> + (en cours de chargement...) + </line_editor> + <text name="Skills:"> + Compétences : + </text> + <check_box label="Textures" name="schk0"/> + <check_box label="Architecture" name="schk1"/> + <check_box label="Modèle" name="schk3"/> + <check_box label="Planification des événements" name="schk2"/> + <check_box label="Langage de scripts" name="schk4"/> + <check_box label="Personnages personnalisés" name="schk5"/> + <line_editor name="skills_edit"> + (en cours de chargement...) + </line_editor> + <text name="Languages:"> + Langues : + </text> + <line_editor name="languages_edit"> + (en cours de chargement...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_notes.xml b/indra/newview/skins/default/xui/fr/panel_profile_notes.xml new file mode 100644 index 0000000000..03fb37d72b --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notes & respect de la vie privée" name="panel_notes"> + <text name="status_message" value="Notes personnelles sur cet avatar:"/> + <text name="status_message2" value="Autoriser cet avatar à :"/> + <check_box label="Voir quand je suis en ligne" name="status_check"/> + <check_box label="Me trouver sur la carte du monde" name="map_check"/> + <check_box label="Modifier, supprimer ou prendre mes objets" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_pick.xml b/indra/newview/skins/default/xui/fr/panel_profile_pick.xml new file mode 100644 index 0000000000..017fcff88a --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (mise à jour après enregistrement) + </panel.string> + <line_editor name="pick_location"> + En cours de chargement... + </line_editor> + <button label="Téléportation" name="teleport_btn"/> + <button label="Voir sur la carte" name="show_on_map_btn"/> + <button label="Définir l'emplacement" name="set_to_curr_location_btn" tool_tip="Définir sur l’emplacement actuel"/> + <button label="Enregistrer les favoris" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_picks.xml b/indra/newview/skins/default/xui/fr/panel_profile_picks.xml new file mode 100644 index 0000000000..1644722813 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Favoris" name="panel_picks"> + <string name="no_picks" value="Pas de favoris"/> + <text name="Tell everyone about your favorite places in Second Life."> + Faites connaître aux autres résidents vos endroits favoris dans Second Life. + </text> + <button label="Nouveau..." name="new_btn"/> + <button label="Supprimer..." name="delete_btn"/> + <text name="picks_panel_text"> + En cours de chargement... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml new file mode 100644 index 0000000000..de9cbf6dce --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> + <string name="status_online"> + Actuellement connecté + </string> + <string name="status_offline"> + Actuellement déconnecté + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Aucun"/> + <string name="no_group_text" value="Aucun"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Développeur"/> + <string name="FSSupp" value="Assistance"/> + <string name="FSQualityAssurance" value="Suivi des anomalies"/> + <string name="FSGW" value="Portail"/> + <text name="name_label" value="Nom :"/> + <button label="Nom :" name="set_name" tool_tip="Définir un nom d'affichage"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(en cours de chargement...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Statut inconnu"/> + <text name="label" value="Date de naissance dans Second Life :"/> + <text name="label2" value="Compte :"/> + <text name="partner_label" value="Partenaire :"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Groupes :"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Inviter dans le groupe"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="À propos :"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Donner des objets :"/> + <text name="Give inventory" tool_tip="Placer les objets de l'inventaire ici pour les donner à cette personne"> + Placer les objets de l'inventaire ici. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Situer sur la carte" label_selected="Situer sur la carte" name="show_on_map_btn" tool_tip="Localiser le Résident sur la carte"/> + <button label="Payer" label_selected="Payer" name="pay" tool_tip="Payer le résident"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Proposer de téléporter" label_selected="Proposer de téléporter" name="teleport" tool_tip="Proposer une téléportation au Résident"/> + <button label="Message instantané" label_selected="Message instantané" name="im" tool_tip="Ouvrir une session IM."/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Ajouter un ami" label_selected="Ajouter un ami" name="add_friend" tool_tip="Proposer à ce résident de devenir votre ami"/> + <button label="Bloquer" name="block" tool_tip="Bloquer ce Résident"/> + <button label="Débloquer" name="unblock" tool_tip="Débloquer ce Résident"/> + </layout_panel> + </layout_stack> + <check_box label="Afficher avec la recherche" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_web.xml b/indra/newview/skins/default/xui/fr/panel_profile_web.xml new file mode 100644 index 0000000000..70e145ade9 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Heure de chargement : [TIME] secondes"/> + <line_editor name="url_edit"> + (en cours de chargement..) + </line_editor> + <flyout_button label="Charger" name="load" tool_tip="Charger ce profil avec le navigateur Web incorporé"> + <flyout_button.item label="Ouvrir dans mon navigateur Web" name="open_item"/> + <flyout_button.item label="Ouvrir dans un navigateur externe" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Profil de fenêtres web"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml index 97f486d3a3..bbab00ca24 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml @@ -12,8 +12,8 @@ terrain" name="terrain_raise_spin"/> <spinner bottom_delta="-34" label="Limite d'abaissement du terrain" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Textures du terrain (fichiers .tga 512 x 512, 24 bit requis) - </text> + Textures du terrain (fichiers .tga 1024 x 1024, 24 bit requis) + </text> <text name="height_text_lbl"> 1 (Bas) </text> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 16423503e7..21825c6b2f 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -357,6 +357,24 @@ Veuillez réessayer de vous connecter dans une minute. <string name="TestingDisconnect"> Test de déconnexion du client </string> + <string name="SocialFacebookConnecting"> + Connexion à Facebook… + </string> + <string name="SocialFacebookPosting"> + Publication… + </string> + <string name="SocialFacebookDisconnecting"> + Déconnexion de Facebook… + </string> + <string name="SocialFacebookErrorConnecting"> + Un problème est survenu lors de la connexion à Facebook. + </string> + <string name="SocialFacebookErrorPosting"> + Un problème est survenu lors de la publication sur Facebook. + </string> + <string name="SocialFacebookErrorDisconnecting"> + Un problème est survenu lors de la déconnexion à Facebook. + </string> <string name="SocialFlickrConnecting"> Connexion à Flickr... </string> @@ -674,9 +692,6 @@ peuvent être joints aux notes. <string name="GroupNameNone"> (aucun) </string> - <string name="AvalineCaller"> - Appelant Avaline [ORDER] - </string> <string name="AssetErrorNone"> Aucune erreur </string> @@ -2579,9 +2594,21 @@ Si vous continuez de recevoir ce message, contactez l’assistance Second Life <string name="NoPicksClassifiedsText"> Vous n'avez pas créé de favoris ni de petites annonces Cliquez sur le bouton Plus pour créer un favori ou une petite annonce. </string> + <string name="NoPicksText"> + Vous n'avez pas créé de favoris Cliquer sur le bouton Nouveau pour créer un favori + </string> + <string name="NoClassifiedsText"> + Vous n'avez pas créé de petites annonces Cliquer sur le bouton Nouveau pour créer une petite annonce. + </string> <string name="NoAvatarPicksClassifiedsText"> L'utilisateur n'a ni favoris ni petites annonces. </string> + <string name="NoAvatarPicksText"> + L'utilisateur n'a pas de favoris + </string> + <string name="NoAvatarClassifiedsText"> + L'utilisateur n'a pas de petites annonces + </string> <string name="PicksClassifiedsLoadingText"> Chargement... </string> @@ -4559,6 +4586,9 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. <string name="share_alert"> Faire glisser les objets de l'inventaire ici </string> + <string name="facebook_post_success"> + Vous avez publié sur Facebook. + </string> <string name="flickr_post_success"> Vous avez publié sur Flickr. </string> diff --git a/indra/newview/skins/default/xui/it/floater_preview_texture.xml b/indra/newview/skins/default/xui/it/floater_preview_texture.xml index 8e8d020067..02f15b6b7b 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Copia nell'Inventario </floater.string> - <text name="desc txt"> - Descrizione: - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - Antreprima rapporto di visualizzazione - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Anteprima con rapporto di visualizzazione fisso"> - <combo_item name="Unconstrained"> - Libero - </combo_item> - <combo_item name="1:1" tool_tip="Logo del gruppo o profilo nel mondo reale"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="Profilo [SECOND_LIFE]"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Annunci e inserzioni, punti di riferimento"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="Informazioni sul terreno"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Preferiti del Profilo"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Elimina" name="Discard"/> - <button label="Salva con nome" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Descrizione: + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + Antreprima rapporto di visualizzazione + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Anteprima con rapporto di visualizzazione fisso"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Elimina" name="Discard"/> + <button label="Salva con nome" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_profile.xml b/indra/newview/skins/default/xui/it/floater_profile.xml new file mode 100644 index 0000000000..7e23f9bbbb --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profilo"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="Interessi" name="panel_profile_interests"/> + <panel label="Preferiti" name="panel_profile_picks"/> + <panel label="Annuncio" name="panel_profile_classifieds"/> + <panel label="Vita reale" name="panel_profile_firstlife"/> + <panel label="Note" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Salva modifiche al profilo e chiudi"/> + <button label="Annulla" label_selected="Annulla" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml index d21c206f6f..c9f71a167e 100644 --- a/indra/newview/skins/default/xui/it/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> Invio e-mail in corso </string> + <string name="facebook_progress_str"> + Pubblicazione su Facebook in corso + </string> <string name="profile_progress_str"> Caricamento post </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Salvataggio sul computer in corso </string> + <string name="facebook_succeeded_str"> + Immagine caricata + </string> <string name="profile_succeeded_str"> Immagine caricata </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Salvato sul computer. </string> + <string name="facebook_failed_str"> + Caricamento immagine sul diario di Facebook non riuscito. + </string> <string name="profile_failed_str"> Caricamento immagine sul feed del profilo non riuscito. </string> diff --git a/indra/newview/skins/default/xui/it/menu_name_field.xml b/indra/newview/skins/default/xui/it/menu_name_field.xml new file mode 100644 index 0000000000..9ac863323c --- /dev/null +++ b/indra/newview/skins/default/xui/it/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Copia Nome Visualizzato" name="copy_display"/> + <menu_item_call label="Copia Nome Agente" name="copy_name"/> + <menu_item_call label="Copia ID Agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 1c43013255..a69fa07c50 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2685,6 +2685,9 @@ Prova a selezionare una parte di terreno più piccola. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/it/panel_edit_classified.xml b/indra/newview/skins/default/xui/it/panel_edit_classified.xml index ad827696ff..57e422a25b 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="Annulla" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_friends.xml b/indra/newview/skins/default/xui/it/panel_facebook_friends.xml index c1c0489f88..28769a010f 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_friends.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_friends"> - <string name="facebook_friends_empty" value="Attualmente non hai amici su Facebook che sono anche residenti in Second Life. Invita i tuoi amici di Facebook a partecipare a Second Life!"/> - <string name="facebook_friends_no_connected" value="Attualmente non sei in collegamento con Facebook. Accedi alla scheda Stato per collegarti e attivare questa funzionalità."/> + <string name="facebook_friends_empty" value="Attualmente non hai amici su Facebook che sono anche residenti Second Life. Invita ora i tuoi amici di Facebook a unirsi a Second Life!"/> + <string name="facebook_friends_no_connected" value="Non sei connesso a Facebook. Accedi alla scheda Stato per collegarti e attivare questa funzionalità."/> <accordion name="friends_accordion"> <accordion_tab name="tab_second_life_friends" title="Amici SL"/> <accordion_tab name="tab_suggested_friends" title="Aggiungi queste persone come amici SL"/> </accordion> <text name="facebook_friends_status"> - Non in collegamento con Facebook. + Non connesso a Facebook. </text> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_photo.xml b/indra/newview/skins/default/xui/it/panel_facebook_photo.xml index 044b8b6164..8d66f35c3c 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_photo.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_photo"> - <combo_box name="resolution_combobox" tool_tip="Risoluzione immagini"> + <combo_box name="resolution_combobox" tool_tip="Risoluzione immagine"> <combo_box.item label="Finestra attuale" name="CurrentWindow"/> <combo_box.item label="640x480" name="640x480"/> <combo_box.item label="800x600" name="800x600"/> <combo_box.item label="1024x768" name="1024x768"/> <combo_box.item label="1200x630" name="1200x630"/> </combo_box> - <combo_box name="filters_combobox" tool_tip="Filtri immagini"> + <combo_box name="filters_combobox" tool_tip="Filtri immagine"> <combo_box.item label="Nessun filtro" name="NoFilter"/> </combo_box> <button label="Aggiorna" name="new_snapshot_btn" tool_tip="Fai clic per aggiornare"/> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_status.xml b/indra/newview/skins/default/xui/it/panel_facebook_status.xml index 9b5171043a..7fb1cec78e 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_status.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_status"> - <string name="facebook_connected" value="Sei in collegamento con Facebook come:"/> - <string name="facebook_disconnected" value="Non in collegamento con Facebook"/> + <string name="facebook_connected" value="Sei connesso a Facebook come:"/> + <string name="facebook_disconnected" value="Non connesso a Facebook"/> <text name="account_caption_label"> - Non in collegamento con Facebook. + Non connesso a Facebook. </text> <panel name="panel_buttons"> - <button label="Collegamento..." name="connect_btn"/> - <button label="Interrompi collegamento" name="disconnect_btn"/> + <button label="Connessione in corso..." name="connect_btn"/> + <button label="Disconnetti" name="disconnect_btn"/> <text name="account_learn_more_label"> [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Come pubblicare su Facebook] </text> diff --git a/indra/newview/skins/default/xui/it/panel_group_general.xml b/indra/newview/skins/default/xui/it/panel_group_general.xml index 60028e6098..168524d1ad 100644 --- a/indra/newview/skins/default/xui/it/panel_group_general.xml +++ b/indra/newview/skins/default/xui/it/panel_group_general.xml @@ -46,7 +46,7 @@ Muovi il tuo mouse sopra le opzioni per maggiore aiuto. <check_box label="Chiunque può aderire" name="open_enrollement" tool_tip="Imposta se questo gruppo permette ai nuovi membri di aderire senza essere invitati."/> <check_box label="Quota di adesione" name="check_enrollment_fee" tool_tip="Imposta se richiedere una tassa d'iscrizione per aderire al gruppo"/> <spinner label="L$" left_delta="136" name="spin_enrollment_fee" tool_tip="I nuovi soci devono pagare questa tassa d'iscrizione quando è selezionata." width="60"/> - <combo_box name="group_mature_check" tool_tip="Le categorie di accesso definiscono il tipo di contenuti e di comportamenti ammessi in un gruppo"> + <combo_box name="group_mature_check" tool_tip="Determina se il tuo gruppo contiene informazioni contrassegnate come Moderate opppure no"> <combo_item name="select_mature"> - Seleziona categoria di accesso - </combo_item> diff --git a/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml new file mode 100644 index 0000000000..72e644008c --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Sconosciuto"/> + <button name="info_btn" tool_tip="Maggiori informazioni"/> + <button name="profile_btn" tool_tip="Vedi profilo"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_me.xml b/indra/newview/skins/default/xui/it/panel_me.xml deleted file mode 100644 index a134f6f1de..0000000000 --- a/indra/newview/skins/default/xui/it/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Il mio profilo" name="panel_me"> - <panel label="I MIEI PREFERITI" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml index 3df2368ae0..9eb93a26e5 100644 --- a/indra/newview/skins/default/xui/it/panel_people.xml +++ b/indra/newview/skins/default/xui/it/panel_people.xml @@ -40,6 +40,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Online"/> <accordion_tab name="tab_all" title="Tutto"/> + <accordion_tab name="tab_suggested_friends" title="Persone che potresti voler aggiungere agli amici"/> </accordion> </panel> <panel label="GRUPPI" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/it/panel_profile_classified.xml b/indra/newview/skins/default/xui/it/panel_profile_classified.xml new file mode 100644 index 0000000000..3c88fbe92f --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Moderato + </panel.string> + <panel.string name="type_pg"> + Contenuto Generale + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] teletrasporto, [MAP] mappa, [PROFILE] profilo + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Abilitato + </panel.string> + <panel.string name="auto_renew_off"> + Disabilitato + </panel.string> + <panel.string name="location_notice"> + (si aggiornerà dopo il salvataggio) + </panel.string> + <string name="publish_label"> + Pubblica + </string> + <string name="save_label"> + Salva + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Fai clic per selezionare un'immagine"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Posizione:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Tipo di contenuto:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Categoria:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Data di creazione:"/> + <text_editor name="creation_date" tool_tip="Data di creazione" value="[date]"/> + <text name="price_for_listing_label" value="Prezzo per inserzione:"/> + <text_editor name="price_for_listing" tool_tip="Prezzo per inserzione."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Clic:"/> + <text_editor name="click_through_text" tool_tip="Numero di clic" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Rinnovo automatico:"/> + <text name="auto_renew" value="Abilitato"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Descrizione:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Titolo: + </text> + <text name="description_label"> + Descrizione: + </text> + <text name="location_label"> + Posizione: + </text> + <text name="classified_location_edit"> + caricamento in corso... + </text> + <button label="Imposta come Luogo Attuale" name="set_to_curr_location_btn"/> + <text name="category_label" value="Categoria:"/> + <text name="content_type_label" value="Tipo di contenuto:"/> + <icons_combo_box label="Contenuto Generale" name="content_type_edit"> + <icons_combo_box.item label="Contenuto Moderato" name="mature_ci" value="Per adulti"/> + <icons_combo_box.item label="Contenuto Generale" name="pg_ci" value="PG"/> + </icons_combo_box> + <check_box label="Rinnovo automatico ogni settimana" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Prezzo per inserzione:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Prezzo per inserzione." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Teletrasporto" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Mappa" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Modifica" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Annulla" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml new file mode 100644 index 0000000000..6fc0fd0729 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Annuncio" name="panel_profile_classifieds"> + <string name="no_classifieds" value="Nessuno annuncio"/> + <button label="Nuovo..." name="new_btn"/> + <button label="Elimina..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Caricamento in corso... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml new file mode 100644 index 0000000000..bf8ccef273 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profilo" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/it/panel_profile_interests.xml b/indra/newview/skins/default/xui/it/panel_profile_interests.xml new file mode 100644 index 0000000000..9fe7331e5c --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interessi" name="panel_profile_interests"> + <text name="I Want To:"> + Desidero: + </text> + <check_box label="Costruire" name="chk0"/> + <check_box label="Esplorare" name="chk1"/> + <check_box label="Incontrare" name="chk2"/> + <check_box label="Essere assunto" name="chk6"/> + <check_box label="Gruppo" name="chk3"/> + <check_box label="Acquistare" name="chk4"/> + <check_box label="Vendere" name="chk5"/> + <check_box label="Assumere" name="chk7"/> + <line_editor name="want_to_edit"> + (caricamento in corso...) + </line_editor> + <text name="Skills:"> + Abilità: + </text> + <check_box label="Texture" name="schk0"/> + <check_box label="Architettura" name="schk1"/> + <check_box label="Realizzazione modelli 3D" name="schk3"/> + <check_box label="Organizzazione eventi" name="schk2"/> + <check_box label="Scripting" name="schk4"/> + <check_box label="Personaggi personalizzati" name="schk5"/> + <line_editor name="skills_edit"> + (caricamento in corso...) + </line_editor> + <text name="Languages:"> + Lingue: + </text> + <line_editor name="languages_edit"> + (caricamento in corso...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_notes.xml b/indra/newview/skins/default/xui/it/panel_profile_notes.xml new file mode 100644 index 0000000000..abd5a347c3 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Note e Privacy" name="panel_notes"> + <text name="status_message" value="Annotazioni private su questo avatar:"/> + <text name="status_message2" value="Consenti a questo avatar di:"/> + <check_box label="Vedere quando sono in linea" name="status_check"/> + <check_box label="Trovarmi sulla mappa del mondo" name="map_check"/> + <check_box label="Modificare, eliminare o prendere i miei oggetti" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_pick.xml b/indra/newview/skins/default/xui/it/panel_profile_pick.xml new file mode 100644 index 0000000000..5d2b145565 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (si aggiornerà dopo il salvataggio) + </panel.string> + <line_editor name="pick_location"> + Caricamento in corso... + </line_editor> + <button label="Teletrasporto" name="teleport_btn"/> + <button label="Mostra sulla mappa" name="show_on_map_btn"/> + <button label="Imposta Luogo" name="set_to_curr_location_btn" tool_tip="Imposta come Luogo Attuale"/> + <button label="Salva Luogo preferito" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_picks.xml b/indra/newview/skins/default/xui/it/panel_profile_picks.xml new file mode 100644 index 0000000000..37cffcf622 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Preferiti" name="panel_picks"> + <string name="no_picks" value="Nessun preferito"/> + <text name="Tell everyone about your favorite places in Second Life."> + Comunica a tutti quali sono i tuoi posti preferiti in Second Life. + </text> + <button label="Nuovo..." name="new_btn"/> + <button label="Elimina..." name="delete_btn"/> + <text name="picks_panel_text"> + Caricamento in corso... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml new file mode 100644 index 0000000000..47af1960a5 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profilo" name="panel_profile"> + <string name="status_online"> + Ora in linea + </string> + <string name="status_offline"> + Ora non in linea + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Nessuno"/> + <string name="no_group_text" value="Nessuno"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Sviluppatore"/> + <string name="FSSupp" value="Assistenza"/> + <string name="FSQualityAssurance" value="Bug Hunter"/> + <string name="FSGW" value="Gateway"/> + <text name="name_label" value="Nome:"/> + <button label="Nome:" name="set_name" tool_tip="Imposta nome visualizzato"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(caricamento in corso...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Stato Sconosciuto"/> + <text name="label" value="Compleanno Second Life:"/> + <text name="label2" value="Account:"/> + <text name="partner_label" value="Partner:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Gruppi:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Invita al gruppo:"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="Informazioni generali:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Consegna oggetto:"/> + <text name="Give inventory" tool_tip="Rilascia gli oggetti dell’inventario per consegnarli a questa persona."> + Rilascia l’oggetto dell’inventario qui. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Trova sulla mappa" label_selected="Trova sulla mappa" name="show_on_map_btn" tool_tip="Localizza il Residente sulla mappa"/> + <button label="Paga" label_selected="Paga" name="pay" tool_tip="Paga del denaro al Residente"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Offri Teletrasporto" label_selected="Offri Teletrasporto" name="teleport" tool_tip="Offri il teletrasporto al Residente"/> + <button label="Messaggio istantaneo" label_selected="Messaggio istantaneo" name="im" tool_tip="Apri sessione di messaggistica istantanea"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Aggiungi come amico" label_selected="Aggiungi come amico" name="add_friend" tool_tip="Offri amicizia al Residente"/> + <button label="Blocca" name="block" tool_tip="Blocca questo Residente"/> + <button label="Sblocca" name="unblock" tool_tip="Sblocca questo Residente"/> + </layout_panel> + </layout_stack> + <check_box label="Mostra nella ricerca" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_web.xml b/indra/newview/skins/default/xui/it/panel_profile_web.xml new file mode 100644 index 0000000000..0c3a8ddcf5 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Tempo di caricamento: [TIME] secondi"/> + <line_editor name="url_edit"> + (caricamento in corso..) + </line_editor> + <flyout_button label="Carica" name="load" tool_tip="Carica la pagina profilo con il browser Web integrato."> + <flyout_button.item label="Apri browser interno" name="open_item"/> + <flyout_button.item label="Apri browser esterno" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Profilo web a comparsa"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_region_terrain.xml b/indra/newview/skins/default/xui/it/panel_region_terrain.xml index c61ac3ecce..e08c55f63b 100644 --- a/indra/newview/skins/default/xui/it/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/it/panel_region_terrain.xml @@ -12,8 +12,8 @@ terreno" name="terrain_raise_spin"/> <spinner bottom_delta="-34" label="Limite di abbassamento del terreno" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Texture terreno (richiede file 512x512, 24 bit .tga) - </text> + Texture terreno (richiede file 1024x1024, 24 bit .tga) + </text> <text name="height_text_lbl"> 1 (basso) </text> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index ea972e5a13..1ebdadb930 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -353,6 +353,24 @@ Prova ad accedere nuovamente tra un minuto. <string name="TestingDisconnect"> Verifica scollegamento viewer </string> + <string name="SocialFacebookConnecting"> + Connessione a Facebook in corso... + </string> + <string name="SocialFacebookPosting"> + Caricamento post... + </string> + <string name="SocialFacebookDisconnecting"> + Disconnessione da Facebook in corso... + </string> + <string name="SocialFacebookErrorConnecting"> + Problemi con la connessione a Facebook + </string> + <string name="SocialFacebookErrorPosting"> + Problemi con la connessione a Facebook + </string> + <string name="SocialFacebookErrorDisconnecting"> + Problemi con la disconnessione da Facebook + </string> <string name="SocialFlickrConnecting"> Collegamento a Flickr... </string> @@ -667,9 +685,6 @@ possono essere allegati ai biglietti. <string name="GroupNameNone"> (nessuno) </string> - <string name="AvalineCaller"> - Chiamante Avaline [ORDER] - </string> <string name="AssetErrorNone"> Nessun errore </string> @@ -2557,9 +2572,21 @@ Se continui a ricevere questo messaggio, contatta l'assistenza Second Life <string name="NoPicksClassifiedsText"> Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante + qui sotto per creare un luogo preferito o un'inserzione. </string> + <string name="NoPicksText"> + Non hai creato Luoghi preferiti. Fai clic sul pulsante Nuovo per creare un Luogo preferito. + </string> + <string name="NoClassifiedsText"> + Non hai creato Annunci. Fai clic sul pulsante Nuovo per creare un Annuncio. + </string> <string name="NoAvatarPicksClassifiedsText"> L'utente non ha luoghi preferiti né inserzioni </string> + <string name="NoAvatarPicksText"> + L'utente non ha luoghi preferiti + </string> + <string name="NoAvatarClassifiedsText"> + L'utente non ha annunci + </string> <string name="PicksClassifiedsLoadingText"> Caricamento in corso... </string> @@ -4474,6 +4501,9 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. <string name="inventory_folder_offered-im"> Offerta cartella di inventario "[ITEM_NAME]" </string> + <string name="facebook_post_success"> + Hai pubblicato su Facebook. + </string> <string name="flickr_post_success"> Hai pubblicato su Flickr. </string> diff --git a/indra/newview/skins/default/xui/ja/floater_picks.xml b/indra/newview/skins/default/xui/ja/floater_picks.xml deleted file mode 100644 index 359585eb86..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="ピック"/> diff --git a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml index 4617fd1d92..66ef13948a 100644 --- a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> インベントリにコピー </floater.string> - <text name="desc txt"> - 説明: - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - 縦横比のプレビュー - </text> - <combo_box name="combo_aspect_ratio" tool_tip="固定した縦横比のプレビュー"> - <combo_item name="Unconstrained"> - 非拘束 - </combo_item> - <combo_item name="1:1" tool_tip="グループ記章か現実世界のプロフィール"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="[SECOND_LIFE] プロフィール"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="クラシファイド広告、検索一覧、ランドマーク"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="土地情報"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="プロフィールのピック"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="処分する" name="Discard"/> - <button label="別名で保存" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + 説明: + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + 縦横比のプレビュー + </text> + <combo_box name="combo_aspect_ratio" tool_tip="固定した縦横比のプレビュー"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="処分する" name="Discard"/> + <button label="別名で保存" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_profile.xml b/indra/newview/skins/default/xui/ja/floater_profile.xml new file mode 100644 index 0000000000..e06cd6e8f6 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="プロフィール"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="趣味" name="panel_profile_interests"/> + <panel label="ピック" name="panel_profile_picks"/> + <panel label="クラシファイド広告" name="panel_profile_classifieds"/> + <panel label="リアルライフ(現実世界)" name="panel_profile_firstlife"/> + <panel label="メモ" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="プロフィールの変更を保存して閉じる"/> + <button label="キャンセル" label_selected="キャンセル" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_snapshot.xml b/indra/newview/skins/default/xui/ja/floater_snapshot.xml index f04193d034..64f292c75c 100644 --- a/indra/newview/skins/default/xui/ja/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/ja/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> メールの送信 </string> + <string name="facebook_progress_str"> + Facebook へ投稿中 + </string> <string name="profile_progress_str"> 投稿 </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> コンピュータに保存 </string> + <string name="facebook_succeeded_str"> + 画像がアップロードされました + </string> <string name="profile_succeeded_str"> 画像がアップロードされました </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> コンピュータに保存されました </string> + <string name="facebook_failed_str"> + Facebook のタイムラインに画像をアップロードできませんでした。 + </string> <string name="profile_failed_str"> プロフィールフィードに画像をアップロードできませんでした。 </string> diff --git a/indra/newview/skins/default/xui/ja/menu_name_field.xml b/indra/newview/skins/default/xui/ja/menu_name_field.xml new file mode 100644 index 0000000000..8c37d95073 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="表示名をコピー" name="copy_display"/> + <menu_item_call label="エージェント名をコピー" name="copy_name"/> + <menu_item_call label="エージェント ID をコピー" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index a66552d3fe..92952f4c8a 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2727,6 +2727,9 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml index cf5f2489f1..619e9de65a 100644 --- a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="キャンセル" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml b/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml index c48f13456b..ee57d178e8 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml @@ -16,5 +16,5 @@ コメント (オプション): </text> <button label="投稿" name="post_photo_btn"/> - <button label="取り消し" name="cancel_photo_btn"/> + <button label="キャンセル" name="cancel_photo_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_place.xml b/indra/newview/skins/default/xui/ja/panel_facebook_place.xml index 61138f90c1..e97422a9df 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_place.xml @@ -5,5 +5,5 @@ </text> <check_box initial_value="false" label="場所の俯瞰図を含める" name="add_place_view_cb"/> <button label="投稿" name="post_place_btn"/> - <button label="取り消し" name="cancel_place_btn"/> + <button label="キャンセル" name="cancel_place_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_status.xml b/indra/newview/skins/default/xui/ja/panel_facebook_status.xml index 9d962c9d62..1f48c9c8c7 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_status.xml @@ -9,12 +9,12 @@ <button label="接続..." name="connect_btn"/> <button label="切断" name="disconnect_btn"/> <text name="account_learn_more_label"> - [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Facebook への投稿について]] + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Facebook への投稿について] </text> </panel> <text name="status_caption_label"> 今、何を考えている? </text> <button label="投稿" name="post_status_btn"/> - <button label="取り消し" name="cancel_status_btn"/> + <button label="キャンセル" name="cancel_status_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml new file mode 100644 index 0000000000..77d3d8f391 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="不明"/> + <button name="info_btn" tool_tip="詳細"/> + <button name="profile_btn" tool_tip="プロフィールの表示"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml deleted file mode 100644 index 9b1cf1c8a4..0000000000 --- a/indra/newview/skins/default/xui/ja/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="プロフィール" name="panel_me"> - <panel label="マイ ピック" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_people.xml b/indra/newview/skins/default/xui/ja/panel_people.xml index 0a295855d0..be00a3c122 100644 --- a/indra/newview/skins/default/xui/ja/panel_people.xml +++ b/indra/newview/skins/default/xui/ja/panel_people.xml @@ -40,6 +40,7 @@ <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="オンライン"/> <accordion_tab name="tab_all" title="全員"/> + <accordion_tab name="tab_suggested_friends" title="友だちになりたくない人"/> </accordion> </panel> <panel label="グループ" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_classified.xml b/indra/newview/skins/default/xui/ja/panel_profile_classified.xml new file mode 100644 index 0000000000..2d1bc07e2c --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Moderate + </panel.string> + <panel.string name="type_pg"> + General コンテンツ + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] テレポート、 [MAP] 地図、 [PROFILE] プロフィール + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + 有効 + </panel.string> + <panel.string name="auto_renew_off"> + 無効 + </panel.string> + <panel.string name="location_notice"> + (掲載後更新) + </panel.string> + <string name="publish_label"> + 掲載 + </string> + <string name="save_label"> + 保存 + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="クリックして画像を選択"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="場所:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="コンテンツの種類:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="カテゴリ:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="制作日:"/> + <text_editor name="creation_date" tool_tip="制作日" value="[date]"/> + <text name="price_for_listing_label" value="掲載価格:"/> + <text_editor name="price_for_listing" tool_tip="掲載価格。"> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="クリック数:"/> + <text_editor name="click_through_text" tool_tip="クリックスルーデータ" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="自動更新:"/> + <text name="auto_renew" value="有効"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="説明:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + タイトル: + </text> + <text name="description_label"> + 説明: + </text> + <text name="location_label"> + 場所: + </text> + <text name="classified_location_edit"> + ロード中... + </text> + <button label="現在地に設定" name="set_to_curr_location_btn"/> + <text name="category_label" value="カテゴリ:"/> + <text name="content_type_label" value="コンテンツの種類:"/> + <icons_combo_box label="General コンテンツ" name="content_type_edit"> + <icons_combo_box.item label="Moderate コンテンツ" name="mature_ci" value="Mature"/> + <icons_combo_box.item label="General コンテンツ" name="pg_ci" value="PG"/> + </icons_combo_box> + <check_box label="毎週自動更新" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="掲載価格:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="掲載価格。" value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="テレポート" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="地図" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="編集" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="キャンセル" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml new file mode 100644 index 0000000000..1980c0fa62 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="クラシファイド広告" name="panel_profile_classifieds"> + <string name="no_classifieds" value="クラシファイド広告なし"/> + <button label="新規…" name="new_btn"/> + <button label="削除…" name="delete_btn"/> + <text name="classifieds_panel_text"> + ロード中... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml new file mode 100644 index 0000000000..a4ee262cb3 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="プロフィール" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_interests.xml b/indra/newview/skins/default/xui/ja/panel_profile_interests.xml new file mode 100644 index 0000000000..93cde6ffec --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="趣味" name="panel_profile_interests"> + <text name="I Want To:"> + 次の内容を実行: + </text> + <check_box label="作る" name="chk0"/> + <check_box label="探検" name="chk1"/> + <check_box label="出会う" name="chk2"/> + <check_box label="雇ってもらう" name="chk6"/> + <check_box label="グループ" name="chk3"/> + <check_box label="買う" name="chk4"/> + <check_box label="販売する" name="chk5"/> + <check_box label="雇う" name="chk7"/> + <line_editor name="want_to_edit"> + (ロード中...) + </line_editor> + <text name="Skills:"> + スキル: + </text> + <check_box label="テクスチャ" name="schk0"/> + <check_box label="建築" name="schk1"/> + <check_box label="モデリング" name="schk3"/> + <check_box label="イベント計画" name="schk2"/> + <check_box label="スクリプト" name="schk4"/> + <check_box label="キャラクターのカスタマイズ" name="schk5"/> + <line_editor name="skills_edit"> + (ロード中...) + </line_editor> + <text name="Languages:"> + 言語: + </text> + <line_editor name="languages_edit"> + (ロード中...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_notes.xml b/indra/newview/skins/default/xui/ja/panel_profile_notes.xml new file mode 100644 index 0000000000..4b4e0d5e4e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="メモとプライバシー" name="panel_notes"> + <text name="status_message" value="このアバターのプライベートメモ:"/> + <text name="status_message2" value="このアバターに次の許可を与える:"/> + <check_box label="自分のオンラインステータスを表示する" name="status_check"/> + <check_box label="世界地図で自分を探せるようにする" name="map_check"/> + <check_box label="自分のオブジェクトを編集・削除・取得できるようにする" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_pick.xml b/indra/newview/skins/default/xui/ja/panel_profile_pick.xml new file mode 100644 index 0000000000..0a20c04ad6 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (掲載後更新) + </panel.string> + <line_editor name="pick_location"> + ロード中... + </line_editor> + <button label="テレポート" name="teleport_btn"/> + <button label="地図に表示" name="show_on_map_btn"/> + <button label="場所を設定" name="set_to_curr_location_btn" tool_tip="現在地に設定"/> + <button label="ピックを保存" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_picks.xml b/indra/newview/skins/default/xui/ja/panel_profile_picks.xml new file mode 100644 index 0000000000..4cbfadd09d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="ピック" name="panel_picks"> + <string name="no_picks" value="ピックなし"/> + <text name="Tell everyone about your favorite places in Second Life."> + Second Life のお気に入りの場所を紹介しましょう。 + </text> + <button label="新規…" name="new_btn"/> + <button label="削除…" name="delete_btn"/> + <text name="picks_panel_text"> + ロード中... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml new file mode 100644 index 0000000000..5470dc6c82 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="プロフィール" name="panel_profile"> + <string name="status_online"> + オンライン中 + </string> + <string name="status_offline"> + オフライン中 + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="なし"/> + <string name="no_group_text" value="なし"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="開発者"/> + <string name="FSSupp" value="サポート"/> + <string name="FSQualityAssurance" value="バグハンター"/> + <string name="FSGW" value="ゲートウェイ"/> + <text name="name_label" value="名前:"/> + <button label="名前:" name="set_name" tool_tip="表示名を設定"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(ロード中...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="ステータス不明"/> + <text name="label" value="Second Life 生年月日:"/> + <text name="label2" value="アカウント:"/> + <text name="partner_label" value="パートナー:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="グループ:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="グループに招待"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="詳細:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="アイテムを渡す:"/> + <text name="Give inventory" tool_tip="インベントリのアイテムをここにドロップしてこの人に渡します。"> + インベントリのアイテムをここにドロップしてください。 + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="地図上で見つける" label_selected="地図上で見つける" name="show_on_map_btn" tool_tip="住人を地図上で探す"/> + <button label="お金を払う" label_selected="お金を払う" name="pay" tool_tip="住人にお金を支払う"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="テレポートを送る" label_selected="テレポートを送る" name="teleport" tool_tip="住人にテレポートを送る"/> + <button label="インスタントメッセージ" label_selected="インスタントメッセージ" name="im" tool_tip="インスタントメッセージを開きます"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="フレンド登録" label_selected="フレンド登録" name="add_friend" tool_tip="フレンド登録を申し出ます"/> + <button label="ブロック" name="block" tool_tip="この住人をブロックする"/> + <button label="ブロック解除" name="unblock" tool_tip="この住人のブロックを解除する"/> + </layout_panel> + </layout_stack> + <check_box label="検索に表示" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_web.xml b/indra/newview/skins/default/xui/ja/panel_profile_web.xml new file mode 100644 index 0000000000..4f56a7e98d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="ロード時間:[TIME] 秒"/> + <line_editor name="url_edit"> + (ロード中...) + </line_editor> + <flyout_button label="ロード" name="load" tool_tip="このプロフィールページを、組み込み Web ブラウザでロードします。"> + <flyout_button.item label="ビューワ内のブラウザを開く" name="open_item"/> + <flyout_button.item label="外部ブラウザを開く" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Web プロフィールのポップアウト"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_region_terrain.xml b/indra/newview/skins/default/xui/ja/panel_region_terrain.xml index fb853c1925..c1080a7d7b 100644 --- a/indra/newview/skins/default/xui/ja/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/ja/panel_region_terrain.xml @@ -10,8 +10,8 @@ <spinner label="地形の上昇限度" name="terrain_raise_spin"/> <spinner label="地形の下降限度" name="terrain_lower_spin"/> <text name="detail_texture_text"> - 地形テクスチャ(512x512 の 24 bit .tga ファイル) - </text> + 地形テクスチャ(1024x1024 の 24 bit .tga ファイル) + </text> <text name="height_text_lbl"> 1(低) </text> diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml index 04dfc0176d..f222a4d61a 100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml @@ -3,7 +3,7 @@ <button label="ディスクに保存" name="save_to_computer_btn"/> <button label="持ち物に保存(L$[AMOUNT])" name="save_to_inventory_btn"/> <button label="プロフィールフィードで共有する" name="save_to_profile_btn"/> - <button label="Facebook で共有する" name="send_to_facebook_btn"/> + <button label="Facebook でシェア" name="send_to_facebook_btn"/> <button label="Twitter で共有する" name="send_to_twitter_btn"/> <button label="Flickr で共有する" name="send_to_flickr_btn"/> <button label="メールにより送信" name="save_to_email_btn"/> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 344f9fcd94..d90772ab0a 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -356,6 +356,24 @@ support@secondlife.com にお問い合わせください。 <string name="TestingDisconnect"> ビューワの接続を切るテスト中 </string> + <string name="SocialFacebookConnecting"> + Facebook に接続中... + </string> + <string name="SocialFacebookPosting"> + 投稿中... + </string> + <string name="SocialFacebookDisconnecting"> + Facebook から切断中... + </string> + <string name="SocialFacebookErrorConnecting"> + Facebook への接続時のエラー + </string> + <string name="SocialFacebookErrorPosting"> + Facebook への投稿時のエラー + </string> + <string name="SocialFacebookErrorDisconnecting"> + Facebook からの切断時のエラー + </string> <string name="SocialFlickrConnecting"> Flickr に接続中... </string> @@ -673,9 +691,6 @@ support@secondlife.com にお問い合わせください。 <string name="GroupNameNone"> (なし) </string> - <string name="AvalineCaller"> - Avaline コール [ORDER] - </string> <string name="AssetErrorNone"> エラーなし </string> @@ -2577,9 +2592,21 @@ support@secondlife.com にお問い合わせください。 <string name="NoPicksClassifiedsText"> ピックやクラシファイド広告を作成していません。 作成するには、下にある「プラス」ボタンをクリックします。 </string> + <string name="NoPicksText"> + ピックを作成していません。[新規] ボタンをクリックしてピックを作成する。 + </string> + <string name="NoClassifiedsText"> + クラシファイド広告を作成していません。[新規] ボタンをクリックしてクラシファイド広告を作成する。 + </string> <string name="NoAvatarPicksClassifiedsText"> ピック、またはクラシファイド広告がありません </string> + <string name="NoAvatarPicksText"> + ピックがありません + </string> + <string name="NoAvatarClassifiedsText"> + クラシファイド広告がありません + </string> <string name="PicksClassifiedsLoadingText"> ローディング... </string> @@ -4557,6 +4584,9 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ <string name="share_alert"> インベントリからここにアイテムをドラッグします </string> + <string name="facebook_post_success"> + Facebook に投稿しました。 + </string> <string name="flickr_post_success"> Flickr に投稿しました。 </string> diff --git a/indra/newview/skins/default/xui/pl/floater_picks.xml b/indra/newview/skins/default/xui/pl/floater_picks.xml deleted file mode 100644 index a329e834db..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<floater name="floater_picks" title="Miejsca" /> diff --git a/indra/newview/skins/default/xui/pl/panel_me.xml b/indra/newview/skins/default/xui/pl/panel_me.xml deleted file mode 100644 index 431929420a..0000000000 --- a/indra/newview/skins/default/xui/pl/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel label="Mój Profil" name="panel_me"> - <panel label="MIEJSCA" name="panel_picks" /> -</panel> diff --git a/indra/newview/skins/default/xui/pl/panel_region_terrain.xml b/indra/newview/skins/default/xui/pl/panel_region_terrain.xml index f086a52dcd..2d4286334f 100644 --- a/indra/newview/skins/default/xui/pl/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/pl/panel_region_terrain.xml @@ -7,7 +7,7 @@ <spinner label="Górny limit terenu" name="terrain_raise_spin" /> <spinner label="Dolny limit terenu" name="terrain_lower_spin" /> <text name="detail_texture_text"> - Tekstury terenu (512x512 / 1024x1024, 24 bitowy plik .tga) + Tekstury terenu (1024x1024, 24 bitowy plik .tga) </text> <text name="height_text_lbl"> 1 (Nisko) diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index 2b182dc3cc..90d2d86c02 100644 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -596,9 +596,6 @@ Spróbuj zalogować się ponownie za minutę. <string name="GroupNameNone"> (brak danych) </string> - <string name="AvalineCaller"> - Avaline [ORDER] - </string> <string name="AssetErrorNone"> Brak błędu </string> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml index c50d7dcda0..a43dec4e7b 100644 --- a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@ <check_box label="Gestos" name="check_gesture"/> <check_box label="Landmarks" name="check_landmark"/> <check_box label="Anotações" name="check_notecard"/> - <check_box label="Meshes:" name="check_mesh"/> + <check_box label="Malhas" name="check_mesh"/> <check_box label="Objetos" name="check_object"/> <check_box label="Scripts" name="check_script"/> <check_box label="Sons" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/pt/floater_picks.xml b/indra/newview/skins/default/xui/pt/floater_picks.xml deleted file mode 100644 index 9766196319..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destaques"/> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_texture.xml b/indra/newview/skins/default/xui/pt/floater_preview_texture.xml index 6f39635240..90102023a3 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Copiar para inventário </floater.string> - <text name="desc txt"> - Descrição: - </text> - <text name="dimensions"> - [WIDTH]px x [HEIGHT]px - </text> - <text name="aspect_ratio"> - Visualizar relação de aspecto - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Visualizar com proporção de aspecto fixa"> - <combo_item name="Unconstrained"> - Sem limites - </combo_item> - <combo_item name="1:1" tool_tip="Símbolo ou perfil RW do grupo"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="[SECOND_LIFE] perfil"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Procurar anúncios classificados e marcos"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="Sobre terrenos"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Perfis destacados"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Descartar" name="Discard"/> - <button label="Salvar como" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Descrição: + </text> + <text name="dimensions"> + [WIDTH]px x [HEIGHT]px + </text> + <text name="aspect_ratio"> + Visualizar relação de aspecto + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Visualizar com proporção de aspecto fixa"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Descartar" name="Discard"/> + <button label="Salvar como" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_profile.xml b/indra/newview/skins/default/xui/pt/floater_profile.xml new file mode 100644 index 0000000000..0327211d8f --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Perfil"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="Interesses" name="panel_profile_interests"/> + <panel label="Destaques" name="panel_profile_picks"/> + <panel label="Anúncio" name="panel_profile_classifieds"/> + <panel label="Vida real" name="panel_profile_firstlife"/> + <panel label="Observações" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Salvar alterações do perfil e fechar"/> + <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml index e3812ed708..89901b539f 100644 --- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> Enviando e-mail </string> + <string name="facebook_progress_str"> + Como publicar no Facebook + </string> <string name="profile_progress_str"> Postando </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Salvo no computador </string> + <string name="facebook_succeeded_str"> + Imagem carregada + </string> <string name="profile_succeeded_str"> Imagem carregada </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Salvo no computador! </string> + <string name="facebook_failed_str"> + Falha ao carregar a imagem na sua linha do tempo no Facebook. + </string> <string name="profile_failed_str"> Falha ao carregar a imagem no feed do seu perfil. </string> diff --git a/indra/newview/skins/default/xui/pt/menu_name_field.xml b/indra/newview/skins/default/xui/pt/menu_name_field.xml new file mode 100644 index 0000000000..2157de9813 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Exibir Cópia do Nome" name="copy_display"/> + <menu_item_call label="Copiar Nome do Agente" name="copy_name"/> + <menu_item_call label="Copiar Id do Agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index bd1185bdd2..733ec2c709 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2673,6 +2673,9 @@ Selecione só um objeto. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_classified.xml b/indra/newview/skins/default/xui/pt/panel_edit_classified.xml index 23e00bfc3a..7b27c811f5 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="Cancelar" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/pt/panel_group_general.xml b/indra/newview/skins/default/xui/pt/panel_group_general.xml index 64a7d13fdb..f6c6d11b87 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_general.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_general.xml @@ -46,7 +46,7 @@ Para obter mais ajuda, passe o mouse sobre as opções. <check_box label="Qualquer um pode entrar" name="open_enrollement" tool_tip="Controla a entrada de novos membros, com ou sem convite."/> <check_box label="Taxa de inscrição" name="check_enrollment_fee" tool_tip="Controla a cobrança de uma taxa de associação ao grupo."/> <spinner label="L$" left_delta="120" name="spin_enrollment_fee" tool_tip="Se a opção 'Taxa de associação' estiver marcada, novos membros precisam pagar o valor definido para entrar no grupo." width="60"/> - <combo_box name="group_mature_check" tool_tip="Os níveis de maturidade determinam o tipo de conteúdo e comportamento permitidos em um grupo" width="170"> + <combo_box name="group_mature_check" tool_tip="Definir se o seu grupo contém informações classificadas como Moderado" width="170"> <combo_item name="select_mature"> - Selecione o nível de maturidade - </combo_item> diff --git a/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml new file mode 100644 index 0000000000..0490878507 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Desconhecido"/> + <button name="info_btn" tool_tip="Mais informações"/> + <button name="profile_btn" tool_tip="Ver perfil"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_me.xml b/indra/newview/skins/default/xui/pt/panel_me.xml deleted file mode 100644 index 281c886bd4..0000000000 --- a/indra/newview/skins/default/xui/pt/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Meu perfil" name="panel_me"> - <panel label="MEUS DESTAQUES" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_people.xml b/indra/newview/skins/default/xui/pt/panel_people.xml index 2ef01841c5..ce50449b03 100644 --- a/indra/newview/skins/default/xui/pt/panel_people.xml +++ b/indra/newview/skins/default/xui/pt/panel_people.xml @@ -40,6 +40,7 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa- <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Online"/> <accordion_tab name="tab_all" title="Todos"/> + <accordion_tab name="tab_suggested_friends" title="Pessoas que talvez você deseje adicionar"/> </accordion> </panel> <panel label="GRUPOS" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_classified.xml b/indra/newview/skins/default/xui/pt/panel_profile_classified.xml new file mode 100644 index 0000000000..b43a0ad9f2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Moderado + </panel.string> + <panel.string name="type_pg"> + Conteúdo Geral + </panel.string> + <panel.string name="l$_price"> + L$[PRICE]- + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] teletransporte, [MAP] mapa, [PROFILE] perfil + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Ativado + </panel.string> + <panel.string name="auto_renew_off"> + Desativado + </panel.string> + <panel.string name="location_notice"> + (salvar para atualizar) + </panel.string> + <string name="publish_label"> + Publicar + </string> + <string name="save_label"> + Salvar + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Selecione uma imagem"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Localização:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Tipo de conteúdo:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Categoria:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Data de criação:"/> + <text_editor name="creation_date" tool_tip="Data de criação" value="[date]"/> + <text name="price_for_listing_label" value="Preço do anúncio:"/> + <text_editor name="price_for_listing" tool_tip="Preço do anúncio."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Cliques:"/> + <text_editor name="click_through_text" tool_tip="Dados de click-through" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Renovação automática:"/> + <text name="auto_renew" value="Ativado"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Descrição:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Título: + </text> + <text name="description_label"> + Descrição: + </text> + <text name="location_label"> + Localização: + </text> + <text name="classified_location_edit"> + Carregando... + </text> + <button label="Usar configuração local" name="set_to_curr_location_btn"/> + <text name="category_label" value="Categoria:"/> + <text name="content_type_label" value="Tipo de conteúdo:"/> + <icons_combo_box label="Conteúdo Geral" name="content_type_edit"> + <icons_combo_box.item label="Conteúdo Moderado" name="mature_ci" value="Moderado"/> + <icons_combo_box.item label="Conteúdo Geral" name="pg_ci" value="Adequado para menores"/> + </icons_combo_box> + <check_box label="Renovar automaticamente todas as semanas" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Preço do anúncio:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Preço do anúncio." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Teletransportar" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Mapa" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Editar" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Cancelar" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml new file mode 100644 index 0000000000..f8369954fd --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anúncio" name="panel_profile_classifieds"> + <string name="no_classifieds" value="Nenhum classificado"/> + <button label="Novo..." name="new_btn"/> + <button label="Excluir..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Carregando... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/it/floater_picks.xml b/indra/newview/skins/default/xui/pt/panel_profile_firstlife.xml index dfc539da66..0fb502e441 100644 --- a/indra/newview/skins/default/xui/it/floater_picks.xml +++ b/indra/newview/skins/default/xui/pt/panel_profile_firstlife.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Preferiti"/> +<panel label="Perfil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_interests.xml b/indra/newview/skins/default/xui/pt/panel_profile_interests.xml new file mode 100644 index 0000000000..edf74115f2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interesses" name="panel_profile_interests"> + <text name="I Want To:"> + Quero: + </text> + <check_box label="Crie" name="chk0"/> + <check_box label="Explore" name="chk1"/> + <check_box label="Encontrar" name="chk2"/> + <check_box label="Seja contratado" name="chk6"/> + <check_box label="Grupo" name="chk3"/> + <check_box label="Comprar" name="chk4"/> + <check_box label="Venda" name="chk5"/> + <check_box label="Contratar" name="chk7"/> + <line_editor name="want_to_edit"> + (carregando...) + </line_editor> + <text name="Skills:"> + Habilidades: + </text> + <check_box label="Texturas" name="schk0"/> + <check_box label="Arquitetura" name="schk1"/> + <check_box label="Modelo" name="schk3"/> + <check_box label="Planejamento de evento" name="schk2"/> + <check_box label="Scripts" name="schk4"/> + <check_box label="Personagens personalizados" name="schk5"/> + <line_editor name="skills_edit"> + (carregando...) + </line_editor> + <text name="Languages:"> + Idiomas: + </text> + <line_editor name="languages_edit"> + (carregando...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_notes.xml b/indra/newview/skins/default/xui/pt/panel_profile_notes.xml new file mode 100644 index 0000000000..499e371bb7 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anotações e Privacidade" name="panel_notes"> + <text name="status_message" value="Notas particulares neste avatar:"/> + <text name="status_message2" value="Permitir que esse avatar:"/> + <check_box label="Ver quando eu estiver conectado" name="status_check"/> + <check_box label="Encontre-me no mapa-múndi" name="map_check"/> + <check_box label="Pegar, editar ou excluir objetos meus" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_pick.xml b/indra/newview/skins/default/xui/pt/panel_profile_pick.xml new file mode 100644 index 0000000000..2dd37b38f9 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (salvar para atualizar) + </panel.string> + <line_editor name="pick_location"> + Carregando... + </line_editor> + <button label="Teletransportar" name="teleport_btn"/> + <button label="Mostrar no mapa" name="show_on_map_btn"/> + <button label="Definir Localização" name="set_to_curr_location_btn" tool_tip="Usar configuração local"/> + <button label="Salvar destaque" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_picks.xml b/indra/newview/skins/default/xui/pt/panel_profile_picks.xml new file mode 100644 index 0000000000..f9ead974dc --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Destaques" name="panel_picks"> + <string name="no_picks" value="Nenhum"/> + <text name="Tell everyone about your favorite places in Second Life."> + Conte a todos sobre os seu lugares favoritos no Second Life. + </text> + <button label="Novo..." name="new_btn"/> + <button label="Excluir..." name="delete_btn"/> + <text name="picks_panel_text"> + Carregando... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml new file mode 100644 index 0000000000..8723b1bf58 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Perfil" name="panel_profile"> + <string name="status_online"> + Atualmente Online + </string> + <string name="status_offline"> + Atualmente Offline + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Nenhum"/> + <string name="no_group_text" value="Nenhum"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Desenvolvedor"/> + <string name="FSSupp" value="Suporte"/> + <string name="FSQualityAssurance" value="Caçador de Bug"/> + <string name="FSGW" value="Gateway"/> + <text name="name_label" value="Nome:"/> + <button label="Nome:" name="set_name" tool_tip="Definir nome de tela"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(carregando...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Status desconhecido"/> + <text name="label" value="Aniversário Second Life:"/> + <text name="label2" value="Conta:"/> + <text name="partner_label" value="Parceiro(a):"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Grupos:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Convidar para entrar no grupo"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="Sobre:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Dar o item:"/> + <text name="Give inventory" tool_tip="Arraste e solte o item novo do inventário aqui para dá-los a esta pessoa."> + Arraste e solte o item novo do inventário aqui. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Localizar no mapa" label_selected="Localizar no mapa" name="show_on_map_btn" tool_tip="Localizar o Residente no mapa"/> + <button label="Pagar" label_selected="Pagar" name="pay" tool_tip="Pague em dinheiro para o Residente"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Teletransportar?" label_selected="Teletransportar?" name="teleport" tool_tip="Oferecer teletransporte ao Residente"/> + <button label="Mensagem instantânea" label_selected="Mensagem instantânea" name="im" tool_tip="Abrir sessão de mensagem instantânea"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Adicionar amigo" label_selected="Adicionar amigo" name="add_friend" tool_tip="Oferecer amizade ao residente"/> + <button label="Bloquear" name="block" tool_tip="Bloquear este Residente"/> + <button label="Desbloquear" name="unblock" tool_tip="Desbloquear este Residente"/> + </layout_panel> + </layout_stack> + <check_box label="Mostrar nos resultados de busca" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_web.xml b/indra/newview/skins/default/xui/pt/panel_profile_web.xml new file mode 100644 index 0000000000..0f556c7dad --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Carregar tempo: [TIME] segundos"/> + <line_editor name="url_edit"> + (carregando..) + </line_editor> + <flyout_button label="Carregar" name="load" tool_tip="Carregar esta página de perfil com navegador embutido"> + <flyout_button.item label="Abrir no visualizador do navegador" name="open_item"/> + <flyout_button.item label="Abrir no navegador externo" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Abra o perfil da web"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_region_terrain.xml b/indra/newview/skins/default/xui/pt/panel_region_terrain.xml index 74330a8946..1d312aeed9 100644 --- a/indra/newview/skins/default/xui/pt/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/pt/panel_region_terrain.xml @@ -12,8 +12,8 @@ terreno" name="terrain_raise_spin"/> <spinner bottom_delta="-34" label="Limite mais baixo do terreno" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Texturas de terreno (exige arquivos .tga 512x512, 24 bit) - </text> + Texturas de terreno (exige arquivos .tga 1024x1024, 24 bit) + </text> <text name="height_text_lbl"> 1 (Baixo) </text> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 7c593ab3be..ae452d6a4d 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -47,7 +47,7 @@ Placa de vídeo: [GRAPHICS_CARD_VENDOR] Placa gráfica: [GRAPHICS_CARD] </string> <string name="AboutDriver"> - Versão do driver de vídeo Windows: [GRAPHICS_CARD_VENDOR] + Versão do driver de vídeo Windows: [GRAPHICS_DRIVER_VERSION] </string> <string name="AboutOGL"> Versão do OpenGL: [OPENGL_VERSION] @@ -313,6 +313,24 @@ Aguarde um minuto antes que tentar logar-se novamente. <string name="TestingDisconnect"> Teste de desconexão </string> + <string name="SocialFacebookConnecting"> + Conectando ao Facebook... + </string> + <string name="SocialFacebookPosting"> + Publicando... + </string> + <string name="SocialFacebookDisconnecting"> + Desconectando do Facebook... + </string> + <string name="SocialFacebookErrorConnecting"> + Problema ao conectar ao Facebook + </string> + <string name="SocialFacebookErrorPosting"> + Problema ao publicar no Facebook + </string> + <string name="SocialFacebookErrorDisconnecting"> + Problema ao desconectar do Facebook + </string> <string name="SocialFlickrConnecting"> Conectando ao Flickr... </string> @@ -627,9 +645,6 @@ ser anexado às anotações. <string name="GroupNameNone"> (nenhum) </string> - <string name="AvalineCaller"> - Interlocutor Avaline [ORDER] - </string> <string name="AssetErrorNone"> Nenhum erro </string> @@ -2517,9 +2532,21 @@ Se você continuar a receber essa mensagem, entre em contato com o suporte do Se <string name="NoPicksClassifiedsText"> Você não criou nenhum Destaque ou Anúncio. Clique no botão "+" para criar um Destaque ou Anúncio. </string> + <string name="NoPicksText"> + Você não criou nenhuma Escolha. Clique em Novo Botão para criar um Escolher + </string> + <string name="NoClassifiedsText"> + Você criou nenhum Anúncio. Clique em Novo Botão para criar um Classificado + </string> <string name="NoAvatarPicksClassifiedsText"> O usuário não tem nenhum destaque ou anúncio </string> + <string name="NoAvatarPicksText"> + Usuário não tem escolha + </string> + <string name="NoAvatarClassifiedsText"> + Usuário não tem anúncio + </string> <string name="PicksClassifiedsLoadingText"> Carregando... </string> @@ -4433,6 +4460,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="inventory_folder_offered-im"> Pasta do inventário '[ITEM_NAME]' oferecida </string> + <string name="facebook_post_success"> + Você publicou no Facebook. + </string> <string name="flickr_post_success"> Você publicou no Flickr. </string> diff --git a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml index 7c1d3b52c5..bf90d898f9 100644 --- a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@ <check_box label="Жесты" name="check_gesture"/> <check_box label="Закладки" name="check_landmark"/> <check_box label="Заметки" name="check_notecard"/> - <check_box label="Меши" name="check_mesh"/> + <check_box label="Полисетки" name="check_mesh"/> <check_box label="Объекты" name="check_object"/> <check_box label="Скрипты" name="check_script"/> <check_box label="Звуки" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/ru/floater_picks.xml b/indra/newview/skins/default/xui/ru/floater_picks.xml deleted file mode 100644 index e0ae8d6f03..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Подборка"/> diff --git a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml index 46d2a37503..e3921a75ac 100644 --- a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Копировать в инвентарь </floater.string> - <text name="desc txt"> - Описание: - </text> - <text name="dimensions"> - [WIDTH]пикселей x [HEIGHT]пикселей - </text> - <text name="aspect_ratio"> - Просмотр изображения с соотношением сторон - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с фиксированным соотношением сторон"> - <combo_item name="Unconstrained"> - Без ограничения - </combo_item> - <combo_item name="1:1" tool_tip="Символ группы или профиль в реальном мире"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="Профиль для [SECOND_LIFE]"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="Реклама, поиск и закладки"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="О земле"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Профиль подборки"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="OK" name="Keep"/> - <button label="Отменить" name="Discard"/> - <button label="Сохранить как" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Описание: + </text> + <text name="dimensions"> + [WIDTH]пикселей x [HEIGHT]пикселей + </text> + <text name="aspect_ratio"> + Предварительный просмотр соотношения сторон + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с фиксированным соотношением сторон"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="OK" name="Keep"/> + <button label="Сбросить" name="Discard"/> + <button label="Сохранить как" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_profile.xml b/indra/newview/skins/default/xui/ru/floater_profile.xml new file mode 100644 index 0000000000..6f8daf0a62 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Профиль"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Веб" name="panel_profile_web"/> + <panel label="Круг интересов" name="panel_profile_interests"/> + <panel label="Подборка" name="panel_profile_picks"/> + <panel label="Объявление" name="panel_profile_classifieds"/> + <panel label="Реальная жизнь" name="panel_profile_firstlife"/> + <panel label="Примечания" name="panel_profile_notes"/> + </tab_container> + <button label="OK" name="ok_btn" tool_tip="Сохранить изменения в профиле и закрыть"/> + <button label="Отменить" label_selected="Отменить" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_report_abuse.xml b/indra/newview/skins/default/xui/ru/floater_report_abuse.xml index 3ac8cb74b4..89a453d9cd 100644 --- a/indra/newview/skins/default/xui/ru/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/ru/floater_report_abuse.xml @@ -67,7 +67,7 @@ <combo_box.item label="Земля > Посягательство > Объекты или текстуры" name="Land__Encroachment__Objects_textures"/> <combo_box.item label="Земля > Посягательство > Частицы" name="Land__Encroachment__Particles"/> <combo_box.item label="Земля > Посягательство > Деревья/растения" name="Land__Encroachment__Trees_plants"/> - <combo_box.item label="Нарушение правил игр на ловкость" name="Wagering_gambling"/> + <combo_box.item label="Нарушение игровых правил" name="Wagering_gambling"/> <combo_box.item label="Другое" name="Other"/> </combo_box> <text name="abuser_name_title"> diff --git a/indra/newview/skins/default/xui/ru/floater_snapshot.xml b/indra/newview/skins/default/xui/ru/floater_snapshot.xml index 97de279b8f..a796d942f3 100644 --- a/indra/newview/skins/default/xui/ru/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/ru/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> Отправка письма </string> + <string name="facebook_progress_str"> + Публикация в Facebook + </string> <string name="profile_progress_str"> Публикация </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Сохранение на компьютере </string> + <string name="facebook_succeeded_str"> + Изображение загружено + </string> <string name="profile_succeeded_str"> Изображение отправлено </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Сохранено на компьютере! </string> + <string name="facebook_failed_str"> + Не удалось передать изображение на вашу хронику Facebook. + </string> <string name="profile_failed_str"> Не удалось передать изображение в ваш профиль. </string> diff --git a/indra/newview/skins/default/xui/ru/menu_name_field.xml b/indra/newview/skins/default/xui/ru/menu_name_field.xml new file mode 100644 index 0000000000..889f3c37ab --- /dev/null +++ b/indra/newview/skins/default/xui/ru/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Копировать отображаемое имя" name="copy_display"/> + <menu_item_call label="Копировать имя агента" name="copy_name"/> + <menu_item_call label="Копировать Id агента" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index bfcda798be..e75fd1fd82 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -2682,6 +2682,9 @@ <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/ru/panel_edit_classified.xml b/indra/newview/skins/default/xui/ru/panel_edit_classified.xml index a2f06dbadf..ec457c4565 100644 --- a/indra/newview/skins/default/xui/ru/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/ru/panel_edit_classified.xml @@ -46,8 +46,8 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> - <button label="Отмена" name="cancel_btn"/> + <layout_panel name="cancel_btn_lp"> + <button label="Отменить" name="cancel_btn"/> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml b/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml index 746da8d523..1e4d1346f7 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_friends"> - <string name="facebook_friends_empty" value="Сейчас у вас нет друзей по Facebook, которые также были бы жителями Second Life. Предложите своим друзьям по Facebook присоединиться к Second Life!"/> + <string name="facebook_friends_empty" value="Сейчас у вас нет друзей в Facebook, которые являются также жителями Second Life. Предложите своим друзьям в Facebook присоединиться к Second Life!"/> <string name="facebook_friends_no_connected" value="Сейчас вы не подключены к Facebook. Перейдите на вкладку «Статус», чтобы подключиться и включить эту функцию."/> <accordion name="friends_accordion"> <accordion_tab name="tab_second_life_friends" title="Друзья по SL"/> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml b/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml index 143a57fec7..50296778ff 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml @@ -2,19 +2,19 @@ <panel name="panel_facebook_photo"> <combo_box name="resolution_combobox" tool_tip="Разрешение изображения"> <combo_box.item label="Текущее окно" name="CurrentWindow"/> - <combo_box.item label="640x480" name="640x480"/> - <combo_box.item label="800x600" name="800x600"/> - <combo_box.item label="1024x768" name="1024x768"/> - <combo_box.item label="1200x630" name="1200x630"/> + <combo_box.item label="640 x 480" name="640x480"/> + <combo_box.item label="800 x 600" name="800x600"/> + <combo_box.item label="1024 x 768" name="1024x768"/> + <combo_box.item label="1200 x 630" name="1200x630"/> </combo_box> <combo_box name="filters_combobox" tool_tip="Фильтры изображений"> <combo_box.item label="Без фильтра" name="NoFilter"/> </combo_box> - <button label="Обновить" name="new_snapshot_btn" tool_tip="Щелкните для обновления"/> - <button label="Просмотр" name="big_preview_btn" tool_tip="Щелкните для смены вида"/> + <button label="Обновить" name="new_snapshot_btn" tool_tip="Щелкнуть для обновления"/> + <button label="Предпросмотр" name="big_preview_btn" tool_tip="Щелкнуть для смены вида"/> <text name="caption_label"> Комментарий (не обязательно): </text> <button label="Опубликовать" name="post_photo_btn"/> - <button label="Отмена" name="cancel_photo_btn"/> + <button label="Отменить" name="cancel_photo_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_place.xml b/indra/newview/skins/default/xui/ru/panel_facebook_place.xml index 7d0917a43a..a7fadca059 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_place.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_place"> <text name="place_caption_label"> - Напишите о том, где вы: + Сообщите, где вы находитесь: </text> <check_box initial_value="false" label="Включить вид места сверху" name="add_place_view_cb"/> <button label="Опубликовать" name="post_place_btn"/> - <button label="Отмена" name="cancel_place_btn"/> + <button label="Отменить" name="cancel_place_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_status.xml b/indra/newview/skins/default/xui/ru/panel_facebook_status.xml index c651a8087c..826ac6a08c 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_status.xml @@ -1,20 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_status"> <string name="facebook_connected" value="Вы подключились к Facebook как:"/> - <string name="facebook_disconnected" value="Не подключено к Facebook"/> + <string name="facebook_disconnected" value="Нет подключения к Facebook"/> <text name="account_caption_label"> - Не подключено к Facebook. + Нет подключения к Facebook. </text> <panel name="panel_buttons"> - <button label="Подключение..." name="connect_btn"/> - <button label="Отключить" name="disconnect_btn"/> + <button label="Соединение..." name="connect_btn"/> + <button label="Разъединить" name="disconnect_btn"/> <text name="account_learn_more_label"> - [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 О публикации в Facebook] + [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Узнать о публикации в Facebook] </text> </panel> <text name="status_caption_label"> О чем вы думаете? </text> <button label="Опубликовать" name="post_status_btn"/> - <button label="Отмена" name="cancel_status_btn"/> + <button label="Отменить" name="cancel_status_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml new file mode 100644 index 0000000000..3408969d09 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Неизвестно"/> + <button name="info_btn" tool_tip="Больше информации"/> + <button name="profile_btn" tool_tip="Посмотреть профиль"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_me.xml b/indra/newview/skins/default/xui/ru/panel_me.xml deleted file mode 100644 index 21a125af87..0000000000 --- a/indra/newview/skins/default/xui/ru/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Мой профиль" name="panel_me"> - <panel label="МОЯ ПОДБОРКА" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml b/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml index 5e3de180f9..331ba889d8 100644 --- a/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_navigation_bar.xml @@ -14,7 +14,7 @@ <label name="favorites_bar_label" tool_tip="Перетаскивайте сюда закладки, чтобы было удобнее переходить в любимые места в Second Life!"> Избранное </label> - <more_button name=">>" tool_tip="Показать больше избранного"> + <more_button name=">>" tool_tip="Показать больше избранного" width="60"> Больше ▼ </more_button> </favorites_bar> diff --git a/indra/newview/skins/default/xui/ru/panel_people.xml b/indra/newview/skins/default/xui/ru/panel_people.xml index 0812eb7433..8170c8d26f 100644 --- a/indra/newview/skins/default/xui/ru/panel_people.xml +++ b/indra/newview/skins/default/xui/ru/panel_people.xml @@ -40,6 +40,7 @@ <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Онлайн"/> <accordion_tab name="tab_all" title="Все"/> + <accordion_tab name="tab_suggested_friends" title="С кем вы можете подружиться"/> </accordion> </panel> <panel label="ГРУППЫ" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_classified.xml b/indra/newview/skins/default/xui/ru/panel_profile_classified.xml new file mode 100644 index 0000000000..2d3ed685c0 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Умеренная + </panel.string> + <panel.string name="type_pg"> + Общий контент + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + Телепорт [TELEPORT], карта [MAP], профиль [PROFILE] + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Включен + </panel.string> + <panel.string name="auto_renew_off"> + Отключен + </panel.string> + <panel.string name="location_notice"> + (будет обновлено после сохранения) + </panel.string> + <string name="publish_label"> + Опубликовать + </string> + <string name="save_label"> + Сохранить + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Щелкнуть для выбора изображения"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Местоположение:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="Тип контента:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Категория:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Дата создания:"/> + <text_editor name="creation_date" tool_tip="Дата создания" value="[date]"/> + <text name="price_for_listing_label" value="Стоимость размещения:"/> + <text_editor name="price_for_listing" tool_tip="Цена за размещение."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Клики:"/> + <text_editor name="click_through_text" tool_tip="Информация о переходах" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Автоматическое продление:"/> + <text name="auto_renew" value="Включен"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Описание:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Название: + </text> + <text name="description_label"> + Описание: + </text> + <text name="location_label"> + Местоположение: + </text> + <text name="classified_location_edit"> + загрузка... + </text> + <button label="Установить в текущее местоположение" name="set_to_curr_location_btn"/> + <text name="category_label" value="Категория:"/> + <text name="content_type_label" value="Тип контента:"/> + <icons_combo_box label="Общий контент" name="content_type_edit"> + <icons_combo_box.item label="Умеренный контент" name="mature_ci" value="Возрастной"/> + <icons_combo_box.item label="Общий контент" name="pg_ci" value="C разрешения родителей"/> + </icons_combo_box> + <check_box label="Автоматическое обновление каждую неделю" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="Стоимость размещения:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="Цена за размещение." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Телепорт" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Карта" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Редактировать" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="Отменить" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml new file mode 100644 index 0000000000..fac494682a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Объявление" name="panel_profile_classifieds"> + <string name="no_classifieds" value="Нет рекламы"/> + <button label="Новый..." name="new_btn"/> + <button label="Удалить..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Загрузка... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml new file mode 100644 index 0000000000..f5ac5e906a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Профиль" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_interests.xml b/indra/newview/skins/default/xui/ru/panel_profile_interests.xml new file mode 100644 index 0000000000..ba1c3d0357 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Круг интересов" name="panel_profile_interests"> + <text name="I Want To:"> + Я собираюсь: + </text> + <check_box label="Построить" name="chk0"/> + <check_box label="Просмотреть" name="chk1"/> + <check_box label="Встретить" name="chk2"/> + <check_box label="Получить работу" name="chk6"/> + <check_box label="Группа" name="chk3"/> + <check_box label="Купить" name="chk4"/> + <check_box label="Продать" name="chk5"/> + <check_box label="Нанять" name="chk7"/> + <line_editor name="want_to_edit"> + (загрузка…) + </line_editor> + <text name="Skills:"> + Навыки: + </text> + <check_box label="Текстуры" name="schk0"/> + <check_box label="Архитектура" name="schk1"/> + <check_box label="Моделирование" name="schk3"/> + <check_box label="Планирование мероприятия" name="schk2"/> + <check_box label="Создавать сценарии" name="schk4"/> + <check_box label="Пользовательские символы" name="schk5"/> + <line_editor name="skills_edit"> + (загрузка…) + </line_editor> + <text name="Languages:"> + Языки: + </text> + <line_editor name="languages_edit"> + (загрузка…) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_notes.xml b/indra/newview/skins/default/xui/ru/panel_profile_notes.xml new file mode 100644 index 0000000000..41117c743a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Примечания и конфиденциальность" name="panel_notes"> + <text name="status_message" value="Личные заметки об этом аватаре:"/> + <text name="status_message2" value="Разрешить этому аватару:"/> + <check_box label="Смотреть, когда я в сети" name="status_check"/> + <check_box label="Найти меня на карте мира" name="map_check"/> + <check_box label="Редактировать, удалять или брать мои объекты" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_pick.xml b/indra/newview/skins/default/xui/ru/panel_profile_pick.xml new file mode 100644 index 0000000000..a2ff5710ea --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (будет обновлено после сохранения) + </panel.string> + <line_editor name="pick_location"> + Загрузка... + </line_editor> + <button label="Телепорт" name="teleport_btn"/> + <button label="Показать на карте" name="show_on_map_btn"/> + <button label="Указать местоположение" name="set_to_curr_location_btn" tool_tip="Установить в текущее местоположение"/> + <button label="Сохранить подборку" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_picks.xml b/indra/newview/skins/default/xui/ru/panel_profile_picks.xml new file mode 100644 index 0000000000..227b3f82b8 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Подборка" name="panel_picks"> + <string name="no_picks" value="Нет подборки"/> + <text name="Tell everyone about your favorite places in Second Life."> + Сообщить всем о ваших избранных службах в Second Life. + </text> + <button label="Новый..." name="new_btn"/> + <button label="Удалить..." name="delete_btn"/> + <text name="picks_panel_text"> + Загрузка... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml new file mode 100644 index 0000000000..e7a66ba29e --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Профиль" name="panel_profile"> + <string name="status_online"> + В настоящее время в режиме онлайн + </string> + <string name="status_offline"> + В настоящее время в режиме оффлайн + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Никто"/> + <string name="no_group_text" value="Никто"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Разработчик"/> + <string name="FSSupp" value="Поддержка"/> + <string name="FSQualityAssurance" value="Отладчик"/> + <string name="FSGW" value="Межсетевой интерфейс"/> + <text name="name_label" value="Имя:"/> + <button label="Имя:" name="set_name" tool_tip="Задать отображаемое имя"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(загрузка…)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Статус неизвестен"/> + <text name="label" value="Дата рождения в Second Life:"/> + <text name="label2" value="Аккаунт:"/> + <text name="partner_label" value="Партнер:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Группы:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Пригласить в группу"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="О нас:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Передать вещь:"/> + <text name="Give inventory" tool_tip="Сбросить вещи из инвентаря здесь для передачи их этому игроку."> + Сбросить вещь из инвентаря здесь. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Найти на карте" label_selected="Найти на карте" name="show_on_map_btn" tool_tip="Найти жителя на карте"/> + <button label="Оплатить" label_selected="Оплатить" name="pay" tool_tip="Выплатить деньги резиденту"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Предложить телепорт" label_selected="Предложить телепорт" name="teleport" tool_tip="Предложить телепорт этому жителю"/> + <button label="Мгновенное сообщение" label_selected="Мгновенное сообщение" name="im" tool_tip="Начать сеанс IM"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Добавить друга" label_selected="Добавить друга" name="add_friend" tool_tip="Предложить дружбу этому жителю"/> + <button label="Заблокировать" name="block" tool_tip="Заблокировать этого жителя"/> + <button label="Разблокировать" name="unblock" tool_tip="Разблокировать этого жителя"/> + </layout_panel> + </layout_stack> + <check_box label="Показать в поиске" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_web.xml b/indra/newview/skins/default/xui/ru/panel_profile_web.xml new file mode 100644 index 0000000000..18a17e2586 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Веб" name="panel_profile_web"> + <panel.string name="LoadTime" value="Время загрузки: [TIME] секунд"/> + <line_editor name="url_edit"> + (загрузка…) + </line_editor> + <flyout_button label="Загрузить" name="load" tool_tip="Загрузить эту страницу с профилем с помощью встроенного веб-браузера."> + <flyout_button.item label="Открыть в просмотрщике браузера" name="open_item"/> + <flyout_button.item label="Открыть во внешнем браузере" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Всплывающий веб-профиль"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_region_terrain.xml b/indra/newview/skins/default/xui/ru/panel_region_terrain.xml index af25565226..76b4f513a8 100644 --- a/indra/newview/skins/default/xui/ru/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/ru/panel_region_terrain.xml @@ -10,8 +10,8 @@ <spinner label="Верх. точка ландшафта" name="terrain_raise_spin"/> <spinner label="Ниж. точка ландшафта" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Текстуры ландшафта (требования: 512x512, 24-битные, TGA) - </text> + Текстуры ландшафта (требования: 1024x1024, 24-битные, TGA) + </text> <text name="height_text_lbl"> 1 (Низ) </text> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 95b1664279..61d836a2d1 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -357,6 +357,24 @@ support@secondlife.com. <string name="TestingDisconnect"> Тестирование отключения клиента </string> + <string name="SocialFacebookConnecting"> + Подключение к Facebook... + </string> + <string name="SocialFacebookPosting"> + Публикация... + </string> + <string name="SocialFacebookDisconnecting"> + Отключение от Facebook... + </string> + <string name="SocialFacebookErrorConnecting"> + Проблема с подключением к Facebook + </string> + <string name="SocialFacebookErrorPosting"> + Проблемы при публикации в Facebook + </string> + <string name="SocialFacebookErrorDisconnecting"> + Проблема с отключением от Facebook + </string> <string name="SocialFlickrConnecting"> Подключение к Flickr... </string> @@ -671,9 +689,6 @@ support@secondlife.com. <string name="GroupNameNone"> (нет) </string> - <string name="AvalineCaller"> - [ORDER] абонента Avaline - </string> <string name="AssetErrorNone"> Ошибок нет </string> @@ -2576,9 +2591,21 @@ support@secondlife.com. <string name="NoPicksClassifiedsText"> Вы не создали подборки или рекламы. Нажмите кнопку со знаком «плюс» ниже, чтобы создать подборку или рекламу </string> + <string name="NoPicksText"> + Вы не сделали никакой подборки. Нажмите кнопку Создать, чтобы сделать подборку. + </string> + <string name="NoClassifiedsText"> + Вы не сделали никакой рекламы. Нажмите кнопку Создать, чтобы сделать рекламу. + </string> <string name="NoAvatarPicksClassifiedsText"> У жителя нет подборки или рекламы </string> + <string name="NoAvatarPicksText"> + У пользователя нет подборки + </string> + <string name="NoAvatarClassifiedsText"> + У пользователя нет объявлений + </string> <string name="PicksClassifiedsLoadingText"> Загрузка... </string> @@ -4553,6 +4580,9 @@ support@secondlife.com. <string name="share_alert"> Перетаскивайте вещи из инвентаря сюда </string> + <string name="facebook_post_success"> + Вы опубликовали сообщение в Facebook. + </string> <string name="flickr_post_success"> Вы опубликовали сообщение в Flickr. </string> diff --git a/indra/newview/skins/default/xui/tr/floater_facebook.xml b/indra/newview/skins/default/xui/tr/floater_facebook.xml index 656a4a81c9..d8cbd84ed1 100644 --- a/indra/newview/skins/default/xui/tr/floater_facebook.xml +++ b/indra/newview/skins/default/xui/tr/floater_facebook.xml @@ -3,7 +3,7 @@ <tab_container name="tabs"> <panel label="DURUM" name="panel_facebook_status"/> <panel label="FOTOĞRAF" name="panel_facebook_photo"/> - <panel label="KONUMA GİRİŞ YAPIN" name="panel_facebook_place"/> + <panel label="GİRİŞ YAP" name="panel_facebook_place"/> <panel label="ARKADAŞLAR" name="panel_facebook_friends"/> </tab_container> <text name="connection_error_text"> diff --git a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml index accb1ed71c..caa8497d3a 100644 --- a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@ <check_box label="Mimikler" name="check_gesture"/> <check_box label="Yer İmleri" name="check_landmark"/> <check_box label="Not Kartları" name="check_notecard"/> - <check_box label="Örgüler" name="check_mesh"/> + <check_box label="Ağlar" name="check_mesh"/> <check_box label="Nesneler" name="check_object"/> <check_box label="Komut Dosyaları" name="check_script"/> <check_box label="Sesler" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/tr/floater_picks.xml b/indra/newview/skins/default/xui/tr/floater_picks.xml deleted file mode 100644 index 5aee6ae091..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Seçimler"/> diff --git a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml index 8302c62070..8ba9123545 100644 --- a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> Envantere Kopyala </floater.string> - <text name="desc txt"> - Açıklama: - </text> - <text name="dimensions"> - [WIDTH] pks x [HEIGHT] pks - </text> - <text name="aspect_ratio"> - En boy oranını önizle - </text> - <combo_box name="combo_aspect_ratio" tool_tip="Sabit en boy oranında önizle"> - <combo_item name="Unconstrained"> - Kısıtsız - </combo_item> - <combo_item name="1:1" tool_tip="Grup işaretleri veya Real World profili"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="[SECOND_LIFE] profili"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="İlanlar ve arama listeleri, yer imleri"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="Arazi hakkında"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="Profil seçmeleri"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="Tamam" name="Keep"/> - <button label="At" name="Discard"/> - <button label="Farklı Kaydet" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + Açıklama: + </text> + <text name="dimensions"> + [WIDTH]pks x [HEIGHT]pks + </text> + <text name="aspect_ratio"> + En boy oranını önizle + </text> + <combo_box name="combo_aspect_ratio" tool_tip="Sabit en boy oranında önizle"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="Tamam" name="Keep"/> + <button label="At" name="Discard"/> + <button label="Farklı Kaydet" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_profile.xml b/indra/newview/skins/default/xui/tr/floater_profile.xml new file mode 100644 index 0000000000..bb158ddf66 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="Second Life" name="panel_profile_secondlife"/> + <panel label="Web" name="panel_profile_web"/> + <panel label="İlgi alanları" name="panel_profile_interests"/> + <panel label="Favoriler" name="panel_profile_picks"/> + <panel label="İlan" name="panel_profile_classifieds"/> + <panel label="Gerçek Hayat" name="panel_profile_firstlife"/> + <panel label="Notlar" name="panel_profile_notes"/> + </tab_container> + <button label="Tamam" name="ok_btn" tool_tip="Değişiklikleri profile kaydet ve kapat"/> + <button label="İptal Et" label_selected="İptal Et" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_snapshot.xml b/indra/newview/skins/default/xui/tr/floater_snapshot.xml index be6c58e8cf..8496194700 100644 --- a/indra/newview/skins/default/xui/tr/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/tr/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> E-posta Gönderiliyor </string> + <string name="facebook_progress_str"> + Facebook'ta yayınlanıyor + </string> <string name="profile_progress_str"> Yayınlanıyor </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> Bilgisayara Kaydediliyor </string> + <string name="facebook_succeeded_str"> + Görüntü yüklendi + </string> <string name="profile_succeeded_str"> Görüntü yüklendi </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> Bilgisayara Kaydedildi! </string> + <string name="facebook_failed_str"> + Görüntü Facebook zaman tünelinize yüklenemedi. + </string> <string name="profile_failed_str"> Görüntü Profil Akışınıza yüklenemedi. </string> diff --git a/indra/newview/skins/default/xui/tr/menu_name_field.xml b/indra/newview/skins/default/xui/tr/menu_name_field.xml new file mode 100644 index 0000000000..b1afd737c3 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="Görünen Adı Kopyala" name="copy_display"/> + <menu_item_call label="Aracı Adını Kopyala" name="copy_name"/> + <menu_item_call label="Aracı Kimliğini Kopyala" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 5403a78f22..17d2969d19 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -2682,6 +2682,9 @@ Daha küçük bir arazi parçası seçmeyi deneyin. <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml index fc444f21f6..78c34a3ac0 100644 --- a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="İptal Et" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml b/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml index 8184d6d7cf..edbe87d74c 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_friends"> - <string name="facebook_friends_empty" value="Şu an için aynı zamanda bir Second Life sakini olan hiçbir Facebook arkadaşınız yok. Facebook arkadaşlarınızı bugün Second Life'a katılmaya davet edin!"/> + <string name="facebook_friends_empty" value="Şu anda aynı zamanda bir Second Life sakini olan hiçbir Facebook arkadaşınız yok. Facebook arkadaşlarınızdan bugün Second Life'a katılmalarını isteyin!"/> <string name="facebook_friends_no_connected" value="Şu anda Facebook'a bağlı değilsiniz. Bağlanmak ve bu özelliği etkinleştirmek için lütfen Durum sekmesine gidin."/> <accordion name="friends_accordion"> <accordion_tab name="tab_second_life_friends" title="SL arkadaşları"/> <accordion_tab name="tab_suggested_friends" title="Bu kişileri SL arkadaşları olarak ekle"/> </accordion> <text name="facebook_friends_status"> - Facebook'a bağlanılmadı. + Facebook'a bağlanılamadı. </text> </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml b/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml index d772aff937..e3150f258d 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_photo"> <combo_box name="resolution_combobox" tool_tip="Görüntü çözünürlüğü"> - <combo_box.item label="Mevcut Pencere" name="CurrentWindow"/> + <combo_box.item label="Geçerli Pencere" name="CurrentWindow"/> <combo_box.item label="640x480" name="640x480"/> <combo_box.item label="800x600" name="800x600"/> <combo_box.item label="1024x768" name="1024x768"/> @@ -11,10 +11,10 @@ <combo_box.item label="Filtre Yok" name="NoFilter"/> </combo_box> <button label="Yenile" name="new_snapshot_btn" tool_tip="Yenilemek için tıklayın"/> - <button label="Önizleme" name="big_preview_btn" tool_tip="Önizleme ayarları arasında geçiş yapmak için tıklayın"/> + <button label="Önizleme" name="big_preview_btn" tool_tip="Önizlemeye geçmek için tıklayın"/> <text name="caption_label"> Yorum (isteğe bağlı): </text> <button label="Yayınla" name="post_photo_btn"/> - <button label="İptal" name="cancel_photo_btn"/> + <button label="İptal Et" name="cancel_photo_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_place.xml b/indra/newview/skins/default/xui/tr/panel_facebook_place.xml index 85b401a1a0..96c34d03d0 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_place.xml @@ -5,5 +5,5 @@ </text> <check_box initial_value="false" label="Konumun üstten görünümünü ekle" name="add_place_view_cb"/> <button label="Yayınla" name="post_place_btn"/> - <button label="İptal" name="cancel_place_btn"/> + <button label="İptal Et" name="cancel_place_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_status.xml b/indra/newview/skins/default/xui/tr/panel_facebook_status.xml index e6feff5949..f5dba088de 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_status.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <panel name="panel_facebook_status"> <string name="facebook_connected" value="Facebook'a şu kimlikle bağlandınız:"/> - <string name="facebook_disconnected" value="Facebook'a bağlanılmadı"/> + <string name="facebook_disconnected" value="Facebook'a bağlanılamadı"/> <text name="account_caption_label"> - Facebook'a bağlanılmadı. + Facebook'a bağlanılamadı. </text> <panel name="panel_buttons"> <button label="Bağlan..." name="connect_btn"/> @@ -13,8 +13,8 @@ </text> </panel> <text name="status_caption_label"> - Ne düşünüyorsunuz? + Aklınızdan ne geçiyor? </text> <button label="Yayınla" name="post_status_btn"/> - <button label="İptal" name="cancel_status_btn"/> + <button label="İptal Et" name="cancel_status_btn"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_group_general.xml b/indra/newview/skins/default/xui/tr/panel_group_general.xml index c666778c69..5578b36f3f 100644 --- a/indra/newview/skins/default/xui/tr/panel_group_general.xml +++ b/indra/newview/skins/default/xui/tr/panel_group_general.xml @@ -45,7 +45,7 @@ Daha fazla yardım edinmek için farenizi seçeneklerin üzerine getirin. <check_box label="Herkes katılabilir" name="open_enrollement" tool_tip="Bu grubun davet edilmeden yeni üyelerin katılmasına imkan tanıyıp tanımayacağını belirler."/> <check_box label="Katılma ücreti" name="check_enrollment_fee" tool_tip="Bu gruba katılmak için bir kayıt ücretinin gerekip gerekmeyeceğini belirler"/> <spinner label="L$" name="spin_enrollment_fee" tool_tip="Kayıt Ücreti işaretlendiğinde yeni üyeler gruba katılmak için bu ücreti ödemelidir."/> - <combo_box name="group_mature_check" tool_tip="Erişkinlik dereceleri bir grupta izin verilen içerik ve davranış türlerini belirler"> + <combo_box name="group_mature_check" tool_tip="Grubunuzun Orta olarak sınıflandırılmış bilgiler içerip içermeyeceğini belirler"> <combo_item name="select_mature"> - Erişkinlik seviyesini seçin - </combo_item> diff --git a/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml new file mode 100644 index 0000000000..0ed905ed35 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="Bilinmiyor"/> + <button name="info_btn" tool_tip="Ek bilgi"/> + <button name="profile_btn" tool_tip="Profili görüntüle"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_me.xml b/indra/newview/skins/default/xui/tr/panel_me.xml deleted file mode 100644 index d9e79d171c..0000000000 --- a/indra/newview/skins/default/xui/tr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Profilim" name="panel_me"> - <panel label="SEÇTİKLERİM" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml b/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml index 8d43e3fb5a..ae9bc33bfa 100644 --- a/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_navigation_bar.xml @@ -14,7 +14,7 @@ <label name="favorites_bar_label" tool_tip="Second Life içerisinde sık kullandığınız yerlere hızla erişmek için Yer İmlerini buraya sürükleyin!"> Favoriler Çubuğu </label> - <more_button name=">>" tool_tip="Favorilerimden daha çok göster"> + <more_button name=">>" tool_tip="Favorilerimden daha çok göster" width="65"> Daha Fazla ▼ </more_button> </favorites_bar> diff --git a/indra/newview/skins/default/xui/tr/panel_people.xml b/indra/newview/skins/default/xui/tr/panel_people.xml index 25d29fcbb5..acbcd2a544 100644 --- a/indra/newview/skins/default/xui/tr/panel_people.xml +++ b/indra/newview/skins/default/xui/tr/panel_people.xml @@ -40,6 +40,7 @@ Birlikte takılacak kişiler mi arıyorsunuz? [secondlife:///app/worldmap Dünya <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="Çevrimiçi"/> <accordion_tab name="tab_all" title="Tümü"/> + <accordion_tab name="tab_suggested_friends" title="Arkadaş olmak isteyebileceğiniz kişiler"/> </accordion> </panel> <panel label="GRUPLAR" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_classified.xml b/indra/newview/skins/default/xui/tr/panel_profile_classified.xml new file mode 100644 index 0000000000..805de24c11 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + Orta + </panel.string> + <panel.string name="type_pg"> + Genel İçerik + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] ışınlanma, [MAP] harita, [PROFILE] profil + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + Etkin + </panel.string> + <panel.string name="auto_renew_off"> + Devre dışı + </panel.string> + <panel.string name="location_notice"> + (kaydedildikten sonra güncellenir) + </panel.string> + <string name="publish_label"> + Yayınla + </string> + <string name="save_label"> + Kaydet + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="Bir görüntü seçmek için tıklayın"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="Konum:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="İçerik Türü:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="Kategori:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="Oluşturma tarihi:"/> + <text_editor name="creation_date" tool_tip="Oluşturma tarihi" value="[date]"/> + <text name="price_for_listing_label" value="İlan fiyatı:"/> + <text_editor name="price_for_listing" tool_tip="İlan fiyatı."> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="Tıklama sayısı:"/> + <text_editor name="click_through_text" tool_tip="Tıklama verileri" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="Otomatik yenileme:"/> + <text name="auto_renew" value="Etkin"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="Açıklama:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + Başlık: + </text> + <text name="description_label"> + Açıklama: + </text> + <text name="location_label"> + Konum: + </text> + <text name="classified_location_edit"> + yükleniyor... + </text> + <button label="Geçerli Konuma Ayarla" name="set_to_curr_location_btn"/> + <text name="category_label" value="Kategori:"/> + <text name="content_type_label" value="İçerik türü:"/> + <icons_combo_box label="Genel İçerik" name="content_type_edit"> + <icons_combo_box.item label="Orta İçerik" name="mature_ci" value="Yetişkin"/> + <icons_combo_box.item label="Genel İçerik" name="pg_ci" value="PG"/> + </icons_combo_box> + <check_box label="Her hafta otomatik yenile" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="İlan fiyatı:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="İlan fiyatı." value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="Işınlanma" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="Harita" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="Düzenle" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="İptal Et" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml new file mode 100644 index 0000000000..0edae1ab2a --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="İlan" name="panel_profile_classifieds"> + <string name="no_classifieds" value="İlan Yok"/> + <button label="Yeni..." name="new_btn"/> + <button label="Sil..." name="delete_btn"/> + <text name="classifieds_panel_text"> + Yükleniyor... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml new file mode 100644 index 0000000000..0f65090209 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_interests.xml b/indra/newview/skins/default/xui/tr/panel_profile_interests.xml new file mode 100644 index 0000000000..b068aa3dad --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="İlgi alanları" name="panel_profile_interests"> + <text name="I Want To:"> + Şunu Yapmak İstiyorum: + </text> + <check_box label="İnşa Et" name="chk0"/> + <check_box label="Keşfet" name="chk1"/> + <check_box label="Tanış" name="chk2"/> + <check_box label="İşe Gir" name="chk6"/> + <check_box label="Gruplandır" name="chk3"/> + <check_box label="Satın Al" name="chk4"/> + <check_box label="Sat" name="chk5"/> + <check_box label="İşe Al" name="chk7"/> + <line_editor name="want_to_edit"> + (yükleniyor...) + </line_editor> + <text name="Skills:"> + Beceriler: + </text> + <check_box label="Dokular" name="schk0"/> + <check_box label="Mimari" name="schk1"/> + <check_box label="Modelleme" name="schk3"/> + <check_box label="Etkinlik Planlama" name="schk2"/> + <check_box label="Kodlama" name="schk4"/> + <check_box label="Özel Karakterler" name="schk5"/> + <line_editor name="skills_edit"> + (yükleniyor...) + </line_editor> + <text name="Languages:"> + Diller: + </text> + <line_editor name="languages_edit"> + (yükleniyor...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_notes.xml b/indra/newview/skins/default/xui/tr/panel_profile_notes.xml new file mode 100644 index 0000000000..fff75dd685 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notlar ve Gizlilik" name="panel_notes"> + <text name="status_message" value="Bu avatar ile ilgili özel notlar:"/> + <text name="status_message2" value="Bu avatar için şunlara izin ver:"/> + <check_box label="Çevrimiçi olduğumu görme" name="status_check"/> + <check_box label="Beni dünya haritasında bulma" name="map_check"/> + <check_box label="Nesnelerimi düzenleme, silme veya alma" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_pick.xml b/indra/newview/skins/default/xui/tr/panel_profile_pick.xml new file mode 100644 index 0000000000..d42c1eff7f --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (kaydedildikten sonra güncellenir) + </panel.string> + <line_editor name="pick_location"> + Yükleniyor... + </line_editor> + <button label="Işınlanma" name="teleport_btn"/> + <button label="Haritada Göster" name="show_on_map_btn"/> + <button label="Konumu Ayarla" name="set_to_curr_location_btn" tool_tip="Geçerli Konuma Ayarla"/> + <button label="Favoriyi Kaydet" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_picks.xml b/indra/newview/skins/default/xui/tr/panel_profile_picks.xml new file mode 100644 index 0000000000..7222a2fc2e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Favoriler" name="panel_picks"> + <string name="no_picks" value="Favori Yok"/> + <text name="Tell everyone about your favorite places in Second Life."> + Second Life'ta favori yerlerinizi herkese anlatın! + </text> + <button label="Yeni..." name="new_btn"/> + <button label="Sil..." name="delete_btn"/> + <text name="picks_panel_text"> + Yükleniyor... + </text> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml new file mode 100644 index 0000000000..00e81d005e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> + <string name="status_online"> + Şu Anda Çevrimiçi + </string> + <string name="status_offline"> + Şu Anda Çevrimdışı + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="Yok"/> + <string name="no_group_text" value="Yok"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="Geliştirici"/> + <string name="FSSupp" value="Destek"/> + <string name="FSQualityAssurance" value="Böcek bilimci"/> + <string name="FSGW" value="Ağ geçidi"/> + <text name="name_label" value="Ad:"/> + <button label="Ad:" name="set_name" tool_tip="Görünen Adı Ayarla"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(yükleniyor...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="Durum Bilinmiyor"/> + <text name="label" value="Second Life Doğum Tarihi:"/> + <text name="label2" value="Hesap:"/> + <text name="partner_label" value="Ortak:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="Gruplar:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="Gruba Davet Et"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="Hakkında:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="Öğe ver:"/> + <text name="Give inventory" tool_tip="Envanter öğelerini bu kişiye vermek için buraya bırakın."> + Envanter öğesini buraya bırakın. + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="Haritada Bul" label_selected="Haritada Bul" name="show_on_map_btn" tool_tip="Sakini haritada bul"/> + <button label="Öde" label_selected="Öde" name="pay" tool_tip="Sakine para öde"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="Işınlanma Teklif Et" label_selected="Işınlanma Teklif Et" name="teleport" tool_tip="Sakine ışınlanma teklif et"/> + <button label="Anlık İleti" label_selected="Anlık İleti" name="im" tool_tip="Anlık ileti oturumu aç"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="Arkadaş Ekle" label_selected="Arkadaş Ekle" name="add_friend" tool_tip="Sakine arkadaşlık teklif et"/> + <button label="Engelle" name="block" tool_tip="Bu Sakini engelle"/> + <button label="Engellemeyi Kaldır" name="unblock" tool_tip="Bu Sakinin engellemesini kaldır"/> + </layout_panel> + </layout_stack> + <check_box label="Aramada göster" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_web.xml b/indra/newview/skins/default/xui/tr/panel_profile_web.xml new file mode 100644 index 0000000000..265b1fee7e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> + <panel.string name="LoadTime" value="Yükleme Süresi: [TIME] saniye"/> + <line_editor name="url_edit"> + (yükleniyor..) + </line_editor> + <flyout_button label="Yükle" name="load" tool_tip="Bu profil sayfasını tümleşik web tarayıcı ile yükleyin."> + <flyout_button.item label="Görüntüleyici içindeki tarayıcıda aç" name="open_item"/> + <flyout_button.item label="Dış tarayıcıda aç" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="Açılır web profili"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_region_terrain.xml b/indra/newview/skins/default/xui/tr/panel_region_terrain.xml index 3226ee008e..e25047301d 100644 --- a/indra/newview/skins/default/xui/tr/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/tr/panel_region_terrain.xml @@ -10,8 +10,8 @@ <spinner label="Yüzey Yükslt. Limiti" name="terrain_raise_spin"/> <spinner label="Yüzey Alçatma Limiti" name="terrain_lower_spin"/> <text name="detail_texture_text"> - Yüzey Dokuları (512x512, 24 bit .tga dosyalar gerektirir) - </text> + Yüzey Dokuları (1024x1024, 24 bit .tga dosyalar gerektirir) + </text> <text name="height_text_lbl"> 1 (Düşük) </text> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 74a6b3cac3..e709a4c5d6 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -357,6 +357,24 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin. <string name="TestingDisconnect"> Görüntüleyici bağlantısının kesilmesi test ediliyor </string> + <string name="SocialFacebookConnecting"> + Facebook ile bağlantı kuruluyor... + </string> + <string name="SocialFacebookPosting"> + Yayınlanıyor... + </string> + <string name="SocialFacebookDisconnecting"> + Facebook bağlantısı kesiliyor... + </string> + <string name="SocialFacebookErrorConnecting"> + Facebook ile bağlantı kurulurken sorun oluştu + </string> + <string name="SocialFacebookErrorPosting"> + Facebook'ta yayınlarken sorun oluştu + </string> + <string name="SocialFacebookErrorDisconnecting"> + Facebook bağlantısı kesilirken sorun oluştu + </string> <string name="SocialFlickrConnecting"> Flickr bağlantısı kuruluyor... </string> @@ -671,9 +689,6 @@ kartlarına eklenebilir. <string name="GroupNameNone"> (hiçbiri) </string> - <string name="AvalineCaller"> - Avaline Arayanı [ORDER] - </string> <string name="AssetErrorNone"> Hata yok </string> @@ -2576,9 +2591,21 @@ Bu mesaj size gelmeye devam ederse lütfen http://support.secondlife.com adresin <string name="NoPicksClassifiedsText"> Herhangi bir Seçme veya İlan oluşturmadınız. Bir Seçme veya İlan oluşturmak için aşağıdaki Artı düğmesine tıklayın. </string> + <string name="NoPicksText"> + Herhangi bir Favori oluşturmadınız. Bir Favori oluşturmak için Yeni düğmesine tıklayın. + </string> + <string name="NoClassifiedsText"> + Herhangi bir İlan oluşturmadınız. Bir İlan oluşturmak için Yeni düğmesine tıklayın. + </string> <string name="NoAvatarPicksClassifiedsText"> Kullanıcının herhangi bir seçmesi veya ilanı yok </string> + <string name="NoAvatarPicksText"> + Kullanıcının favorisi yok + </string> + <string name="NoAvatarClassifiedsText"> + Kullanıcının ilanı yok + </string> <string name="PicksClassifiedsLoadingText"> Yükleniyor... </string> @@ -4556,6 +4583,9 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun. <string name="share_alert"> Envanterinizden buraya öğeler sürükleyin </string> + <string name="facebook_post_success"> + Facebook'ta yayınladınız. + </string> <string name="flickr_post_success"> Flickr'da yayınladınız. </string> diff --git a/indra/newview/skins/default/xui/zh/floater_picks.xml b/indra/newview/skins/default/xui/zh/floater_picks.xml deleted file mode 100644 index a8bfcd99e3..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="精選地點"/> diff --git a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml index 2b6eac48b3..9213cc212d 100644 --- a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml @@ -6,42 +6,23 @@ <floater.string name="Copy"> 覆製到收納區 </floater.string> - <text name="desc txt"> - 描述: - </text> - <text name="dimensions"> - [WIDTH]像素 x [HEIGHT]像素 - </text> - <text name="aspect_ratio"> - 預覽長寬比 - </text> - <combo_box name="combo_aspect_ratio" tool_tip="以固定長寬比預覽"> - <combo_item name="Unconstrained"> - 不受限 - </combo_item> - <combo_item name="1:1" tool_tip="群組徽章或現實世界小檔案"> - 1:1 - </combo_item> - <combo_item name="4:3" tool_tip="[SECOND_LIFE] 檔案"> - 4:3 - </combo_item> - <combo_item name="10:7" tool_tip="個人廣告和搜索刊登廣告、地標"> - 10:7 - </combo_item> - <combo_item name="3:2" tool_tip="土地資料"> - 3:2 - </combo_item> - <combo_item name="16:10"> - 16:10 - </combo_item> - <combo_item name="16:9" tool_tip="個人檔案精選"> - 16:9 - </combo_item> - <combo_item name="2:1"> - 2:1 - </combo_item> - </combo_box> - <button label="確定" name="Keep"/> - <button label="丟棄" name="Discard"/> - <button label="另存為" name="save_tex_btn"/> + <layout_stack name="preview_stack"> + <layout_panel name="texture_panel"> + <text name="desc txt"> + 描述: + </text> + <text name="dimensions"> + [WIDTH]像素 x [HEIGHT]像素 + </text> + <text name="aspect_ratio"> + 預覽長寬比 + </text> + <combo_box name="combo_aspect_ratio" tool_tip="以固定長寬比預覽"/> + </layout_panel> + <layout_panel name="buttons_panel"> + <button label="確定" name="Keep"/> + <button label="丟棄" name="Discard"/> + <button label="另存為" name="save_tex_btn"/> + </layout_panel> + </layout_stack> </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_profile.xml b/indra/newview/skins/default/xui/zh/floater_profile.xml new file mode 100644 index 0000000000..0f73f527a9 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="簡覽"> + <panel name="panel_profile_view"> + <tab_container name="panel_profile_tabs"> + <panel label="第二人生" name="panel_profile_secondlife"/> + <panel label="網頁" name="panel_profile_web"/> + <panel label="興趣" name="panel_profile_interests"/> + <panel label="精選地點" name="panel_profile_picks"/> + <panel label="分類廣告" name="panel_profile_classifieds"/> + <panel label="真實世界" name="panel_profile_firstlife"/> + <panel label="筆記" name="panel_profile_notes"/> + </tab_container> + <button label="確定" name="ok_btn" tool_tip="儲存變更到個人檔案後關閉"/> + <button label="取消" label_selected="取消" name="cancel_btn"/> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_snapshot.xml b/indra/newview/skins/default/xui/zh/floater_snapshot.xml index 4090248083..6e1a156762 100644 --- a/indra/newview/skins/default/xui/zh/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/zh/floater_snapshot.xml @@ -6,6 +6,9 @@ <string name="postcard_progress_str"> 正在發送電郵 </string> + <string name="facebook_progress_str"> + 發佈到臉書 + </string> <string name="profile_progress_str"> 發佈 </string> @@ -15,6 +18,9 @@ <string name="local_progress_str"> 正在存到電腦 </string> + <string name="facebook_succeeded_str"> + 圖像已上傳 + </string> <string name="profile_succeeded_str"> 圖像已上傳 </string> @@ -27,6 +33,9 @@ <string name="local_succeeded_str"> 成功存入電腦! </string> + <string name="facebook_failed_str"> + 上傳圖像到你的臉書時間線時失敗。 + </string> <string name="profile_failed_str"> 上傳圖像到你的檔案訊息發佈時出錯。 </string> diff --git a/indra/newview/skins/default/xui/zh/menu_name_field.xml b/indra/newview/skins/default/xui/zh/menu_name_field.xml new file mode 100644 index 0000000000..5eaf3461cd --- /dev/null +++ b/indra/newview/skins/default/xui/zh/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> + <menu_item_call label="複製顯示名稱" name="copy_display"/> + <menu_item_call label="複製代理名稱" name="copy_name"/> + <menu_item_call label="複製代理ID" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index cfde824349..4d0f1cb85b 100644 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -2666,6 +2666,9 @@ SHA1 指紋:[MD5_DIGEST] <notification name="SystemMessage"> [MESSAGE] </notification> + <notification name="FacebookConnect"> + [MESSAGE] + </notification> <notification name="FlickrConnect"> [MESSAGE] </notification> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml index b06ece02ad..4d3248db46 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml @@ -46,7 +46,7 @@ <layout_panel name="save_changes_btn_lp"> <button label="[LABEL]" name="save_changes_btn"/> </layout_panel> - <layout_panel name="show_on_map_btn_lp"> + <layout_panel name="cancel_btn_lp"> <button label="取消" name="cancel_btn"/> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml new file mode 100644 index 0000000000..fec4bb572a --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> + <text name="group_name" value="未知"/> + <button name="info_btn" tool_tip="詳情"/> + <button name="profile_btn" tool_tip="察看檔案"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_me.xml b/indra/newview/skins/default/xui/zh/panel_me.xml deleted file mode 100644 index aad1348e46..0000000000 --- a/indra/newview/skins/default/xui/zh/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="我的個人檔案" name="panel_me"> - <panel label="我的精選地點" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_people.xml b/indra/newview/skins/default/xui/zh/panel_people.xml index b0e60218cf..b95dd96026 100644 --- a/indra/newview/skins/default/xui/zh/panel_people.xml +++ b/indra/newview/skins/default/xui/zh/panel_people.xml @@ -40,6 +40,7 @@ <accordion name="friends_accordion"> <accordion_tab name="tab_online" title="上線"/> <accordion_tab name="tab_all" title="全部"/> + <accordion_tab name="tab_suggested_friends" title="你可能想要加為好友的人"/> </accordion> </panel> <panel label="群組" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_classified.xml b/indra/newview/skins/default/xui/zh/panel_profile_classified.xml new file mode 100644 index 0000000000..4eee4e8855 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> + <panel.string name="type_mature"> + 適度成人 + </panel.string> + <panel.string name="type_pg"> + 一般普級內容 + </panel.string> + <panel.string name="l$_price"> + L$[PRICE] + </panel.string> + <panel.string name="click_through_text_fmt"> + [TELEPORT] 瞬間傳送,[MAP] 地圖,[PROFILE] 檔案 + </panel.string> + <panel.string name="date_fmt"> + [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] + </panel.string> + <panel.string name="auto_renew_on"> + 已啟用 + </panel.string> + <panel.string name="auto_renew_off"> + 已停用 + </panel.string> + <panel.string name="location_notice"> + (儲存後將會更新) + </panel.string> + <string name="publish_label"> + 發布 + </string> + <string name="save_label"> + 儲存 + </string> + <scroll_container name="profile_scroll"> + <panel name="info_scroll_content_panel"> + <icon label="" name="edit_icon" tool_tip="點按以選擇圖像"/> + <layout_stack name="info_panel"> + <layout_panel name="main_info_panel"> + <text_editor name="classified_name"> + [name] + </text_editor> + <text name="classified_location_label" value="位置:"/> + <text_editor name="classified_location" value="[loading...]"/> + <text name="content_type_label" value="內容類型:"/> + <text_editor name="content_type" value="[content type]"/> + <text name="category_label" value="分類:"/> + <text_editor name="category" value="[category]"/> + <text name="creation_date_label" value="建立日期:"/> + <text_editor name="creation_date" tool_tip="建立日期" value="[date]"/> + <text name="price_for_listing_label" value="刊登費:"/> + <text_editor name="price_for_listing" tool_tip="刊登費。"> + [PRICE] + </text_editor> + </layout_panel> + <layout_panel name="clickthrough_layout_panel"> + <text name="click_through_label" value="點按狀況:"/> + <text_editor name="click_through_text" tool_tip="點按資料" value="[clicks]"/> + </layout_panel> + <layout_panel name="auto_renew_layout_panel"> + <text name="auto_renew_label" value="自動續訂:"/> + <text name="auto_renew" value="已啟用"/> + </layout_panel> + <layout_panel name="descr_layout_panel"> + <text name="classified_desc_label" value="描述:"/> + <text_editor name="classified_desc" value="[description]"/> + </layout_panel> + </layout_stack> + <panel name="edit_panel"> + <text name="Name:"> + 標題: + </text> + <text name="description_label"> + 描述: + </text> + <text name="location_label"> + 位置: + </text> + <text name="classified_location_edit"> + 載入中... + </text> + <button label="設定為目前位置" name="set_to_curr_location_btn"/> + <text name="category_label" value="分類:"/> + <text name="content_type_label" value="內容類型:"/> + <icons_combo_box label="一般普級內容" name="content_type_edit"> + <icons_combo_box.item label="適度成人內容" name="mature_ci" value="適度成人"/> + <icons_combo_box.item label="一般普級內容" name="pg_ci" value="一般普級"/> + </icons_combo_box> + <check_box label="每星期自動續訂" name="auto_renew_edit"/> + <text name="price_for_listing_edit_label" value="刊登費:"/> + <spinner label="L$" name="price_for_listing_edit" tool_tip="刊登費。" value="50"/> + </panel> + </panel> + </scroll_container> + <layout_stack name="edit_btns_pnl"> + <layout_panel name="teleport_btn_lp"> + <button label="瞬間傳送" name="teleport_btn"/> + </layout_panel> + <layout_panel name="map_btn_lp"> + <button label="地圖" name="show_on_map_btn"/> + </layout_panel> + <layout_panel name="edit_btn_lp"> + <button label="編輯" name="edit_btn"/> + </layout_panel> + <layout_panel name="save_btn_lp"> + <button label="[LABEL]" name="save_changes_btn"/> + </layout_panel> + <layout_panel name="cancel_btn_lp"> + <button label="取消" name="cancel_btn"/> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml new file mode 100644 index 0000000000..89b5cdf641 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="分類廣告" name="panel_profile_classifieds"> + <string name="no_classifieds" value="禁止個人廣告"/> + <button label="新增…" name="new_btn"/> + <button label="刪除…" name="delete_btn"/> + <text name="classifieds_panel_text"> + 載入中… + </text> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml new file mode 100644 index 0000000000..9370661d7f --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="簡覽" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_interests.xml b/indra/newview/skins/default/xui/zh/panel_profile_interests.xml new file mode 100644 index 0000000000..150f3cca4f --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="興趣" name="panel_profile_interests"> + <text name="I Want To:"> + 我想要: + </text> + <check_box label="建造" name="chk0"/> + <check_box label="探索" name="chk1"/> + <check_box label="見面" name="chk2"/> + <check_box label="受雇" name="chk6"/> + <check_box label="群組" name="chk3"/> + <check_box label="購買" name="chk4"/> + <check_box label="出售" name="chk5"/> + <check_box label="招人" name="chk7"/> + <line_editor name="want_to_edit"> + (載入中...) + </line_editor> + <text name="Skills:"> + 技能: + </text> + <check_box label="材質" name="schk0"/> + <check_box label="架構" name="schk1"/> + <check_box label="建模" name="schk3"/> + <check_box label="計畫活動" name="schk2"/> + <check_box label="建腳本" name="schk4"/> + <check_box label="定製角色" name="schk5"/> + <line_editor name="skills_edit"> + (載入中...) + </line_editor> + <text name="Languages:"> + 語言: + </text> + <line_editor name="languages_edit"> + (載入中...) + </line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_notes.xml b/indra/newview/skins/default/xui/zh/panel_profile_notes.xml new file mode 100644 index 0000000000..17e1a997da --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="筆記和隱私" name="panel_notes"> + <text name="status_message" value="關於這化身的私人筆記:"/> + <text name="status_message2" value="允許這個化身:"/> + <check_box label="看見我何時上線" name="status_check"/> + <check_box label="在世界地圖上找到我" name="map_check"/> + <check_box label="邊輯,刪除或取下我的物件" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_pick.xml b/indra/newview/skins/default/xui/zh/panel_profile_pick.xml new file mode 100644 index 0000000000..5f8d6a2ba5 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> + <panel.string name="location_notice"> + (儲存後將會更新) + </panel.string> + <line_editor name="pick_location"> + 載入中… + </line_editor> + <button label="瞬間傳送" name="teleport_btn"/> + <button label="顯示在地圖上" name="show_on_map_btn"/> + <button label="設定位置" name="set_to_curr_location_btn" tool_tip="設定為目前位置"/> + <button label="儲存精選地點" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_picks.xml b/indra/newview/skins/default/xui/zh/panel_profile_picks.xml new file mode 100644 index 0000000000..8f189d1308 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="精選地點" name="panel_picks"> + <string name="no_picks" value="無精選地點"/> + <text name="Tell everyone about your favorite places in Second Life."> + 告訴大家你在Second Life中最愛的去處。 + </text> + <button label="新增…" name="new_btn"/> + <button label="刪除…" name="delete_btn"/> + <text name="picks_panel_text"> + 載入中… + </text> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml new file mode 100644 index 0000000000..da4aafce55 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="簡覽" name="panel_profile"> + <string name="status_online"> + 目前在線 + </string> + <string name="status_offline"> + 目前離線 + </string> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] +[PAYMENTINFO] + </string> + <string name="payment_update_link_url"> + http://www.secondlife.com/account/billing.php?lang=en + </string> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=en + </string> + <string name="my_account_link_url" value="http://secondlife.com/account"/> + <string name="no_partner_text" value="無"/> + <string name="no_group_text" value="無"/> + <string name="RegisterDateFormat"> + [REG_DATE] + </string> + <string name="name_text_args"> + [NAME] + </string> + <string name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <string name="FSDev" value="開發者"/> + <string name="FSSupp" value="支援"/> + <string name="FSQualityAssurance" value="除錯獵人"/> + <string name="FSGW" value="網關"/> + <text name="name_label" value="名稱:"/> + <button label="名稱:" name="set_name" tool_tip="設定顯示名稱"/> + <panel name="name_holder"> + <text_editor name="complete_name" value="(載入中...)"/> + </panel> + <layout_stack name="imagepositioner"> + <layout_panel name="label_stack"> + <text name="status" value="狀態不明"/> + <text name="label" value="Second Life生日:"/> + <text name="label2" value="帳戶:"/> + <text name="partner_label" value="伴侶:"/> + </layout_panel> + </layout_stack> + <text name="Groups:" value="群組:"/> + <button label="+" label_selected="+" name="group_invite" tool_tip="邀請加入群組"/> + <layout_stack name="aboutpositioner"> + <layout_panel name="about_stack"> + <text name="About:" value="關於:"/> + </layout_panel> + <layout_panel name="give_stack"> + <text name="Give item:" value="贈與物品:"/> + <text name="Give inventory" tool_tip="把收納區物品放到這裡,送給此人。"> + 把收納區物品放到這裡。 + </text> + </layout_panel> + </layout_stack> + <layout_stack name="buttonstack"> + <layout_panel name="left_buttonstack"> + <button label="在地圖上查找" label_selected="在地圖上查找" name="show_on_map_btn" tool_tip="在地圖上找出這個居民"/> + <button label="支付" label_selected="支付" name="pay" tool_tip="付款給這個居民"/> + </layout_panel> + <layout_panel name="middle_buttonstack"> + <button label="發出瞬間傳送邀請" label_selected="發出瞬間傳送邀請" name="teleport" tool_tip="向這個居民發出瞬間傳送邀請"/> + <button label="即時訊息" label_selected="即時訊息" name="im" tool_tip="開啟即時訊息會話"/> + </layout_panel> + <layout_panel name="right_buttonstack"> + <button label="加為朋友" label_selected="加為朋友" name="add_friend" tool_tip="向這個居民發出交友邀請"/> + <button label="封鎖" name="block" tool_tip="封鎖這位居民"/> + <button label="解除封鎖" name="unblock" tool_tip="不再封鎖這位居民"/> + </layout_panel> + </layout_stack> + <check_box label="在搜尋結果中顯示" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_web.xml b/indra/newview/skins/default/xui/zh/panel_profile_web.xml new file mode 100644 index 0000000000..566651dceb --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="網頁" name="panel_profile_web"> + <panel.string name="LoadTime" value="載入時間:[TIME]秒"/> + <line_editor name="url_edit"> + (載入中…) + </line_editor> + <flyout_button label="載入" name="load" tool_tip="用內嵌瀏覽器載入此個人檔案頁面。"> + <flyout_button.item label="開啓内部瀏覽器" name="open_item"/> + <flyout_button.item label="開啓外部瀏覽器" name="home_item"/> + </flyout_button> + <button name="web_profile_popout_btn" tool_tip="彈出式個人檔案網頁"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_region_terrain.xml b/indra/newview/skins/default/xui/zh/panel_region_terrain.xml index 85e759e445..81bce46876 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_terrain.xml @@ -10,7 +10,7 @@ <spinner label="地形提升限制" name="terrain_raise_spin"/> <spinner label="地形降低限制" name="terrain_lower_spin"/> <text name="detail_texture_text"> - 地形材質(須 512x512,24 位元 .tga 檔格式) + 地形材質(須 1024x1024,24 位元 .tga 檔格式) </text> <text name="height_text_lbl"> 1(低) diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index a8d5fd90bb..bdb16c9bf1 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -353,6 +353,24 @@ http://secondlife.com/viewer-access-faq <string name="TestingDisconnect"> 測試瀏覽器斷線 </string> + <string name="SocialFacebookConnecting"> + 連通臉書中… + </string> + <string name="SocialFacebookPosting"> + 發佈中… + </string> + <string name="SocialFacebookDisconnecting"> + 臉書連通中斷中… + </string> + <string name="SocialFacebookErrorConnecting"> + 連通臉書時出問題 + </string> + <string name="SocialFacebookErrorPosting"> + 發佈到臉書時出問題 + </string> + <string name="SocialFacebookErrorDisconnecting"> + 試圖中斷臉書連通時出問題 + </string> <string name="SocialFlickrConnecting"> 連通 Flickr 中… </string> @@ -667,9 +685,6 @@ http://secondlife.com/viewer-access-faq <string name="GroupNameNone"> (無) </string> - <string name="AvalineCaller"> - Avaline 通話者 [ORDER] - </string> <string name="AssetErrorNone"> 無錯誤 </string> @@ -2569,9 +2584,21 @@ http://secondlife.com/support 求助解決問題。 <string name="NoPicksClassifiedsText"> 你尚未建立任何精選地點或個人廣告。 點按下面的 + 按鈕建立精選地點或個人廣告。 </string> + <string name="NoPicksText"> + 你尚未建立任何精選地點。 點按「新增」按鈕建立精選地點。 + </string> + <string name="NoClassifiedsText"> + 你尚未建立任何分類廣告。 點按「新增」按鈕建立分類廣告。 + </string> <string name="NoAvatarPicksClassifiedsText"> 使用者無精選地點或個人廣告 </string> + <string name="NoAvatarPicksText"> + 使用者沒有精選地點 + </string> + <string name="NoAvatarClassifiedsText"> + 使用者沒有分類廣告 + </string> <string name="PicksClassifiedsLoadingText"> 載入中... </string> @@ -4549,6 +4576,9 @@ http://secondlife.com/support 求助解決問題。 <string name="share_alert"> 將收納區物品拖曳到這裡 </string> + <string name="facebook_post_success"> + 成功發佈到臉書。 + </string> <string name="flickr_post_success"> 成功發佈到 Flickr。 </string> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index de5ac5ed3d..59eb18b734 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -568,6 +568,7 @@ class WindowsManifest(ViewerManifest): self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") + self.path("cube.dae") with self.prefix(src=pkgdir): self.path("ca-bundle.crt") @@ -954,6 +955,7 @@ class DarwinManifest(ViewerManifest): self.path("licenses-mac.txt", dst="licenses.txt") self.path("featuretable_mac.txt") + self.path("cube.dae") self.path("SecondLife.nib") with self.prefix(src=pkgdir,dst=""): @@ -1427,6 +1429,7 @@ class LinuxManifest(ViewerManifest): print("Skipping llcommon.so (assuming llcommon was linked statically)") self.path("featuretable_linux.txt") + self.path("cube.dae") with self.prefix(src=pkgdir): self.path("ca-bundle.crt") |